0

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?

kirbyfan64sos
  • 10,377
  • 6
  • 54
  • 75
  • clang lets you select which passes to perform, with gcc I'm not so sure – Marco A. May 09 '14 at 21:31
  • 3
    The best way to benchmark these things is to use the result. Just printing out a single number from the output is usually enough. – Mysticial May 09 '14 at 21:31
  • With pure/const functions, you want to use the result, but you also want to make sure that you are calling them with a different argument each time or the compiler may perform a single call. Disabling a compiler pass (@Marco of course gcc allows it) is too fragile (unless you go for -O0). You could try declaring those libc functions yourself (instead of including the standard headers) and compiling with -fno-builtin so the compiler doesn't know the functions are pure/const, but better follow Mysticial's advice. – Marc Glisse May 09 '14 at 21:38
  • Thanks Marc. Never needed that, to be honest. But it's good to know. – Marco A. May 09 '14 at 21:40

1 Answers1

0

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.

kirbyfan64sos
  • 10,377
  • 6
  • 54
  • 75
  • There is nothing in your solution that prevents the next version of the compiler, or the current one, to transform the loop to `int i = (int)f(args); for (...) x = i;` – Pascal Cuoq May 09 '14 at 21:54
  • @PascalCuoq: I declared `x` as [`volatile`](http://en.wikipedia.org/wiki/Volatile_variable), so the compiler knows that it shouldn't be touched. – kirbyfan64sos May 09 '14 at 22:02
  • You declared `x` as `volatile`, so the compiler knows that there should be as many accesses to it in the object code as in the source code. The `volatile` qualifier does not apply to `(int)f(args)`, so the compiler can hoist it out of the loop. It is a classic optimization and I wouldn't be surprised if at least one existing compiler was able to apply it to your code already. Compilers that do not do so have simply not implemented the full scope of optimizations relating to pure functions yet. – Pascal Cuoq May 09 '14 at 22:08
  • See “5. Expecting volatile to enforce ordering with non-volatile accesses” in http://blog.regehr.org/archives/28 – Pascal Cuoq May 09 '14 at 22:13
  • @PascalCuoq: Ah, crap. I can try changing the cast to read `(volatile int)`. Could that help? – kirbyfan64sos May 09 '14 at 22:17
  • In theory no, in practice probably. What's wrong with the usual solution that Mysticial provided in a comment? – Pascal Cuoq May 09 '14 at 22:19
  • @PascalCuoq You don't want the compiler to know that args is the same in all the calls. If you make args volatile... I'll let you think about what happens. – Marc Glisse May 10 '14 at 00:47
  • @MarcGlisse: That's a really good point. If the arguments are volatile, it won't optimize out the calls. I'll try that! – kirbyfan64sos May 10 '14 at 22:23