Friday, June 3, 2022

[SOLVED] GCC: __atomic_always_lock_free compiles with -O3, but not with -O0

Issue

Sample code:

int *s;

int foo(void)
{
  return 4;
}

int bar(void)
{
  return __atomic_always_lock_free(foo(), s);
}

Invocations:

$ gcc t0.c -O3 -c
<nothing>

$ gcc t0.c -O0 -c
t0.c:10:10: error: non-constant argument 1 to '__atomic_always_lock_free'

Any ideas?

Relevant: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html.


Solution

This doesn't seem surprising. The documentation you linked says that "size must resolve to a compile-time constant" and so it's to be expected that you might get an error when passing foo(). However, it's typical that if GCC is able to determine the value of an expression at compile time, then it will treat it as a compile-time constant, even if it doesn't meet the language's basic definition of a constant expression. This may be considered an extension and is explicitly allowed by the C17 standard at 6.6p10.

The optimization level is relevant to what the compiler tries in attempting to evaluate an expression at compile time. With optimizations off, it does little more than the basic constant folding that the standard requires (e.g. 2*4). With optimizations on, you get the benefit of its full constant propagation pass, as well as function inlining.

So in essence, under -O0, the compiler doesn't notice that foo() always returns the same value, because you've disabled the optimizations that would allow it to reach that conclusion. With -O3 it does and so it accepts it as a constant.



Answered By - Nate Eldredge
Answer Checked By - Willingham (WPSolving Volunteer)