Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent optimizing away static const

Tags:

c++

g++

Is it possible to prevent static const members optimization using compiler command-line options?

Here is an example:

template <unsigned v1>
struct TRAITS {
    static const unsigned val1 = v1;
};

template < class TRAITS >
struct foo {
    static const unsigned x1 = TRAITS::val1;
};

int main () {
    foo<TRAITS<1>> f1;
    // SET BREAKPOINT HERE
    return 0;
}

Compile:

g++ -g -O0 optimize_out.cpp

GDB:

gdb a.out
(gdb) break optimize_out.cpp:13
(gdb) r
(gdb) p f1 
$1 = {static x1 = <optimized out>}

What is specific about this code is that classes are templates. Probably there is something in C++ standard that forces compiler to optimize fields away, even with -O0 ? When I don't use templates, values are not optimized away:

struct foo {
    static const unsigned x1 = 1;
};

In this case I can see x1 in debugger

like image 283
random Avatar asked Feb 05 '18 04:02

random


People also ask

Does const get optimized?

The short answer is that const makes no difference to optimization; it's to help catch bugs at compile-time.

Can we use const with static?

“static const” is basically a combination of static(a storage specifier) and const(a type qualifier). The static determines the lifetime and visibility/accessibility of the variable.

How do I know if GCC is not optimized?

Compiler specific pragma gcc provides pragma GCC as a way to control temporarily the compiler behavior. By using pragma GCC optimize("O0") , the optimization level can be set to zero, which means absolutely no optimize for gcc.

Is static the same as const?

The short answer: A const is a promise that you will not try to modify the value once set. A static variable means that the object's lifetime is the entire execution of the program and it's value is initialized only once before the program startup.


1 Answers

You can use the used attribute to tell the compiler to emit the definition even if it isn't needed by anything:

template <unsigned v1>
struct TRAITS {
    static const unsigned val1 [[gnu::used]] = v1;
};

template < class TRAITS >
struct foo {
    static const unsigned x1 [[gnu::used]] = TRAITS::val1;
};

Alternatively, you could add out-of-line definitions of the static variables (which would be needed anyway if you odr-used them) and add the attribute to those definitions:

template < class TRAITS >
  const unsigned foo<TRAITS>::x1 [[gnu::used]];

template <unsigned v1>
  const unsigned TRAITS<v1>::val1 [[gnu::used]];

like image 154
Jonathan Wakely Avatar answered Nov 11 '22 21:11

Jonathan Wakely