Search code examples
optimizationvisual-c++visual-studio-2005compiler-optimization

Some example of __assume leading to a faster code other than "no default" in switch?


The documentation for __assume says "The most common use of __assume is with the default case of a switch statement, as shown in the following example.".

  • Is there any other case where __assume can lead to more efficient (or even different) code?
  • When inside of an if / else, isn't the compiler automatically "assuming" what is already known because of the if condition?

I was unable to find any non-trivial examples that show any of above - I hope someone else could.


Solution

  • Consider the following code, compiled with the /Ox switch:

    if (1) {
      printf("live code\n");
    } else {
      printf("dead code\n");
    }
    

    The optimizer will optimize away the else. Now consider:

    int x = 1;
    if (x == 1) {
      printf("live code\n");
    } else {
      printf("dead code\n");
    }
    

    The optimizer will once again optimize away the else. Also consider:

    int x = 1;
    __assume(x != 1);
    if (x == 1) {
      printf("live code\n");
    } else {
      printf("dead code\n");
    }
    

    The optimizer will optimize away the if this time -- incorrectly so.

    To test, build a test program in Release mode (with the /Ox and /Zi options) and look at the generated assembly (Alt+8 in Visual Studio.)

    Now consider the above if/else condition being tested in an inline method. In certain contexts, the programmer may know that the inline method is called with a particular value and the optimizer may not have realized this fact. Using __assume at the caller level in the manner illustrated above, just before the inlined method is called, can theoretically help the optimizer.

    From Optimization Best Practices (quote from older version):

    __assume has been in Visual C++ for multiple releases, but it has become much more usable in Visual C++ 2005. With __assume, a developer can tell the compiler to make assumptions about the value of some variable.

    For example __assume(a < 5); tells the optimizer that at that line of code the variable a is less than 5. Again this is a promise to the compiler. If a is actually 6 at this point in the program then the behavior of the program after the compiler has optimized may not be what you would expect. __assume is most useful prior to switch statements and/or conditional expressions.

    There are some limitations to __assume. First, like __restrict, it is only a suggestion, so the compiler is free to ignore it. Also, __assume currently works only with variable inequalities against constants. It does not propagate symbolic inequalities, for example, assume(a < b).