I have a program where I need to pass the pointer to a local variable to a asm
statement. (For those who are curious, the intended use of this code is to call the INVVPID instruction.)
#include <stdio.h>
static void f(long x){
long a = x;
asm volatile(
"xorq %%rcx, %%rcx;"
"cmpq (%%rax), %%rcx;"
"xorq %%rax, %%rax"
:
: "a"(&a)
: "cc", "memory");
}
int main(void)
{
f(0);
f(1);
}
I am using a 64-bit machine and gcc (GCC) 12.2.1 20220819 (Red Hat 12.2.1-1)
. When compiled with -O0
, the program runs well without error. However, when compiled with -O3
, this program runs into segmentation fault at 0x401043
because RAX=0. The disassembly is:
0000000000401020 <main>:
401020: 48 c7 44 24 f8 00 00 movq $0x0,-0x8(%rsp)
401027: 00 00
401029: 48 8d 44 24 f8 lea -0x8(%rsp),%rax
40102e: 48 31 c9 xor %rcx,%rcx
401031: 48 3b 08 cmp (%rax),%rcx
401034: 48 31 c0 xor %rax,%rax
401037: 48 c7 44 24 f8 01 00 movq $0x1,-0x8(%rsp)
40103e: 00 00
401040: 48 31 c9 xor %rcx,%rcx
401043: 48 3b 08 cmp (%rax),%rcx
401046: 48 31 c0 xor %rax,%rax
401049: 31 c0 xor %eax,%eax
40104b: c3 ret
It looks like the problem happens because local variable a
is optimized out in f(1)
. The program can be fixed by changing the line to volatile long a = x;
.
My question is: is this a legitimate behavior of the GCC compiler? My intuition tells me that things should not be optimized out because the address of a
appears in f()
.