I have some heavily-used code that I would like GCC to optimize aggressively. But I also want to write clean, reusable code with (inlinable) functions that are called from several places. There are cases where in the inlined function, there is code that I know can be removed because the conditions can never happen.
Let's look at a concrete example:
#include <assert.h>
static inline int foo(int c)
{
if (c < 4)
return c;
else
return 4;
}
int bar(int c)
{
assert(c < 2);
return foo(c);
}
With -DNDEBUG -O3, GCC will still generate the (c < 4) comparison even though I know it is not needed, because a precondition of the bar function is that c is 0 or 1. Without -DNDEBUG, GCC does remove the comparison because it is implied by the asserts - but of course you have the overhead of the asserts then (which is a lot more).
Is there a way to convey the variable range to GCC so it can be used for optimisation?
If CLang can do better on this, I could also consider switching compilers.
You might use __builtin_unreachable (read about other builtins) in a test to tell the compiler, e.g.,
if (x<2 || x>100)
__builtin_unreachable();
// Here the compiler knows that x is between 3 and 99 inclusive
In your case, add this at the start of your bar (probably wrapped in some nice looking macro):
if (c >= 2)
__builtin_unreachable();
If you optimize strongly (e.g., -O2 at least), the compiler knows that x is between 3 and 99 (and recent versions of GCC contain code to do such analysis—at least processing simple constant interval constraints like above—and take advantage of them in later optimization passes).
However, I am not so sure that you should use that! (at least don't use it often and wrap that in some assert-like macro), because it might not worth the trouble, and because the compiler is in practice only able to handle and propagate simple constraints (whose details are compiler version specific).
As far as I know, both recent Clang and GCC accepts that builtin.
Also look into __builtin_trap (which also emits runtime code).
Related
To avoid declaring flows of one-time-use variables, I like to proceed using as few variables as possible and recasting them like so:
int main()
{
int i1;
#define cChar ((char)i1)
cChar='a';
#undef cChar
}
Which gives me the famous "error : lvalue required as left operand of assignment".
After reading a bit about this issue on this forum, it was pointed out that since 4.0, the cast-as-lvalue was removed (https://gcc.gnu.org/gcc-4.0/changes.html).
However, I fail to understand the why behind this and I was wondering if there was an option (apparently not) or even an alternative to GCC that would accept this kind of operation, which has been working for ages on ye olde compiler (obviously not GCC, but like Borland C++).
I have the following code (CPU Atmel AVR ATmega64A):
#define UO_ADC1023 265
#define UREF_180V (1023*180/UO_ADC1023)
....
if(ADC > UREF180) {do_something();}
This should evaluate UREF_180V as 694.87... and than this value should be rounded (better) to 695 or floored (poorer) to 694 to be compared to ADC register.
However I have integer overflow warning at compile. As per this I suppose that compiler generating code which calculates (1023*180/UO_ADC1023) at the run time which is very bad in my case.
I'd like to avoid to calculate those constants by my self (#define UREF_180V 695 in this case I could be sure that they are really literals) to make the code more flexible and readable. I'd like also to be able to check those values after the compiler.
So the questions are:
Is there any possibility to force GCC compiler to calculate such constants at compile time?
How to check this calculated value?
int on AVR is 16-bit. Tell the compiler to use long instead (since 1023 * 180 will overflow).
#define UREF_180V (1023L * 180 / UO_ADC1023)
Macros are inserted at the place of invokation, where their content can later be compiled.
In C++11 you can evaluate expressions at compile time with constexpr, like this:
constexpr auto UREF_180V = 1023*180/UO_ADC1023;
Due to all of the numbers being ints the result of this is 694. To properly round it you would have to change one of the values to a floating point number and create a constexpr rounding function, which can be invoked at compile time.
As for checking the number you could use static_assert(695 == UREF_180V, "");.
To compile C++11 code add -std=c++11 to your compiler options. (You probably have to switch to a C++ project, and I'm not entirely certain AtmelStudio supports C++11, if not I'm sorry)
see the -fmerge-all-constants command, -fgcse, -fsee, or better, see here: https://gcc.gnu.org/onlinedocs/gcc-4.2.2/gcc/Optimize-Options.html
nonetheless, the integer overflow can be part of an semantic error in your code as welternsturm mentioned
I'm running a set of benchmarks comparing different libc string functions. The problem is that GCC and Clang are optimizing out the computations in the loops because the functions are marked "pure" and "const". Is there some way to either turn off that optimization or get around it?
I solved it! The solution was nasty, but it works:
volatile int x;
for (...)
{
// ...
x = (int)f(args);
}
I never use the value of x, so the cast won't be a problem. Better yet, now I don't get errors about not using return value of function declared with pure attribute.
AFAIK there are pthread functions that acts as memory barriers (e.g. here clarifications-on-full-memory-barriers-involved-by-pthread-mutexes). But what about compile-time barrier, i.e. is compiler (especially gcc) aware of this?
In other words - e.g. - is pthread_create() reason for gcc not to perform reordering?
For example in code:
a = 1;
pthread_create(...);
Is it certain that reordering will not take place?
What about invocations from different functions:
void fun(void) {
pthread_create(...);
...
}
a = 1;
fun();
Is fun() also compile time barrier (assuming pthread_create() is)?
What about functions in different translation units?
Please note that I am interested in general gcc and pthreads behavior scpecification, not necessarily x86-specific (various different embedded platforms in focus).
I am also not interested in other compilers/thread libraries behavior.
Because functions such as pthread_create() are external functions the compiler must ensure that any side effects that could be visible to an external function (such as a write to a global variable) must be done before calling the function. The compile couldn't reorder the write to a until after the function call in the first case) assuming a was global or otherwise potentially accessible externally).
This is behavior that is necessary for any C compiler, and really has little to do with threads.
However, if the variable a was a local variable, the compiler might be able to reorder it until after the function call (a might not even end up in memory at all for that matter), unless something like the address of a was taken and made available externally somehow (like passing it as the thread parameter).
For example:
int a;
void foo(void)
{
a = 1;
pthread_create(...); // the compiler can't reorder the write to `a` past
// the call to `pthread_create()`
// ...
}
void bar(void)
{
int b;
b = 1;
pthread_create(...); // `b` can be initialized after calling `pthread_create()`
// `b` might not ever even exist except as a something
// passed on the stack or in a register to `printf()`
printf( "%d\n", b);
}
I'm not sure if there's a document that outlines this in more detail - this is covered largely by C's 'as if' rule. In C99 that's in 5.1.2.3/3 "Program execution". C is specified by an abstract machine with sequence points where side effects must be complete, and programs must follow that abstract machine model except where the compiler can deduce that the side effects aren't needed.
In my foo() example above, the compiler would generally not be able to deduce that setting a = 1; isn't needed by pthread_create(), so the side effect of setting a to the value 1 must be completed before calling pthread_create(). Note that if there are compilers that perform global optimizations that can deduce that a isn't used elsewhere, they could delay or elide the assignment. However, in that case nothing else is using the side effect, so there would be no problem with that.
When learning to code, I was taught the following style when checking the value of a variable:
int x;
Object *object;
...
if(x == 7) { ... }
if(object == NULL) { ... }
However, now that I am in the field, I have encountered more than one co-worker who swears by the approach of switching the lhs and rhs in the if statements:
if(7 == x) { ... }
if(NULL == object) { ... }
The reasoning being that if you accidentally type = instead of ==, then the code will fail at compile. Being unaccustomed to this style, reading 7 == x is difficult for me, slowing my comprehension of their code.
It seems if I adopt this style, I will likely someday in the future save myself from debugging an x = 7 bug, but in the mean time, every time somebody reads my code I may be wasting their time because I fear the syntax is unorthodox.
Is the 7 == x style generally accepted and readable in the industry, or is this just a personal preference of my coworkers?
The reasoning being that if you accidentally type = instead of ==, then the code will fail at compile.
True. On the other hand, I believe modern C and C++ compilers (I'm assuming you're using one of those languages? You haven't said) will warn you if you do this.
Have you tried it with the compiler you're using? If it doesn't do it by default, look to see if there are flags you can use to provoke it - ideally to make it an error rather than just a warning.
For example, using the Microsoft C compiler, I get:
cl /Wall Test.c
test.c(3) : warning C4706: assignment within conditional expression
That's pretty clear, IMO. (The default warning settings don't spot it, admittedly.)
Being unaccustomed to this style, reading 7 == x is difficult for me, slowing my comprehension of their code.
Indeed. Your approach is the more natural style, and should (IMO) be used unless you're really dealing with a compiler which doesn't spot this as a potential problem (and you have no alternative to using that compiler).
EDIT: Note that this isn't a problem in all languages - not even all C-like languages.
For example, although both Java and C# have a similar if construct, the condition expression in both needs to be implicitly convertible to a Boolean value. While the assignment part would compile, the type of the expression in your first example would be int, which isn't implicitly convertible to the relevant Boolean type in either language, leading to a compile-time error. The rare situation where you'd still have a problem would be:
if (foo == true)
which, if typo'd to:
if (foo = true)
would compile and do the wrong thing. The MS C# compiler even warns you about that, although it's generally better to just use
if (foo)
or
if (!foo)
where possible. That just leaves things like:
if (x == MethodReturningBool())
vs
if (MethodReturningBool() == x)
which is still pretty rare, and there's still a warning for it in the MS C# compiler (and probably in some Java compilers).