diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index cf7a4ce4bed..040b91a4e1d 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -250,7 +250,7 @@ void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, } } - uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset; + uint64_t ThisVal = std::min(Offset, Chunk); if (ThisVal == (Is64BitTarget ? 8 : 4)) { // Use push / pop instead. unsigned Reg = isSub @@ -980,8 +980,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, bool Is64Bit = STI.is64Bit(); // standard x86_64 and NaCl use 64-bit frame/stack pointers, x32 - 32-bit. const bool Uses64BitFramePtr = STI.isTarget64BitLP64() || STI.isTargetNaCl64(); + bool HasFP = hasFP(MF); const bool Is64BitILP32 = STI.isTarget64BitILP32(); - bool UseLEA = STI.useLeaForSP(); unsigned SlotSize = RegInfo->getSlotSize(); unsigned FramePtr = RegInfo->getFrameRegister(MF); unsigned MachineFramePtr = @@ -991,6 +991,20 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, bool IsWinEH = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); bool NeedsWinEH = IsWinEH && MF.getFunction()->needsUnwindTableEntry(); + bool UseLEAForSP = false; + + // We can't use LEA instructions for adjusting the stack pointer if this is a + // leaf function in the Win64 ABI. Only ADD instructions may be used to + // deallocate the stack. + if (STI.useLeaForSP()) { + if (!IsWinEH) { + // We *aren't* using the Win64 ABI which means we are free to use LEA. + UseLEAForSP = true; + } else if (HasFP) { + // We *have* a frame pointer which means we are permitted to use LEA. + UseLEAForSP = true; + } + } switch (RetOpcode) { default: @@ -1084,8 +1098,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, } } else if (NumBytes) { // Adjust stack pointer back: ESP += numbytes. - emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, Uses64BitFramePtr, UseLEA, - TII, *RegInfo); + emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, Uses64BitFramePtr, + UseLEAForSP, TII, *RegInfo); --MBBI; } @@ -1131,7 +1145,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, // Check for possible merge with preceding ADD instruction. Offset += mergeSPUpdates(MBB, MBBI, StackPtr, true); emitSPUpdate(MBB, MBBI, StackPtr, Offset, Is64Bit, Uses64BitFramePtr, - UseLEA, TII, *RegInfo); + UseLEAForSP, TII, *RegInfo); } // Jump to label or value in register. @@ -1179,8 +1193,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, // Check for possible merge with preceding ADD instruction. delta += mergeSPUpdates(MBB, MBBI, StackPtr, true); - emitSPUpdate(MBB, MBBI, StackPtr, delta, Is64Bit, Uses64BitFramePtr, UseLEA, TII, - *RegInfo); + emitSPUpdate(MBB, MBBI, StackPtr, delta, Is64Bit, Uses64BitFramePtr, + UseLEAForSP, TII, *RegInfo); } } diff --git a/test/CodeGen/X86/win64_eh.ll b/test/CodeGen/X86/win64_eh.ll index 76d3e86003d..597127a6998 100644 --- a/test/CodeGen/X86/win64_eh.ll +++ b/test/CodeGen/X86/win64_eh.ll @@ -1,5 +1,6 @@ -; RUN: llc < %s -O0 -mattr=sse2 -mtriple=x86_64-pc-windows-itanium | FileCheck %s -check-prefix=WIN64 -; RUN: llc < %s -O0 -mattr=sse2 -mtriple=x86_64-pc-mingw32 | FileCheck %s -check-prefix=WIN64 +; RUN: llc < %s -O0 -mattr=sse2 -mtriple=x86_64-pc-windows-itanium | FileCheck %s -check-prefix=WIN64 -check-prefix=NORM +; RUN: llc < %s -O0 -mattr=sse2 -mtriple=x86_64-pc-mingw32 | FileCheck %s -check-prefix=WIN64 -check-prefix=NORM +; RUN: llc < %s -O0 -mattr=sse2 -mtriple=x86_64-pc-mingw32 -mcpu=atom | FileCheck %s -check-prefix=WIN64 -check-prefix=ATOM ; Check function without prolog define void @foo0() uwtable { @@ -20,7 +21,8 @@ entry: } ; WIN64-LABEL: foo1: ; WIN64: .seh_proc foo1 -; WIN64: subq $4000, %rsp +; NORM: subq $4000, %rsp +; ATOM: leaq -4000(%rsp), %rsp ; WIN64: .seh_stackalloc 4000 ; WIN64: .seh_endprologue ; WIN64: addq $4000, %rsp @@ -83,7 +85,8 @@ entry: ; WIN64: .seh_proc foo3 ; WIN64: pushq %rsi ; WIN64: .seh_pushreg 6 -; WIN64: subq $24, %rsp +; NORM: subq $24, %rsp +; ATOM: leaq -24(%rsp), %rsp ; WIN64: .seh_stackalloc 24 ; WIN64: .seh_endprologue ; WIN64: addq $24, %rsp @@ -126,7 +129,8 @@ endtryfinally: ; WIN64-LABEL: foo4: ; WIN64: .seh_proc foo4 ; WIN64: .seh_handler _d_eh_personality, @unwind, @except -; WIN64: subq $56, %rsp +; NORM: subq $56, %rsp +; ATOM: leaq -56(%rsp), %rsp ; WIN64: .seh_stackalloc 56 ; WIN64: .seh_endprologue ; WIN64: addq $56, %rsp @@ -150,7 +154,8 @@ entry: ; WIN64: .seh_pushreg 7 ; WIN64: pushq %rbx ; WIN64: .seh_pushreg 3 -; WIN64: subq $96, %rsp +; NORM: subq $96, %rsp +; ATOM: leaq -96(%rsp), %rsp ; WIN64: .seh_stackalloc 96 ; WIN64: leaq 96(%rsp), %rbp ; WIN64: .seh_setframe 5, 96