-Of and-Onf: Create Sub-Functions with Common Code

Group

OPTIMIZATIONS

Scope

Function

Syntax
  -O[nf|f]
  
  
Arguments

nf: Disable

f: Enable

Default

-Of default or with -Os, -Onf with -Ot

Defines

None

Pragmas

None

Description

This option performs the reverse of inlining. It detects common code parts in the generated code. The Compiler moves the common code to a different place and replaces all occurrences with a JSR to the moved code. At the end of the common code, the Compiler inserts an RTS instruction. The Compiler increases all SP uses by an address size. This optimization takes care of stack allocation, control flow, and functions having arguments on the stack.

Note: Inline assembler code is never treated as common code.
Example

Consider this function:

  void f(int);

  
  void g(void);

  
  void h(void);

  
  void main(void) {

  
    f(1);  f(2);  f(3);

  
    h();

  
    f(1);  f(2);   f(3);

  
    g();

  
    f(1);  f(2);

  
  }

  

The compiler first detects that "f(1); f(2); f(3);" occurs twice and places this code separately. Then the Compiler replaces the two code patterns by a call to the moved code.

The non-C pseudo code (C does not support local functions) in the following code presents a similar scenario:

  void main(void) {

  
    void tmp0(void) {

  
      f(1);  f(2);  f(3);

  
    }

  
    tmp0();

  
    h();

  
    tmp0();

  
    g();

  
    f(1);  f(2);

  
  }

  

In a next step, the compiler detects that the code "f(1); f(2);" occurs twice. The Compiler generates a second local function:

  void main(void) {

  
    void tmp1(void) {

  
      f(1);  f(2);

  
    }

  
    void tmp0(void) {

  
      tmp1();  f(3);

  
    }

  
    tmp0();

  
    h();

  
    tmp0();

  
    g();

  
    tmp1();

  
  }

  

main () calls tmp1 once directly and once indirectly using tmp0. These two call chains use a different amount of stack. Because of this situation, it is not always possible to generate correct debug information. For the local function tmp1, the compiler cannot state both possible SP values, and therefore only states one of them. While debugging the other state, the debugger declares local variables and the call chain invalid.

Tip: Switch off this optimization to debug your application. The common code complicates the control flow. Also, the debugger cannot distinguish between two distinct usages of the same code. Setting a breakpoint in common code stops the application and every use of it. It also stops the local variables and the call frame if not displayed correctly, as explained above.
Tip: Switch off this optimization to get faster code. For code density, there are only a few cases that produce slower code. This situation only occurs when other optimizations (such as branch tail merging or peepholing) do not find a pattern.