Fold Expressions
Expression folding optimizes code to minimize the computation of intermediate results at block outputs and the storage of such results in temporary buffers or variables. When expression folding is on, the code generator collapses (folds) block computations into a single expression, instead of generating separate code statements and storage declarations for each block in a model. Most Simulink® blocks support expression folding.
Expression folding improves the efficiency of generated code, frequently achieving results that compare favorably to hand-optimized code. In many cases, entire groups of model computations fold into a single, highly optimized line of code.
Example Model
model = 'FoldBlockComputations';
open_system(model);
Generate Code
Expression folding is available only when the Signal storage reuse parameter is set to on because expression folding operates only on expressions involving local variables. The Signal storage reuse and Eliminate superfluous local variables (expression folding) parameters are on by default. Clear the Eliminate superfluous local variables (expression folding) parameter or enter the following command in the MATLAB® Command Window to turn the parameter off:
set_param(model, 'ExpressionFolding','off');
Build the model.
slbuild(model)
### Starting build procedure for: FoldBlockComputations ### Successful completion of build procedure for: FoldBlockComputations Build Summary Top model targets: Model Build Reason Status Build Duration ======================================================================================================================== FoldBlockComputations Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 13.365s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 14.304s
With expression folding off, in the FoldBlockComputations.c
file, there are separate code statements before and in the Switch block operation.
cfile = fullfile('FoldBlockComputations_grt_rtw','FoldBlockComputations.c'); coder.example.extractLines(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */ void FoldBlockComputations_step(void) { real_T rtb_Gain; boolean_T rtb_LogicalOperator; boolean_T rtb_RelationalOperator; /* RelationalOperator: '<Root>/Relational Operator1' incorporates: * Constant: '<Root>/Constant' * Inport: '<Root>/In2' */ rtb_LogicalOperator = (FoldBlockComputations_P.UPPER >= FoldBlockComputations_U.In2); /* RelationalOperator: '<Root>/Relational Operator' incorporates: * Constant: '<Root>/Constant1' * Inport: '<Root>/In2' */ rtb_RelationalOperator = (FoldBlockComputations_U.In2 <= FoldBlockComputations_P.LOWER); /* Logic: '<Root>/Logical Operator' */ rtb_LogicalOperator = (rtb_LogicalOperator || rtb_RelationalOperator); /* Switch: '<Root>/Switch' */ if (rtb_LogicalOperator) { /* Gain: '<Root>/Gain' incorporates: * Inport: '<Root>/In1' */ rtb_Gain = 2.0 * FoldBlockComputations_U.In1; /* Lookup_n-D: '<Root>/Look-Up Table' incorporates: * Gain: '<Root>/Gain' */ rtb_Gain = look1_binlx(rtb_Gain, FoldBlockComputations_P.T1Break, FoldBlockComputations_P.T1Data, 10U); } else { /* Lookup_n-D: '<Root>/Look-Up Table (2-D)' incorporates: * Inport: '<Root>/In3' * Inport: '<Root>/In4' */ rtb_Gain = look2_binlx(FoldBlockComputations_U.In3, FoldBlockComputations_U.In4, FoldBlockComputations_P.T2Break, FoldBlockComputations_P.T2Break, FoldBlockComputations_P.T2Data, rtCP_LookUpTable2D_maxIndex, 3U); } /* End of Switch: '<Root>/Switch' */ /* Outport: '<Root>/Out1' */ FoldBlockComputations_Y.Out1 = rtb_Gain; }
Generate Code with Optimization
Enter the following command to turn expression folding on:
set_param(model, 'ExpressionFolding','on');
Build the model.
slbuild(model);
### Starting build procedure for: FoldBlockComputations ### Successful completion of build procedure for: FoldBlockComputations Build Summary Top model targets: Model Build Reason Status Build Duration ==================================================================================================== FoldBlockComputations Generated code was out of date. Code generated and compiled. 0h 0m 8.5528s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 9.5178s
The following is a portion of FoldBlockComputations.c
. In the optimized code, the code generator folds all computations into the Switch block operation.
coder.example.extractLines(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */ void FoldBlockComputations_step(void) { /* Switch: '<Root>/Switch' incorporates: * Constant: '<Root>/Constant' * Constant: '<Root>/Constant1' * Inport: '<Root>/In2' * Logic: '<Root>/Logical Operator' * RelationalOperator: '<Root>/Relational Operator' * RelationalOperator: '<Root>/Relational Operator1' */ if ((FoldBlockComputations_P.UPPER >= FoldBlockComputations_U.In2) || (FoldBlockComputations_U.In2 <= FoldBlockComputations_P.LOWER)) { /* Outport: '<Root>/Out1' incorporates: * Gain: '<Root>/Gain' * Inport: '<Root>/In1' * Lookup_n-D: '<Root>/Look-Up Table' */ FoldBlockComputations_Y.Out1 = look1_binlx(2.0 * FoldBlockComputations_U.In1, FoldBlockComputations_P.T1Break, FoldBlockComputations_P.T1Data, 10U); } else { /* Outport: '<Root>/Out1' incorporates: * Inport: '<Root>/In3' * Inport: '<Root>/In4' * Lookup_n-D: '<Root>/Look-Up Table (2-D)' */ FoldBlockComputations_Y.Out1 = look2_binlx(FoldBlockComputations_U.In3, FoldBlockComputations_U.In4, FoldBlockComputations_P.T2Break, FoldBlockComputations_P.T2Break, FoldBlockComputations_P.T2Data, rtCP_LookUpTable2D_maxIndex, 3U); } /* End of Switch: '<Root>/Switch' */ }
Close the model and code generation report.
bdclose(model)