Index: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ lib/CodeGen/PrologEpilogInserter.cpp @@ -709,10 +709,6 @@ SmallVector ObjectsToAllocate; - int EHRegNodeFrameIndex = INT_MAX; - if (const WinEHFuncInfo *FuncInfo = Fn.getWinEHFuncInfo()) - EHRegNodeFrameIndex = FuncInfo->EHRegNodeFrameIndex; - // Then prepare to assign frame offsets to stack objects that are not used to // spill callee saved registers. for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { @@ -727,8 +723,6 @@ continue; if (MFI->getStackProtectorIndex() == (int)i) continue; - if (EHRegNodeFrameIndex == (int)i) - continue; if (ProtectedObjs.count(i)) continue; @@ -736,16 +730,9 @@ ObjectsToAllocate.push_back(i); } - // Allocate the EH registration node first if one is present. - if (EHRegNodeFrameIndex != INT_MAX) - AdjustStackOffset(MFI, EHRegNodeFrameIndex, StackGrowsDown, Offset, - MaxAlign, Skew); - // Give the targets a chance to order the objects the way they like it. - if (Fn.getTarget().getOptLevel() != CodeGenOpt::None && - Fn.getTarget().Options.StackSymbolOrdering) - TFI.orderFrameObjects(Fn, ObjectsToAllocate); - + TFI.orderFrameObjects(Fn, ObjectsToAllocate); + // Now walk the objects and actually assign base offsets to them. for (auto &Object : ObjectsToAllocate) AdjustStackOffset(MFI, Object, StackGrowsDown, Offset, MaxAlign, Skew); Index: lib/Target/X86/X86FrameLowering.h =================================================================== --- lib/Target/X86/X86FrameLowering.h +++ lib/Target/X86/X86FrameLowering.h @@ -165,6 +165,8 @@ bool RestoreSP = false) const; private: + void optimizeFrameObjects(const MachineFunction &MF, + SmallVectorImpl &ObjectsToAllocate) const; uint64_t calculateMaxStackAlign(const MachineFunction &MF) const; /// Emit target stack probe as a call to a helper function Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -2741,14 +2741,10 @@ // We want to place the local stack objects in some sort of sensible order. // The heuristic we use is to try and pack them according to static number // of uses and size of object in order to minimize code size. -void X86FrameLowering::orderFrameObjects( +void X86FrameLowering::optimizeFrameObjects( const MachineFunction &MF, SmallVectorImpl &ObjectsToAllocate) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); - // Don't waste time if there's nothing to do. - if (ObjectsToAllocate.empty()) - return; - // Create an array of all MFI objects. We won't need all of these // objects, but we're going to create a full array of them to make // it easier to index into when we're counting "uses" down below. @@ -2811,6 +2807,88 @@ std::reverse(ObjectsToAllocate.begin(), ObjectsToAllocate.end()); } +void X86FrameLowering::orderFrameObjects( + const MachineFunction &MF, SmallVectorImpl &ObjectsToAllocate) const { + // Don't waste time if there's nothing to do. + if (ObjectsToAllocate.empty()) + return; + + if (MF.getTarget().getOptLevel() != CodeGenOpt::None && + MF.getTarget().Options.StackSymbolOrdering) + optimizeFrameObjects(MF, ObjectsToAllocate); + + // We might need to re-order the objects to handle WinEH constraints. + const WinEHFuncInfo *FuncInfo = MF.getWinEHFuncInfo(); + if (!FuncInfo) + return; + + // Gather up all the catch objects' frame indicies in the function. + SmallSet CatchObjects; + for (const WinEHTryBlockMapEntry &TBME : FuncInfo->TryBlockMap) + for (const WinEHHandlerType &HT : TBME.HandlerArray) + if (HT.CatchObj.FrameIndex != INT_MAX) + CatchObjects.insert(HT.CatchObj.FrameIndex); + + // No catch objects? Nothing to re-order. + if (CatchObjects.empty()) + return; + + // Make sure the EH registration node comes before the catch objects. + int EHRegNodeFrameIndex = FuncInfo->EHRegNodeFrameIndex; + if (EHRegNodeFrameIndex != INT_MAX) { + // Find the earliest catch object. + auto EarliestCatchObject = ObjectsToAllocate.end(); + for (int &Object : ObjectsToAllocate) { + if (CatchObjects.count(Object) > 0) { + EarliestCatchObject = &Object; + break; + } + } + // Find the EH registration node. + auto EHNodeIter = find(ObjectsToAllocate, EHRegNodeFrameIndex); + if (EHNodeIter > EarliestCatchObject) { + // Move the EH registration node after the before the first catch object. + ObjectsToAllocate.erase(EHNodeIter); + ObjectsToAllocate.insert(EarliestCatchObject, EHRegNodeFrameIndex); + } + } + + // Avoid having a catch object at the top of the stack relative to RSP at the + // end of the prologue. + const MachineFrameInfo *MFI = MF.getFrameInfo(); + if (STI.isTargetWin64() && MFI->hasVarSizedObjects()) { + // Find the last catch object and normal object. + auto LastCatchObject = ObjectsToAllocate.end(); + auto LastNonCatchObject = ObjectsToAllocate.end(); + for (int &Object : reverse(ObjectsToAllocate)) { + // Skip dynamic stack allocations. + if (MFI->isVariableSizedObjectIndex(Object)) + continue; + if (CatchObjects.count(Object) != 0) { + if (LastCatchObject == ObjectsToAllocate.end()) + LastCatchObject = &Object; + } else { + if (LastNonCatchObject == ObjectsToAllocate.end()) + LastNonCatchObject = &Object; + } + + if (LastCatchObject != ObjectsToAllocate.end() && + LastNonCatchObject != ObjectsToAllocate.end()) + break; + } + + assert(LastCatchObject != ObjectsToAllocate.end() && "no catch object!"); + + // Swap the last catch object with the last normal object if the catch + // object came after it. + if (LastNonCatchObject != ObjectsToAllocate.end()) { + if (LastCatchObject > LastNonCatchObject) + std::swap(*LastCatchObject, *LastNonCatchObject); + } else { + } + } +} + unsigned X86FrameLowering::getWinEHParentFrameOffset(const MachineFunction &MF) const { // RDX, the parent frame pointer, is homed into 16(%rsp) in the prologue. Index: test/CodeGen/X86/catchpad-dynamic-alloca.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/catchpad-dynamic-alloca.ll @@ -0,0 +1,60 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +declare void @rt_init() + +declare i32 @__CxxFrameHandler3(...) + +define void @test1(void ()* %fp, i64 %n) personality i32 (...)* @__CxxFrameHandler3 { +entry: + %t.i = alloca i8* + %t.ii = alloca i8 + %.alloca8 = alloca i8, i64 %n + store volatile i8 0, i8* %t.ii + store volatile i8 0, i8* %.alloca8 + invoke void @rt_init() + to label %try.cont unwind label %catch.switch + +try.cont: + invoke void %fp() + to label %exit unwind label %catch.switch + +exit: + ret void + +catch.pad: + %cp = catchpad within %cs [i8* null, i32 0, i8** %t.i] + catchret from %cp to label %exit + +catch.switch: + %cs = catchswitch within none [label %catch.pad] unwind to caller +} + +; CHECK-LABEL: $handlerMap$0$test1: +; CHECK: .long 0 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 8 + +; FIXME: define void @test2(void ()* %fp, i64 %n) personality i32 (...)* @__CxxFrameHandler3 { +; FIXME: entry: +; FIXME: %t.i = alloca i128 +; FIXME: %.alloca8 = alloca i8, i64 %n +; FIXME: store volatile i8 0, i8* %.alloca8 +; FIXME: invoke void @rt_init() +; FIXME: to label %try.cont unwind label %catch.switch +; FIXME: +; FIXME: try.cont: +; FIXME: invoke void %fp() +; FIXME: to label %exit unwind label %catch.switch +; FIXME: +; FIXME: exit: +; FIXME: ret void +; FIXME: +; FIXME: catch.pad: +; FIXME: %cp = catchpad within %cs [i8* null, i32 0, i128* %t.i] +; FIXME: catchret from %cp to label %exit +; FIXME: +; FIXME: catch.switch: +; FIXME: %cs = catchswitch within none [label %catch.pad] unwind to caller +; FIXME: } Index: test/CodeGen/X86/cleanuppad-inalloca.ll =================================================================== --- test/CodeGen/X86/cleanuppad-inalloca.ll +++ test/CodeGen/X86/cleanuppad-inalloca.ll @@ -52,7 +52,7 @@ ; CHECK: "?dtor$2@?0?passes_two@4HA": ; CHECK: pushl %ebp ; CHECK: subl $8, %esp -; CHECK: addl $12, %ebp +; CHECK: addl $16, %ebp ; CHECK: {{movl|leal}} -{{[0-9]+}}(%ebp), %ecx ; CHECK: calll "??1A@@QAE@XZ" ; CHECK: addl $8, %esp