[LLVMdev] optimizer clobbering EFLAGS

Michael Hordijk hoffbrinkle at hotmail.com
Wed Jul 29 07:54:10 PDT 2015


Using Clang/LLVM 3.6.0 we are observing a case where the optimizations 
are clobbering EFLAGS on x86_64.  This is inconvenient when the status 
of bit 9 (IF), which controls interrupts, changes.

Here's a simple test program.  Assume that the external function foo() 
modifies the IF bit in EFLAGS.

#include <stdlib.h>
#include <stdbool.h>

void foo(void);
int a;

int bar(void)
{
         foo();

         bool const zero = a -= 1;

         asm volatile ("" : : : "cc");
         foo();

         if (zero) {
                 return EXIT_FAILURE;
         }

         foo();

         return EXIT_SUCCESS;
}

And it's compiled using the following command line:

clang -O2   -c -o clang-eflag.o clang-eflag.c

Produces this output:

$ objdump -S clang-eflag.o

clang-eflag.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <bar>:
    0:   53                      push   %rbx
    1:   e8 00 00 00 00          callq  6 <bar+0x6>
    6:   ff 0d 00 00 00 00       decl   0x0(%rip)        # c <bar+0xc>
    c:   9c                      pushfq
    d:   5b                      pop    %rbx
    e:   e8 00 00 00 00          callq  13 <bar+0x13>
   13:   b8 01 00 00 00          mov    $0x1,%eax
   18:   53                      push   %rbx
   19:   9d                      popfq
   1a:   75 07                   jne    23 <bar+0x23>
   1c:   e8 00 00 00 00          callq  21 <bar+0x21>
   21:   31 c0                   xor    %eax,%eax
   23:   5b                      pop    %rbx
   24:   c3                      retq

The critical bits here are that at 0xc/0xd, we save the value of EFLAGS 
into %rbx.  We then call foo() (which changes bit 9 of EFLAGS).  We then 
0x18/0x19 reload EFLAGS from the stale value in %rbx thus clobbering the 
value of bit 9 leaving interrupts in an unexpected state.

You may notice that I've tried the asm volatile ("" : : : "cc") 
constraint.  The generated output is identical with and without the 
constraint.  Which is not totally surprising.  I'm thinking that the 
"cc" constraint tells the optimizer that "EFLAGS has been clobbered". 
What we need is a way to tell the optimizer that "EFLAGS has been 
clobbered and needs to be preserved."

- michael




More information about the llvm-dev mailing list