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.
model = 'rtwdemo_slexprfold';
open_system(model);
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');
Create a temporary folder for the build and inspection process.
currentDir = pwd; [~,cgDir] = rtwdemodir();
Build the model.
rtwbuild(model)
### Starting build procedure for: rtwdemo_slexprfold ### Successful completion of build procedure for: rtwdemo_slexprfold Build Summary Top model targets built: Model Action Rebuild Reason =================================================================================================== rtwdemo_slexprfold Code generated and compiled Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 6.7663s
With expression folding off, in the rtwdemo_slexprfold.c
file, there are separate code statements before and in the Switch block operation.
cfile = fullfile(cgDir,'rtwdemo_slexprfold_grt_rtw','rtwdemo_slexprfold.c'); rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */ void rtwdemo_slexprfold_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 = (rtwdemo_slexprfold_P.UPPER >= rtwdemo_slexprfold_U.In2); /* RelationalOperator: '<Root>/Relational Operator' incorporates: * Constant: '<Root>/Constant1' * Inport: '<Root>/In2' */ rtb_RelationalOperator = (rtwdemo_slexprfold_U.In2 <= rtwdemo_slexprfold_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 * rtwdemo_slexprfold_U.In1; /* Lookup_n-D: '<Root>/Look-Up Table' incorporates: * Gain: '<Root>/Gain' */ rtwdemo_slexprfold_Y.Out1 = look1_binlx(rtb_Gain, rtwdemo_slexprfold_P.T1Break, rtwdemo_slexprfold_P.T1Data, 10U); } else { /* Lookup_n-D: '<Root>/Look-Up Table' incorporates: * Inport: '<Root>/In3' * Inport: '<Root>/In4' * Lookup_n-D: '<Root>/Look-Up Table (2-D)' */ rtwdemo_slexprfold_Y.Out1 = look2_binlx(rtwdemo_slexprfold_U.In3, rtwdemo_slexprfold_U.In4, rtwdemo_slexprfold_P.T2Break, rtwdemo_slexprfold_P.T2Break, rtwdemo_slexprfold_P.T2Data, rtCP_LookUpTable2D_maxIndex, 3U); } /* End of Switch: '<Root>/Switch' */ }
Enter the following command to turn expression folding on:
set_param(model, 'ExpressionFolding','on');
Build the model.
rtwbuild(model);
### Starting build procedure for: rtwdemo_slexprfold ### Successful completion of build procedure for: rtwdemo_slexprfold Build Summary Top model targets built: Model Action Rebuild Reason ================================================================================== rtwdemo_slexprfold Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 5.5165s
The following is a portion of rtwdemo_slexprfold.c. In the optimized code, the code generator folds all computations into the Switch block operation.
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */ void rtwdemo_slexprfold_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 ((rtwdemo_slexprfold_P.UPPER >= rtwdemo_slexprfold_U.In2) || (rtwdemo_slexprfold_U.In2 <= rtwdemo_slexprfold_P.LOWER)) { /* Outport: '<Root>/Out1' incorporates: * Gain: '<Root>/Gain' * Inport: '<Root>/In1' * Lookup_n-D: '<Root>/Look-Up Table' */ rtwdemo_slexprfold_Y.Out1 = look1_binlx(2.0 * rtwdemo_slexprfold_U.In1, rtwdemo_slexprfold_P.T1Break, rtwdemo_slexprfold_P.T1Data, 10U); } else { /* Outport: '<Root>/Out1' incorporates: * Inport: '<Root>/In3' * Inport: '<Root>/In4' * Lookup_n-D: '<Root>/Look-Up Table (2-D)' */ rtwdemo_slexprfold_Y.Out1 = look2_binlx(rtwdemo_slexprfold_U.In3, rtwdemo_slexprfold_U.In4, rtwdemo_slexprfold_P.T2Break, rtwdemo_slexprfold_P.T2Break, rtwdemo_slexprfold_P.T2Data, rtCP_LookUpTable2D_maxIndex, 3U); } /* End of Switch: '<Root>/Switch' */ }
Close the model and code generation report.
bdclose(model) rtwdemoclean; cd(currentDir)
For an example in which code expressions are expression folded between Simulink and Stateflow, open this model rtwdemo_sfexprfold
.