0

Suppose I have the following C line:

int a = 4 + 7;

When compiling this line, GCC will always produce something like mov DWORD PTR [rbp-X], 0xb, as the result of this computation is constant and known at compile time. Is there a way to disable this behaviour to have a mov 4, add 7 instead?

A quick search led me to the -O0 or -OG flags, but they turn off other kinds of optimizations, such as the fact that functions should be aligned in memory.

Katoptriss
  • 107
  • 6
  • 3
    Why do you want to turn of this very specific optimization but not others? – user17732522 May 09 '22 at 12:14
  • 1
    The problem is that `int array[4+7]` has to work, and `#if 4+7==1`. . It's not really a simplification, as it is language rules. – MSalters May 09 '22 at 12:15
  • I confess myself curious as well. This is one optimization I never heard complaints against. – StoryTeller - Unslander Monica May 09 '22 at 12:18
  • As noted in the answer, even `-O0` doesn't disable this "optimization": https://godbolt.org/z/raGGz6En5 – user17732522 May 09 '22 at 12:18
  • I'm wondering what GCC would do with `int a = 4 + (volatile int) 7;` though. I suspect that even at `-O2` it would have to respect the `volatile`. But that's a local change, not a global setting. – MSalters May 09 '22 at 12:19
  • @MSalters Does `volatile` on a rvalue have any meaning in C? GCC still compiles it to the same code. – user17732522 May 09 '22 at 12:22
  • @StoryTeller-UnslanderMonica I was doing researches on MBAE (Mixed Boolean Arithmetic Expressions), which are pretty things like `for all (x, y), x + y = 2(~(x ^ y)) + 3(~x & y) + 3(x & ~y) - 2(~(x & y))`. The goal here was to hide a little bit better the operation effectued: if every `y` becomes a 7, a part of the obfuscation here disappear. – Katoptriss May 09 '22 at 12:24
  • @Katoptriss: That sort of expressions may make sense in a specific theoretical CompSci framework, but C has its own rules for `_Bool` and assembly code has wildly varying ideas about bools (x86 and ARM have flag registers, for instance) – MSalters May 09 '22 at 12:30
  • If you're actually using `_Bool` (or C++ `bool`), the ABI for most platforms allows compilers to assume the object-representation is a `0` or `1` byte. Having it be a `7` would be UB. [Does the C++ standard allow for an uninitialized bool to crash a program?](https://stackoverflow.com/a/54125820). Of course if you're just using `int`, that's fine. – Peter Cordes May 09 '22 at 14:52
  • But note that GCC `-O0` [won't do constant-propagation across statements](https://stackoverflow.com/questions/53366394/why-does-clang-produce-inefficient-asm-with-o0-for-this-simple-floating-point), so you can just do `register unsigned seven = 7;` or `register unsigned y = 7`. (The `register` keyword makes code-gen less horrible at `-O0`, normally never use it.) It may still take advantage of the fact that every `y` will read the same value, whatever that is, unless you use `volatile unsigned y = 7`. Then `y ^ y` will do two loads, not optimize to 0. – Peter Cordes May 09 '22 at 14:52

1 Answers1

4

Is there a way to disable this behaviour to have a mov 4, add 7 instead?

No. Evaluation of elementary constant expressions is built into the compiler.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312