Index: llvm/lib/Target/X86/X86WinAllocaExpander.cpp =================================================================== --- llvm/lib/Target/X86/X86WinAllocaExpander.cpp +++ llvm/lib/Target/X86/X86WinAllocaExpander.cpp @@ -211,13 +211,13 @@ bool Is64Bit = STI->is64Bit(); assert(SlotSize == 4 || SlotSize == 8); - unsigned RegA = (SlotSize == 8) ? X86::RAX : X86::EAX; switch (L) { - case TouchAndSub: + case TouchAndSub: { assert(Amount >= SlotSize); // Use a push to touch the top of the stack. + unsigned RegA = Is64Bit ? X86::RAX : X86::EAX; BuildMI(*MBB, I, DL, TII->get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) .addReg(RegA, RegState::Undef); Amount -= SlotSize; @@ -226,10 +226,12 @@ // Fall through to make any remaining adjustment. LLVM_FALLTHROUGH; + } case Sub: assert(Amount > 0); if (Amount == SlotSize) { // Use push to save size. + unsigned RegA = Is64Bit ? X86::RAX : X86::EAX; BuildMI(*MBB, I, DL, TII->get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) .addReg(RegA, RegState::Undef); } else { @@ -241,7 +243,11 @@ break; case Probe: if (!NoStackArgProbe) { - // The probe lowering expects the amount in RAX/EAX. + // The probe lowering expects the amount in RAX/EAX. Caveat: On the x32 + // ABI the alloca size will be in a 32-bit register, even though the + // target is 64-bit. + bool Is64BitAlloca = MI->getOpcode() == X86::WIN_ALLOCA_64; + unsigned RegA = Is64BitAlloca ? X86::RAX : X86::EAX; BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY), RegA) .addReg(MI->getOperand(0).getReg()); Index: llvm/test/CodeGen/X86/pr41477.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/pr41477.ll @@ -0,0 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnux32 | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnux32" + +define void @test(i32 %size) nounwind #0 { +; CHECK-LABEL: test: +; CHECK: # %bb.0: # %start +; CHECK-NEXT: pushq %rbp +; CHECK-NEXT: movl %esp, %ebp +; CHECK-NEXT: # kill: def $edi killed $edi def $rdi +; CHECK-NEXT: leal 15(%rdi), %eax +; CHECK-NEXT: andl $-16, %eax +; CHECK-NEXT: # kill: def $eax killed $eax def $rax +; CHECK-NEXT: callq __rust_probestack +; CHECK-NEXT: subq %rax, %rsp +start: + %unsized_tmp = alloca i8, i32 %size + unreachable +} + +attributes #0 = { "probe-stack"="__rust_probestack" }