[LLVMdev] optimizer clobber EFLAGS

Reid Kleckner rnk at google.com
Wed Jul 29 16:12:43 PDT 2015


I remember this bug. :) IMO, LLVM should never emit pushf / popf. I'm not
sure this patch to fix it ever got committed:
http://reviews.llvm.org/D6629

On Wed, Jul 29, 2015 at 3:11 PM, Michael Hordijk <hoffbrinkle at hotmail.com>
wrote:

>
> 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 LLVM IR has the what appears to be an appropriate inline
> ASM directive:
>
> ---
>
> entry:
>   tail call void @foo() #2
>   %0 = load i32* @a, align 4, !tbaa !1
>   %sub = add nsw i32 %0, -1
>   store i32 %sub, i32* @a, align 4, !tbaa !1
>   %tobool = icmp eq i32 %sub, 0
>   tail call void asm sideeffect "", "~{cc},~{dirflag},~{fpsr},~{flags}"()
> #2, !srcloc !5
>   tail call void @foo() #2
>   br i1 %tobool, label %if.end, label %return
>
> if.end:                                           ; preds = %entry
>   tail call void @foo() #2
>   br label %return
>
> return:                                           ; preds = %entry, %if.end
>   %retval.0 = phi i32 [ 0, %if.end ], [ 1, %entry ]
>   ret i32 %retval.0
>
> ---
>
> The constraint doesn't appear to do anything 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 the new value in EFLAGS needs to be
> preserved (so don't clobber it)."
>
> - michael
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150729/9c60bdb1/attachment.html>


More information about the llvm-dev mailing list