<div dir="ltr">I remember this bug. :) IMO, LLVM should never emit pushf / popf. I'm not sure this patch to fix it ever got committed:<div><div><a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__reviews.llvm.org_D6629&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=uYFinofl2WZUaBLmN4In8wRE-PnG19W8qtRnMrczlkQ&s=S6Q-ZYwMbJXYQjcL-d-hgNPaNRzfBW2yNuGMz_x11S8&e=">http://reviews.llvm.org/D6629</a><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jul 29, 2015 at 3:11 PM, Michael Hordijk <span dir="ltr"><<a href="mailto:hoffbrinkle@hotmail.com" target="_blank">hoffbrinkle@hotmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
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.<br>
<br>
Here's a simple test program.  Assume that the external function foo() modifies the IF bit in EFLAGS.<br>
<br>
---<br>
<br>
#include <stdlib.h><br>
#include <stdbool.h><br>
<br>
void foo(void);<br>
int a;<br>
<br>
int bar(void)<br>
{<br>
        foo();<br>
<br>
        bool const zero = a -= 1;<br>
<br>
        asm volatile ("" : : : "cc");<br>
        foo();<br>
<br>
        if (zero) {<br>
                return EXIT_FAILURE;<br>
        }<br>
<br>
        foo();<br>
<br>
        return EXIT_SUCCESS;<br>
}<br>
<br>
---<br>
<br>
And it's compiled using the following command line:<br>
<br>
---<br>
<br>
$ clang -O2   -c -o clang-eflag.o clang-eflag.c<br>
<br>
---<br>
<br>
Produces this output:<br>
<br>
---<br>
<br>
$ objdump -S clang-eflag.o<br>
<br>
clang-eflag.o:     file format elf64-x86-64<br>
<br>
<br>
Disassembly of section .text:<br>
<br>
0000000000000000 <bar>:<br>
   0:   53                      push   %rbx<br>
   1:   e8 00 00 00 00          callq  6 <bar+0x6><br>
   6:   ff 0d 00 00 00 00       decl   0x0(%rip)        # c <bar+0xc><br>
   c:   9c                      pushfq<br>
   d:   5b                      pop    %rbx<br>
   e:   e8 00 00 00 00          callq  13 <bar+0x13><br>
  13:   b8 01 00 00 00          mov    $0x1,%eax<br>
  18:   53                      push   %rbx<br>
  19:   9d                      popfq<br>
  1a:   75 07                   jne    23 <bar+0x23><br>
  1c:   e8 00 00 00 00          callq  21 <bar+0x21><br>
  21:   31 c0                   xor    %eax,%eax<br>
  23:   5b                      pop    %rbx<br>
  24:   c3                      retq<br>
<br>
---<br>
<br>
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.<br>
<br>
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:<br>
<br>
---<br>
<br>
entry:<br>
  tail call void @foo() #2<br>
  %0 = load i32* @a, align 4, !tbaa !1<br>
  %sub = add nsw i32 %0, -1<br>
  store i32 %sub, i32* @a, align 4, !tbaa !1<br>
  %tobool = icmp eq i32 %sub, 0<br>
  tail call void asm sideeffect "", "~{cc},~{dirflag},~{fpsr},~{flags}"() #2, !srcloc !5<br>
  tail call void @foo() #2<br>
  br i1 %tobool, label %if.end, label %return<br>
<br>
if.end:                                           ; preds = %entry<br>
  tail call void @foo() #2<br>
  br label %return<br>
<br>
return:                                           ; preds = %entry, %if.end<br>
  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %entry ]<br>
  ret i32 %retval.0<br>
<br>
---<br>
<br>
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)."<br>
<br>
- michael<br>
<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu" target="_blank">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" rel="noreferrer" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
</blockquote></div><br></div></div></div></div>