Optimize Generated Code by Consolidating Redundant If-Else Statements

This example shows how to optimize generated code by combining if-else statements that share the same condition. This optimization:

  • Improves control flow.

  • Reduces code size.

  • Reduces RAM consumption.

  • Increases execution speed.

Example

The model rtwdemo_controlflow_opt contains three Switch blocks. The Constant block provides the control input to the Switch blocks. The variable named Cond determines the value of the Constant block.

model = 'rtwdemo_controlflow_opt';
open_system(model);

Generate Code

Create a temporary folder for the build and inspection process.

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

Build the model.

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

Build Summary

Top model targets built:

Model                    Action                       Rebuild Reason                                    
========================================================================================================
rtwdemo_controlflow_opt  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 12.571s

These lines of rtwdemo_controlflow_opt.c code show that in the generated code, two if-else statements and one else-if statement represent the three Switch blocks.

cfile = fullfile(cgDir,'rtwdemo_controlflow_opt_ert_rtw',...
    'rtwdemo_controlflow_opt.c');
rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void rtwdemo_controlflow_opt_step(void)
{
  /* Switch: '<Root>/Switch3' incorporates:
   *  Constant: '<Root>/Const'
   *  Switch: '<Root>/Switch2'
   */
  if (Cond) {
    /* Switch: '<Root>/Switch1' */
    if (Cond) {
      /* Outport: '<Root>/Out1' incorporates:
       *  Inport: '<Root>/In1'
       */
      rtY.Out1 = rtU.In1;
    } else {
      /* Outport: '<Root>/Out1' incorporates:
       *  Inport: '<Root>/In2'
       */
      rtY.Out1 = rtU.In2;
    }

    /* End of Switch: '<Root>/Switch1' */
  } else if (Cond) {
    /* Switch: '<Root>/Switch2' incorporates:
     *  Inport: '<Root>/In1'
     *  Outport: '<Root>/Out1'
     */
    rtY.Out1 = rtU.In1;
  } else {
    /* Outport: '<Root>/Out1' incorporates:
     *  Inport: '<Root>/In2'
     */
    rtY.Out1 = rtU.In2;
  }

  /* End of Switch: '<Root>/Switch3' */
}

Enable Optimization

  1. Open the Configuration Parameters dialog box.

  2. On the Code generation-> Code Style pane, clear Preserve condition expression in if statement. This parameter is on by default.

Alternatively, use the command-line API to turn off the parameter:

set_param(model, 'PreserveIfCondition', 'off');

Generate Code with Optimization

In the optimized code, the code generator consolidates the two if-else statements and one else-if statement into one if-else statement. The code generator consolidates these statements because they all share the same condition. There is no intervening code that affects the outcomes of these statements.

Build the model.

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

Build Summary

Top model targets built:

Model                    Action                       Rebuild Reason                   
=======================================================================================
rtwdemo_controlflow_opt  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 10.368s

Here is the rtwdemo_controlflow_opt.c optimized code.

rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);
/* Model step function */
void rtwdemo_controlflow_opt_step(void)
{
  /* Switch: '<Root>/Switch1' incorporates:
   *  Constant: '<Root>/Const'
   *  Switch: '<Root>/Switch3'
   */
  if (Cond) {
    /* Outport: '<Root>/Out1' incorporates:
     *  Inport: '<Root>/In1'
     */
    rtY.Out1 = rtU.In1;
  } else {
    /* Outport: '<Root>/Out1' incorporates:
     *  Inport: '<Root>/In2'
     */
    rtY.Out1 = rtU.In2;
  }

  /* End of Switch: '<Root>/Switch1' */
}

Close the model and clean up.

bdclose(model)
rtwdemoclean;
cd(currentDir)

See Also

Related Topics