[LLVMdev] optimizer clobber EFLAGS
JF Bastien
jfb at google.com
Wed Jul 29 17:35:20 PDT 2015
Agreed, never emit pushf/popf. Sorry I never committed the patch, the cmov
issue got hairy and I never got to debugging it :-)
I can get back to it if there's interest!
On Wed, Jul 29, 2015 at 4:12 PM, Reid Kleckner <rnk at google.com> wrote:
> 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/6d9ef706/attachment.html>
More information about the llvm-dev
mailing list