<div dir="ltr">I think I see what's going on, and I agree it looks like a bug. It was too much to hope that later passes weren't going to mess with the PUSH instruction. :(<div><br></div><div>While I was trying to reproduce your problem, I think I found another one that looks like this:</div><div>

<pre id="m_-5838096194945216868gmail-hterm:copy-to-clipboard-source" style="color:rgb(0,0,0);font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial">$ clang -S -O2 -m32 -mregparm=3 -mretpoline spill_across_rp.cpp -o - | grep _retpoline_push -B2
...
        movl    %eax, 8(%esp)           # 4-byte Spill
...
        pushl   %edi
        movl    8(%esp), %edi           # 4-byte Reload
        calll   __llvm_retpoline_push</pre>

That's obviously broken, it doesn't account for the SP adjustment in the push.</div><div><br></div><div>It's weird, because it's basically the opposite of the problem you're having, which looks like LLVM *is* accounting for the push and is trying to adjust its offsets accordingly.</div><div><br></div><div>Can you send along the full command line used to compile io_apic_b.i?</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Feb 9, 2018 at 11:38 AM, David Woodhouse <span dir="ltr"><<a href="mailto:dwmw2@infradead.org" target="_blank">dwmw2@infradead.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Fri, 2018-02-09 at 11:24 -0800, Reid Kleckner wrote:<br>
> I haven't read the all the emails in full detail, but it seems pretty<br>
> clear that  __x86_indirect_thunk and __llvm_retpoline_push do not do<br>
> the same things. It sounds like __llvm_retpoline_push is equivalent<br>
> to __x86_indirect_thunk except first it swaps the two words on the<br>
> top of the stack.<br>
><br>
> I arranged it this way because the x86 call instruction puts the<br>
> intended return address on the top of the stack, and there's no easy<br>
> way to put it anywhere else. We use this thunk when we want to make<br>
> an indirect call and there are no available scratch registers, i.e.<br>
> 32-bit -mregparm=3 and the call has three or more arguments, which<br>
> happens in Linux. One way to avoid this would be to compile with<br>
> -mregparm=2, but that would pessimize direct calls unnecessarily.<br>
><br>
> It sounds like Linux is already providing its own thunks, so it might<br>
> be better to for us to go back to the __llvm_retpoline_push external<br>
> thunk name and then get Linux to provide that thunk ifdef __clang__.<br>
<br>
</span>Yes, the thunks are different in this case. That one should indeed be<br>
renamed, and I'll provide the correct one in the kernel.<br>
<br>
However, even if I let LLVM emit the thunk for itself, code generation<br>
seems hosed. It looks like after a call to __llvm_retpoline_push (or<br>
perhaps more to the point after pushing the target address in<br>
preparation for the call?) we're losing track of where %esp points, and<br>
thus everything else that was spilled to the stack.<br>
<br>
Please let me know if you need any more detail on that, than I provided<br>
in my last email. You should have everything you need there to follow<br>
along with my analysis and reproduce it for yourself. Except perhaps<br>
the Grandma-suck-eggs command lines like<br>
<br>
$ qemu-system-i386  -display none -serial stdio -kernel arch/x86/boot/bzImage  -append earlyprintk=ttyS0,keep -s -S<br>
<br>
$ gdb vmlinux<br>
(gdb) tar rem localhost:1234<br>
(gdb) break mp_register_ioapic<br>
(gdb) c<br>
</blockquote></div><br></div>