Consider the following code:
if (1) {
printf("live code\n");
} else {
printf("dead code\n");
}
The optimizer will optimize away the else
. Now consider:
__assume(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:
x = 99;
__assume(x == 1);
if (x == 1) {
printf("live code\n");
} else {
printf("dead code\n");
}
The optimizer will once again optimize away the else
-- incorrectly so.
To test, build a test program in Release mode (with the /Og
option) 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 porgrammer 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:
__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).
Cheers,
V.