Is it legitimate for C compilers to optimize out non-volatile local variables whose address is used?

Viewed 92

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().

0 Answers
Related