1

I am wondering how to turn off optimization for the following loop. I have searched and tried some flag but not working. Thanks.

#include <iostream>

int fun(int i) {return ++i;};

int main ()
{
    int res = 0;

    for (long i = 0; i < 10000; i++)
    {
        res += fun(i);
    }
    std::cout << res;
}

-O1 will remove the loop and directly hard code the result. I would like to use -O3 but with this optimization turned off.

Daniel Langr
  • 22,196
  • 3
  • 50
  • 93
frank
  • 178
  • 2
  • 7
  • one way is to throw the res++ bugger in a virtual function or in some cases to call it via a function pointer. (compiler dependent)... If you want to turn off ops for a specific loop- might get tricky to the point of having to compile it in a separate file. – Abel May 20 '21 at 02:34
  • why would you want to run that useless loop in optimization mode? It's only for debugging purpose – phuclv May 20 '21 at 02:45
  • Most compilers have a pragma to toggle optimizations in code: https://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmas – selbie May 20 '21 at 03:05
  • Also, **what are you really trying to do** by disabling a loop unroll optimization? I wonder if this is an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – selbie May 20 '21 at 03:05
  • You are absolutely right, it is only for testing not for production:) – frank May 20 '21 at 03:13
  • To be more specific, I am tring to performance test some code in the loop but compiler keeps remove the loop. I could use -O0 but it will turn off other optimization which I want to keep. – frank May 20 '21 at 03:22
  • Have you tried to simply put the definition of `fun` into a separate compilation unit (source file)? – Daniel Langr May 20 '21 at 04:01

1 Answers1

2

You can use something like Google Benchmark's DoNotOptimize() function. This function uses an empty asm block to lie to the compiler that the given variable was read from. Adapted from here:

template <class Tp>
[[gnu::always_inline]] inline void DoNotOptimize(Tp const& value) {
  asm volatile("" : : "r,m"(value) : "memory");
}

template <class Tp>
[[gnu::always_inline]] inline void DoNotOptimize(Tp& value) {
#if defined(__clang__)
  asm volatile("" : "+r,m"(value) : : "memory");
#else
  asm volatile("" : "+m,r"(value) : : "memory");
#endif
}

Then, you can lie to the compiler and tell it that res is read in each iteration:

#include <iostream>

int main ()
{
    int res = 0;

    ::DoNotOptimize(res);
    for (long i = 0; i < 10; i++)
    {
        res++;
        ::DoNotOptimize(res);
    }
    std::cout << res;
}

Compiler Explorer link

In -O3, the loop is unrolled, but -O1 and -O2 keep the loop.

Justin
  • 24,288
  • 12
  • 92
  • 142
  • Thanks for your reply. This solution definitely works but I think I over simplified my qusetion. So I updated it to call a function, which is still optimized to a hard coded number 50005000 by compiler. I also increased the iteration to prevent unrolling. – frank May 20 '21 at 03:15
  • @frank I believe this solution still works: https://godbolt.org/z/EM1s7vco6 – Justin May 20 '21 at 05:10