Optimization C: Why does the compiler not treat the object as a constant?

Compiling the next module C

static const int i = 1; void f (const int *i); int g (void) { f (&i); return i; } 

using gcc -S -O3 to handle x86_64, you get the following assembly for the g function:

 g: leaq i(%rip), %rdi subq $8, %rsp call f@PLT movl $1, %eax # inlined constant as an immediate addq $8, %rsp ret 

In other words, the return compiled to move the constant $1 to the %eax return register, which makes sense since i declared a constant.


However, if I remove this const , so I have

 static int i = 1; void f (const int *i); int g (void) { f (&i); return i; } 

the output of gcc -S -O3 suddenly becomes:

 g: leaq i(%rip), %rdi subq $8, %rsp call f@PLT movl i(%rip), %eax # reload i addq $8, %rsp ret 

That is, the return value is explicitly loaded from memory after calling f .

Why is this so? The argument f declared as a pointer to an int constant, so f should not be changed i . In addition, f cannot call a function that modifies i through a link other than a constant, because g can be the only such function, since i declared static.

+5
source share
2 answers

It is not undefined behavior to point a pointer to const to a pointer to non-constant, and change the reference object if the reference object is not declared const.

6.7.3p6 states: "If an attempt is made to modify an object defined using a type defined using const using the lvalue value with a non-constant type, the behavior is undefined."

+4
source

Changes the situation. The body is known. No special action required.

 static int i = 1; __attribute__((noinline)) void f (int *i) { *i *=2; } int g (void) { f (&i); return i; } f: sal DWORD PTR [rdi] ret g: mov edi, OFFSET FLAT:i call f mov eax, DWORD PTR i[rip] ret i: 
-2
source

Source: https://habr.com/ru/post/1272519/


All Articles