Documentation

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 = 'rtwdemo_slexprfold';
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');

Create a temporary folder for the build and inspection process.

currentDir = pwd;
[~,cgDir] = rtwdemodir();

Build the model.

rtwbuild(model)
### Starting build procedure for model: rtwdemo_slexprfold
### Successful completion of build procedure for model: rtwdemo_slexprfold

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)
{
  boolean_T rtb_LogicalOperator;
  boolean_T rtb_RelationalOperator;
  real_T rtb_Gain;

  /* 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' */
    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 (2-D)' incorporates:
     *  Inport: '<Root>/In3'
     *  Inport: '<Root>/In4'
     */
    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' */
}

Generate Code with Optimization

Enter the following command to turn expression folding on:

set_param(model, 'ExpressionFolding','on');

Build the model.

rtwbuild(model);
### Starting build procedure for model: rtwdemo_slexprfold
### Successful completion of build procedure for model: rtwdemo_slexprfold

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.

Was this topic helpful?