Search code examples
cif-statementcompiler-optimizationvolatileevaluation

if statement, function evaluation & compiler optimization


Just a quick question, to save me from testing things (although I really should test things to be absolutely certain):

Given the following C code:

r1 = fun1();
r2 = fun2();

if (r1 && r2)
{
   // do something
}

Variables r1 and r2 are not being used anywhere else in the code, except in the if (...) statement. Will both functions be evaluated? I'm worried that the compiler may optimize the code by eliminating r1 and r2, thus making it look like this:

if (fun1() && fun2())
{
   // do something
}

In this case, fun1() will be evaluated first, and if it returns FALSE, then fun2() will not be evaluated at all. This is not what I want, and that's the reason why I'm coding it as in the first code segment.

How can I guarantee that a function will always be evaluated? I thought that this could be done by assigning it to a variable, but I'm concerned about compiler optimization if it sees that this variable is never actually being used later on in the code...

I know this can be achieved by declaring r1 and r2 as volatile, but I'd like to know if there's a more elegant solution.

Any comments on this issue are greatly appreciated, thanks!


Edit: Thanks to all who replied. I've just used my first code snippet on my project (it's an ARM Cortex-M7-based embedded system). It appears that the compiler does not optimize the code in the way I showed above, and both fun1() and fun2() are evaluated (as they should). Furthermore, compiling the code with r1 and r2 declared as volatile produces exactly the same binary output as when r1 and r2 are just normal variables (i.e., the volatile keyword doesn't change the compiler output at all). This reassures me that the first code snippet is in fact a guaranteed way of evaluating both functions prior to processing the if (...) statement that follows.


Solution

  • Assuming the code does not exhibit any undefined behavior, compilers can only perform optimizations that have the same externally viewable behavior as the unoptimized code.

    In your example, the two pieces of code do two different things. Specifically, one always calls fun2 while the other calls it conditionally. So you don't need to worry about the first piece of code doing the wrong thing.