##### cppreference.com

##### Search

Create account

##### Namespaces

- Page
- Discussion

##### Variants

##### Views

- View
- Edit
- History

##### Actions

# The as-if rule

From cppreference.com
< cpp‎ | language

Allows any and all code transformations that do not change the observable behavior of the program

### [edit] Explanation

The C++ compiler is permitted to perform any changes to the program as long as the following remains true:

- Accesses (reads and writes) to the volatile objects occur in the same order as written.

- At program termination, the data written to all files is exactly as if the program was executed as written.

- All input and output operations occur in the same order and with the same content as if the program was executed as written.

### [edit] Notes

Because the compiler is (usually) unable to analyze the code of an external library to determine whether it does or does not perform I/O or volatile access, third-party library calls also aren't affected by optimization. However, standard library calls may be replaced by other calls, eliminated, or added to the program during optimization.

Programs with undefined behavior, e.g. due to access to an array out of bounds, modification of a const object, evaluation order violations, etc, are free from the as-if rule: they often change observable behavior when recompiled with different optimization settings. For example, if a test for signed integer overflow relies on the result of that overflow, e.g. if(n+1 < n) abort();, it is removed entirely by some compilers because signed overflow is undefined behavior and the optimizer is free to assume it never happens and the test is redundant.

Copy elision is the only well-defined exception from the as-if rule.

### [edit] Example

Run this code

    int& preinc(int& n) { return ++n; }
    int add(int n, int m) { return n+m; }

    // volatile input to prevent constant folding
    volatile int input = 7;

    // volatile output to make the result a visible side-effect
    volatile int result;

    int main()
    {
        int n = input;
    // using built-in operators would invoke undefined behavior
    //    int m = ++n + ++n;
    // but using functions makes sure the code executes as-if
    // the functions were not overlapped
        int m = add(preinc(n), preinc(n));
        result = m;
    }

Output:

    # full code of the main() function as produced by the GCC compiler
    # x86 (Intel) platform:
            movl    input(%rip), %eax   # eax = input
            leal    3(%rax,%rax), %eax  # eax = 3 + eax + eax
            movl    %eax, result(%rip)  # result = eax
            xorl    %eax, %eax          # eax = 0 (the return value of main())
            ret

    # PowerPC (IBM) platform:
            lwz 9,LC..1(2)
            li 3,0          # r3 = 0 (the return value of main())
            lwz 11,0(9)     # r11 = input;
            slwi 11,11,1    # r11 = r11 << 1;
            addi 0,11,3     # r0 = r11 + 3;
            stw 0,4(9)      # result = r0;
            blr

    # Sparc (Sun) platform:
            sethi   %hi(result), %g2
            sethi   %hi(input), %g1
            mov     0, %o0                 # o0 = 0 (the return value of main)
            ld      [%g1+%lo(input)], %g1  # g1 = input
            add     %g1, %g1, %g1          # g1 = g1 + g1
            add     %g1, 3, %g1            # g1 = 3 + g1
            st      %g1, [%g2+%lo(result)] # result = g1
            jmp     %o7+8
            nop

    # in all cases, the side effects of preinc() were eliminated, and the
    # entire main() function was reduced to the equivalent of result = 2*input + 3;

### [edit] See also

- copy elision

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/language/as_if&oldid=44317"