not used const static variable in class optimized out?

一个人想着一个人 提交于 2021-02-08 07:21:37

问题


Can a reasonable decent compiler discard this const static variable

class A{
     const static int a = 3;
}

if it is nowhere used in the compiled binary or does it show up anyway in the binary?


回答1:


Short answer: Maybe. The standard does not say the compiler HAS to keep the constants (or strings, or functions, or anything else), if it's never used.

Long answer: It very much depends on the circumstances. If the compiler can clearly determine that it is not used, it will remove unused constants. If it can't make that determination, it can not remove the unused constant, since the constant COULD be used by something that isn't currently known by the compiler (e.g. another source file).

For example, if class A is inside a function, the compiler can know this class is not used elsewhere, and if the constant isn't used in the function, then it's not used anywhere. If the class is in a "global" space, such that it could be used somewhere else, then it will need to keep the constant.

This gets even more interesting with "whole program optimization" or "link time optimization" (both from now on called LTO), where all the code is actually optimized as one large lump, and of course, "used" or "not used" can be determined for all possible uses.

As you can imagine, the result will also depend on how clever the compiler (and linker for the LTO) is. All compilers should follow the principle of "if in doubt keep it".

You can of course experiment, and write some code where you use the variable, and then remove the use, and see what difference it makes to the assembly code (e.g. g++ -S x.cpp or clang++ -S x.cpp, and look at the resulting x.s file).




回答2:


When optimizations are disabled, the answer is compiler-dependent. But when optimizations are enabled, the end result is the same irrespective of the compiler. Let's assume that optimizations are enabled.

The compiler will not emit a definition for a const static field in the generated object file when both of the following conditions holds:

  1. It can resolve all uses of the field with the constant value it was initialized to.
  2. There is at most one source code file that has used the field (there is an exception which I'll discuss at the end).

I'll discuss the second condition later. But now let's focus on the first. Let's see an example. Suppose that the target platform is 32-bit and that we have defined the following type:

// In MyClassA.h
class MyClassA{
public:
     const static int MyClassAField;
};

// In MyClassA.cpp (or in MyClassA.h if it was included in at most one cpp file)
const int MyClassA::MyClassAField = 2;

Most compilers consider int to be a 32-bit signed integer. Therefore, on a 32-bit processor, most instructions can handle a 32-bit constant. In this case, the compiler will be able to replace any uses of MyClassAField with the constant 2 and that field will not exist in the object file.

On the other hand, if the field was of type double, on a 32-bit platform, instructions cannot handle 64-bit values. In this case, most compilers emit the field in the object file and uses SSE instructions and registers to 64-bit value from memory and process them.

Now I'll explain the second condition. If there is more than one source code file that is using the field, it cannot be eliminated (irrespective of whether Whole Program Optimization (WPO) is enabled or not) because some object file has to include the definition of the field so that the linker can use it for other object files. However, the linker, if you specified the right switch, can eliminate the field from the generated binary.

This is a linker optimization enabled with /OPT:REF for VC++ and --gc-sections for gcc. For icc, the names of the switches are the same (/OPT:REF on Windows and --gc-sections on Linx and OSX). However, the compiler has to emit every function and static or global field in a separate section in the object file so that the linker can eliminate it.

There is a catch, however. If the field has been defined inline as follows:

class MyClassA{
public:
     const static int MyClassAField = 2;
};

Then the compiler itself will eliminate the definition of this field from every object file that uses it. That's because every source code file that uses it includes a separate definition. Each of them is compiled separately, the compiler itself will optimize the field away using an optimization called constant propagation. In fact, the VC++ compiler perform this optimization even if optimizations are disabled.

When optimizations are disabled, whether a const static field will be eliminated or not depends on the compiler, but probably it will not be eliminated.



来源:https://stackoverflow.com/questions/33010268/not-used-const-static-variable-in-class-optimized-out

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!