Tell gcc compiler to treat variable not as constant when optimizing

1k views Asked by At

Is there any way to tell the compiler (here gcc) that it should not optimize variables that it thinks are constants to constant expressions? In general by a compiler flag or even better by using an attribute for a specific variable?

I want the (local) variable to really exist, every read on this variable to be actually executed and also every write, even if I write the same value again.

It would always load/store the variable from/to RAM if I don't optimize. Same if I declare it volatile. However, I do want it to be able to be kept in a register, just like a normal variable that's neither constant nor volatile. Disabling optimization completely is also not an option.

Code example (r(a) and r(b) are any register):
int a, b;
a = 2;
a = 2;
b = a;
Result (provided b is needed later, a no more):
Ignored line
Ignored line
Moves 2 in r(b)
a is replaced by constant expression 2

volatile int a;  
int b;  
a = 2;  
a = 2;  
b = a;  

Result (b is needed later, a doesn't matter):
Moves 2 in r2, puts address of a in r3, writes r2 to RAM(r3)
Writes r2 again to RAM(r3)
Reads RAM(r3) into r4
Puts address of b in r5, writes r4 to RAM(r5)

As you can see this is very inefficient. What I want:
Move 2 in r(a)
Move 2 in r(a) again
Write r(a) into r(b)
If registers are needed for something else, store a and b in RAM
This is exactly what would happen, if a was a real variable and not just 2.

3

There are 3 answers

3
Dellowar On

For such a demand you could not use C for this. It is not possible to dictate a variables physical location (RAM vs registry). The whole point of GCC is to take care of that for you.

You'd have to write your own assembly code to work with using load operations.

5
John Bollinger On

Neither C nor GCC has a mechanism for what you describe. The closest is to declare the variable volatile, which has the following effect:

[...] any expression referring to [a volatile] object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously.

(C2011, 6.7.3/7; emphasis added)

It is primarily the highlighted part that bears on the question, for it requires reads and writes to the stored value of the variable actually be performed. It does not necessarily prevent the variable from being allocated to a register, as the standard has nothing whatever to say about CPU registers, but it may be that it has that effect in some implementations. (I cannot speak directly to GCC's behavior in that regard.)

0
Marcus Müller On

It would always load/store the variable from/to RAM if I don't optimize.

no, that's not how CPUs or compilers work.

While C, at least for externally visible objects, guarantees that an non-temporary object has a comparable address citation needed, there's absolutely no reason for a compiler to generate from the following C code:

int a,b;
a = 0;
b = a + 2; 
a = 3;

any assembler that would, everytime you touch a, load a from RAM and store it back to RAM. In fact, a compiler's job is exactly to know which variables are in which register at a point in execution, and handle operations on variables thus based on these registers.