diff options
-rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 122 | ||||
-rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-cloning.ll | 18 | ||||
-rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-demotion.ll | 66 | ||||
-rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll | 65 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/win-catchpad-varargs.ll | 66 |
5 files changed, 81 insertions, 256 deletions
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 87713f65671..f3f4e3be389 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -69,8 +69,6 @@ private: AllocaInst *insertPHILoads(PHINode *PN, Function &F); void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot, DenseMap<BasicBlock *, Value *> &Loads, Function &F); - void demoteNonlocalUses(Value *V, SetVector<BasicBlock *> &ColorsForBB, - Function &F); bool prepareExplicitEH(Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks); void replaceTerminatePadWithCleanup(Function &F); @@ -90,8 +88,6 @@ private: std::map<BasicBlock *, BasicBlock *> &Orig2Clone); void demotePHIsOnFunclets(Function &F); - void demoteUsesBetweenFunclets(Function &F); - void demoteArgumentUses(Function &F); void cloneCommonBlocks(Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks); void removeImplausibleTerminators(Function &F); @@ -1588,30 +1584,6 @@ void WinEHPrepare::demotePHIsOnFunclets(Function &F) { } } -void WinEHPrepare::demoteUsesBetweenFunclets(Function &F) { - // Turn all inter-funclet uses of a Value into loads and stores. - for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) { - BasicBlock *BB = &*FI++; - SetVector<BasicBlock *> &ColorsForBB = BlockColors[BB]; - for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { - Instruction *I = &*BI++; - // Funclets are permitted to use static allocas. - if (auto *AI = dyn_cast<AllocaInst>(I)) - if (AI->isStaticAlloca()) - continue; - - demoteNonlocalUses(I, ColorsForBB, F); - } - } -} - -void WinEHPrepare::demoteArgumentUses(Function &F) { - // Also demote function parameters used in funclets. - SetVector<BasicBlock *> &ColorsForEntry = BlockColors[&F.getEntryBlock()]; - for (Argument &Arg : F.args()) - demoteNonlocalUses(&Arg, ColorsForEntry, F); -} - void WinEHPrepare::cloneCommonBlocks( Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks) { // We need to clone all blocks which belong to multiple funclets. Values are @@ -1914,12 +1886,10 @@ void WinEHPrepare::verifyPreparedFunclets(Function &F) { report_fatal_error("Uncolored BB!"); if (NumColors > 1) report_fatal_error("Multicolor BB!"); - if (!DisableDemotion) { - bool EHPadHasPHI = BB.isEHPad() && isa<PHINode>(BB.begin()); - assert(!EHPadHasPHI && "EH Pad still has a PHI!"); - if (EHPadHasPHI) - report_fatal_error("EH Pad still has a PHI!"); - } + bool EHPadHasPHI = BB.isEHPad() && isa<PHINode>(BB.begin()); + assert(!EHPadHasPHI && "EH Pad still has a PHI!"); + if (EHPadHasPHI) + report_fatal_error("EH Pad still has a PHI!"); } } @@ -1930,14 +1900,9 @@ bool WinEHPrepare::prepareExplicitEH( // Determine which blocks are reachable from which funclet entries. colorFunclets(F, EntryBlocks); - if (!DisableDemotion) { + if (!DisableDemotion) demotePHIsOnFunclets(F); - demoteUsesBetweenFunclets(F); - - demoteArgumentUses(F); - } - cloneCommonBlocks(F, EntryBlocks); resolveFuncletAncestry(F, EntryBlocks); @@ -2050,83 +2015,6 @@ void WinEHPrepare::insertPHIStore( new StoreInst(PredVal, SpillSlot, PredBlock->getTerminator()); } -// The SetVector == operator uses the std::vector == operator, so it doesn't -// actually tell us whether or not the two sets contain the same colors. This -// function does that. -// FIXME: Would it be better to add a isSetEquivalent() method to SetVector? -static bool isBlockColorSetEquivalent(SetVector<BasicBlock *> &SetA, - SetVector<BasicBlock *> &SetB) { - if (SetA.size() != SetB.size()) - return false; - for (auto *Color : SetA) - if (!SetB.count(Color)) - return false; - return true; -} - -// TODO: Share loads for same-funclet uses (requires dominators if funclets -// aren't properly nested). -void WinEHPrepare::demoteNonlocalUses(Value *V, - SetVector<BasicBlock *> &ColorsForBB, - Function &F) { - // Tokens can only be used non-locally due to control flow involving - // unreachable edges. Don't try to demote the token usage, we'll simply - // delete the cloned user later. - if (isa<CatchPadInst>(V) || isa<CleanupPadInst>(V)) - return; - - DenseMap<BasicBlock *, Value *> Loads; - AllocaInst *SpillSlot = nullptr; - for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;) { - Use &U = *UI++; - auto *UsingInst = cast<Instruction>(U.getUser()); - BasicBlock *UsingBB = UsingInst->getParent(); - - // Is the Use inside a block which is colored the same as the Def? - // If so, we don't need to escape the Def because we will clone - // ourselves our own private copy. - SetVector<BasicBlock *> &ColorsForUsingBB = BlockColors[UsingBB]; - if (isBlockColorSetEquivalent(ColorsForUsingBB, ColorsForBB)) - continue; - - replaceUseWithLoad(V, U, SpillSlot, Loads, F); - } - if (SpillSlot) { - // Insert stores of the computed value into the stack slot. - // We have to be careful if I is an invoke instruction, - // because we can't insert the store AFTER the terminator instruction. - BasicBlock::iterator InsertPt; - if (isa<Argument>(V)) { - InsertPt = F.getEntryBlock().getTerminator()->getIterator(); - } else if (isa<TerminatorInst>(V)) { - auto *II = cast<InvokeInst>(V); - // We cannot demote invoke instructions to the stack if their normal - // edge is critical. Therefore, split the critical edge and create a - // basic block into which the store can be inserted. - if (!II->getNormalDest()->getSinglePredecessor()) { - unsigned SuccNum = - GetSuccessorNumber(II->getParent(), II->getNormalDest()); - assert(isCriticalEdge(II, SuccNum) && "Expected a critical edge!"); - BasicBlock *NewBlock = SplitCriticalEdge(II, SuccNum); - assert(NewBlock && "Unable to split critical edge."); - // Update the color mapping for the newly split edge. - SetVector<BasicBlock *> &ColorsForUsingBB = BlockColors[II->getParent()]; - BlockColors[NewBlock] = ColorsForUsingBB; - for (BasicBlock *FuncletPad : ColorsForUsingBB) - FuncletBlocks[FuncletPad].insert(NewBlock); - } - InsertPt = II->getNormalDest()->getFirstInsertionPt(); - } else { - InsertPt = cast<Instruction>(V)->getIterator(); - ++InsertPt; - // Don't insert before PHI nodes or EH pad instrs. - for (; isa<PHINode>(InsertPt) || InsertPt->isEHPad(); ++InsertPt) - ; - } - new StoreInst(V, SpillSlot, &*InsertPt); - } -} - void WinEHPrepare::replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot, DenseMap<BasicBlock *, Value *> &Loads, Function &F) { diff --git a/llvm/test/CodeGen/WinEH/wineh-cloning.ll b/llvm/test/CodeGen/WinEH/wineh-cloning.ll index 58bf71e62b6..7d6529d6009 100644 --- a/llvm/test/CodeGen/WinEH/wineh-cloning.ll +++ b/llvm/test/CodeGen/WinEH/wineh-cloning.ll @@ -29,18 +29,16 @@ endcatch: ; for the use in entry's copy. ; CHECK-LABEL: define void @test1( ; CHECK: entry: -; CHECK: store i32 %x, i32* [[Slot:%[^ ]+]] +; CHECK: %x = call i32 @g() ; CHECK: invoke void @f() ; CHECK: to label %[[EntryCopy:[^ ]+]] unwind label %catch ; CHECK: catch: ; CHECK: catchpad [] ; CHECK-NEXT: to label %[[CatchCopy:[^ ]+]] unwind ; CHECK: [[CatchCopy]]: -; CHECK: [[LoadX2:%[^ ]+]] = load i32, i32* [[Slot]] -; CHECK: call void @h(i32 [[LoadX2]] +; CHECK: call void @h(i32 %x) ; CHECK: [[EntryCopy]]: -; CHECK: [[LoadX1:%[^ ]+]] = load i32, i32* [[Slot]] -; CHECK: call void @h(i32 [[LoadX1]] +; CHECK: call void @h(i32 %x) define void @test2() personality i32 (...)* @__CxxFrameHandler3 { @@ -281,12 +279,14 @@ exit: ; then calls @h, and that the call to @h doesn't return. ; CHECK-LABEL: define void @test6( ; CHECK: left: +; CHECK: %x.for.left = call i32 @g() +; CHECK: invoke void @f() ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] ; CHECK: right: +; CHECK: catchpad ; CHECK: to label %right.catch unwind label %right.end ; CHECK: right.catch: ; CHECK: %x = call i32 @g() -; CHECK: store i32 %x, i32* %x.wineh.spillslot ; CHECK: to label %shared.cont unwind label %[[INNER_RIGHT:.+]] ; CHECK: right.end: ; CHECK: catchendpad unwind to caller @@ -296,13 +296,11 @@ exit: ; CHECK: unreachable ; CHECK: [[INNER_RIGHT]]: ; CHECK: [[I_R:\%.+]] = cleanuppad [] -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: cleanupret [[I_R]] unwind label %right.end ; CHECK: [[INNER_LEFT]]: ; CHECK: [[I_L:\%.+]] = cleanuppad [] -; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_L]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable diff --git a/llvm/test/CodeGen/WinEH/wineh-demotion.ll b/llvm/test/CodeGen/WinEH/wineh-demotion.ll index e849a8ec80c..96f33b0ed1a 100644 --- a/llvm/test/CodeGen/WinEH/wineh-demotion.ll +++ b/llvm/test/CodeGen/WinEH/wineh-demotion.ll @@ -118,49 +118,6 @@ exit: ret void } -; CHECK-LABEL: @test3( -define void @test3(i1 %B) personality i32 (...)* @__CxxFrameHandler3 { -entry: - ; need to spill parameter %B and def %x since they're used in a funclet - ; CHECK: entry: - ; CHECK-DAG: store i1 %B, i1* [[SlotB:%[^ ]+]] - ; CHECK-DAG: store i32 %x, i32* [[SlotX:%[^ ]+]] - ; CHECK: invoke void @f - %x = call i32 @g() - invoke void @f() - to label %exit unwind label %catchpad - -catchpad: - %cp = catchpad [] to label %catch unwind label %catchend - -catch: - ; Need to reload %B here - ; CHECK: catch: - ; CHECK: [[ReloadB:%[^ ]+]] = load i1, i1* [[SlotB]] - ; CHECK: br i1 [[ReloadB]] - br i1 %B, label %left, label %right -left: - ; Use of %x is in a phi, so need reload here in pred - ; CHECK: left: - ; CHECK: [[ReloadX:%[^ ]+]] = load i32, i32* [[SlotX]] - ; CHECK: br label %merge - br label %merge -right: - br label %merge -merge: - ; CHECK: merge: - ; CHECK: %phi = phi i32 [ [[ReloadX]], %left ] - %phi = phi i32 [ %x, %left ], [ 42, %right ] - call void @h(i32 %phi) - catchret %cp to label %exit - -catchend: - catchendpad unwind to caller - -exit: - ret void -} - ; test4: don't need stores for %phi.inner, as its only use is to feed %phi.outer ; %phi.outer needs stores in %left, %right, and %join ; CHECK-LABEL: @test4( @@ -295,20 +252,15 @@ exit: ret void } +; We used to demote %x, but we don't need to anymore. ; CHECK-LABEL: @test6( define void @test6() personality i32 (...)* @__CxxFrameHandler3 { entry: - ; Since %x needs to be stored but the edge to loop is critical, - ; it needs to be split ; CHECK: entry: - ; CHECK: invoke i32 @g - ; CHECK-NEXT: to label %[[SplitBlock:[^ ]+]] unwind label %to_caller + ; CHECK: %x = invoke i32 @g() + ; CHECK-NEXT: to label %loop unwind label %to_caller %x = invoke i32 @g() to label %loop unwind label %to_caller - ; The store should be in the split block - ; CHECK: [[SplitBlock]]: - ; CHECK: store i32 %x, i32* [[SpillSlot:%[^ ]+]] - ; CHECK: br label %loop to_caller: %cp1 = cleanuppad [] cleanupret %cp1 unwind to caller @@ -317,8 +269,7 @@ loop: to label %loop unwind label %cleanup cleanup: ; CHECK: cleanup: - ; CHECK: [[Load:%[^ ]+]] = load i32, i32* [[SpillSlot]] - ; CHECK: call void @h(i32 [[Load]]) + ; CHECK: call void @h(i32 %x) %cp2 = cleanuppad [] call void @h(i32 %x) cleanupret %cp2 unwind to caller @@ -362,18 +313,15 @@ right: ; Edge from %right to %join needs to be split so that ; the load of %y can be inserted *after* the catchret ; CHECK: right: - ; CHECK: store i32 %y, i32* [[SlotY:%[^ ]+]] - ; CHECK: catchret %[[CatchPad]] to label %[[SplitRight:[^ ]+]] + ; CHECK: %y = call i32 @g() + ; CHECK: catchret %[[CatchPad]] to label %join %y = call i32 @g() catchret %cp to label %join - ; CHECK: [[SplitRight]]: - ; CHECK: [[LoadY:%[^ ]+]] = load i32, i32* [[SlotY]] - ; CHECK: br label %join catchend: catchendpad unwind to caller join: ; CHECK: join: - ; CHECK: %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ [[LoadY]], %[[SplitRight]] ] + ; CHECK: %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ] %phi = phi i32 [ %x, %left ], [ %y, %right ] call void @h(i32 %phi) br label %exit diff --git a/llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll b/llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll index 8c0aed04310..1e9342d17cb 100644 --- a/llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll +++ b/llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll @@ -51,12 +51,14 @@ exit: ; then calls @h, and that the call to @h doesn't return. ; CHECK-LABEL: define void @test1( ; CHECK: left: +; CHECK: cleanuppad +; CHECK: %x.for.left = call i32 @g() +; CHECK: invoke void @f() ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] ; CHECK: right: ; CHECK: to label %right.catch unwind label %right.end ; CHECK: right.catch: ; CHECK: %x = call i32 @g() -; CHECK: store i32 %x, i32* %x.wineh.spillslot ; CHECK: to label %shared.cont unwind label %[[INNER_RIGHT:.+]] ; CHECK: right.end: ; CHECK: catchendpad unwind to caller @@ -66,13 +68,11 @@ exit: ; CHECK: unreachable ; CHECK: [[INNER_RIGHT]]: ; CHECK: [[I_R:\%.+]] = cleanuppad [] -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: cleanupret [[I_R]] unwind label %right.end ; CHECK: [[INNER_LEFT]]: ; CHECK: [[I_L:\%.+]] = cleanuppad [] -; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_L]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable @@ -118,6 +118,9 @@ exit: ; %right.end (which belongs to the entry funclet). ; CHECK-LABEL: define void @test2( ; CHECK: left: +; CHECK: cleanuppad +; CHECK: %x.for.left = call i32 @g() +; CHECK: invoke void @f() ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] ; CHECK: right: ; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]] @@ -136,12 +139,10 @@ exit: ; CHECK: catchpad [] ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] ; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: unreachable ; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_L]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable ; CHECK: [[INNER_END_LEFT]]: ; CHECK: catchendpad unwind to caller @@ -190,6 +191,8 @@ exit: ; CHECK-LABEL: define void @test3( ; CHECK: left: ; CHECK: %l = cleanuppad [] +; CHECK: %x.for.left = call i32 @g() +; CHECK: invoke void @f() ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] ; CHECK: [[LEFT_END:left.end.*]]: ; CHECK: cleanupendpad %l unwind label %right @@ -210,12 +213,10 @@ exit: ; CHECK: catchpad [] ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] ; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: unreachable ; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable ; CHECK: [[INNER_END_LEFT]]: ; CHECK: catchendpad unwind label %[[LEFT_END]] @@ -270,6 +271,8 @@ exit: ; CHECK: catchpad [] ; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]] ; CHECK: left.catch: +; CHECK: %x.for.left = call i32 @g() +; CHECK: invoke void @f() ; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] ; CHECK: [[LEFT_END]]: ; CHECK: catchendpad unwind label %right @@ -290,12 +293,10 @@ exit: ; CHECK: catchpad [] ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] ; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: unreachable ; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_L]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable ; CHECK: [[INNER_END_RIGHT]]: ; CHECK: catchendpad unwind to caller @@ -362,12 +363,10 @@ exit: ; CHECK: catchpad [] ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] ; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: unreachable ; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_L]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable ; CHECK: [[INNER_END_RIGHT]]: ; CHECK: catchendpad unwind to caller @@ -446,12 +445,10 @@ exit: ; CHECK: catchpad [] ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] ; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: unreachable ; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_L]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable ; CHECK: [[INNER_END_RIGHT]]: ; CHECK: catchendpad unwind to caller @@ -522,12 +519,10 @@ exit: ; CHECK: catchpad [] ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] ; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: unreachable ; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_L]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable ; CHECK: [[INNER_END_RIGHT]]: ; CHECK: catchendpad unwind label %[[INNER_SIBLING_RIGHT:.+]] @@ -803,12 +798,10 @@ exit: ; CHECK: catchpad [] ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] ; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: unreachable ; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_L]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable ; CHECK: [[INNER_END_RIGHT]]: ; CHECK: catchendpad unwind to caller @@ -875,12 +868,10 @@ exit: ; CHECK: catchpad [] ; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] ; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_R]]) +; CHECK: call void @h(i32 %x) ; CHECK: unreachable ; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot -; CHECK: call void @h(i32 [[X_RELOAD_L]]) +; CHECK: call void @h(i32 %x.for.left) ; CHECK: unreachable ; CHECK: [[INNER_END_RIGHT]]: ; CHECK: catchendpad unwind label %[[RIGHT_END]] diff --git a/llvm/test/CodeGen/X86/win-catchpad-varargs.ll b/llvm/test/CodeGen/X86/win-catchpad-varargs.ll index 03c6c70dc69..a2988a3059e 100644 --- a/llvm/test/CodeGen/X86/win-catchpad-varargs.ll +++ b/llvm/test/CodeGen/X86/win-catchpad-varargs.ll @@ -35,40 +35,34 @@ return: ; preds = %entry, %catch ; X64-LABEL: .seh_proc f ; X64: pushq %rbp -; X64: pushq %rsi -; X64: subq $56, %rsp -; X64: leaq 48(%rsp), %rbp -; X64: movq $-2, (%rbp) +; X64: subq $64, %rsp +; X64: leaq 64(%rsp), %rbp +; X64: movq $-2, -8(%rbp) +; X64: movl $-1, -20(%rbp) # 4-byte Folded Spill ; X64: callq g -; X64: movl %esi, %eax -; X64: addq $56, %rsp -; X64: popq %rsi +; X64: .LBB0_1 +; X64: movl -20(%rbp), %eax # 4-byte Reload +; X64: addq $64, %rsp ; X64: popq %rbp -; X64: movl -4(%rbp), %esi -; X64: jmp - -; X64-LABEL: "?catch$1@?0?f@4HA": -; X64: .seh_proc "?catch$1@?0?f@4HA" +; X64-LABEL: "?catch${{[0-9]}}@?0?f@4HA": +; X64: .seh_proc "?catch${{[0-9]}}@?0?f@4HA" ; X64: movq %rdx, 16(%rsp) ; X64: pushq %rbp -; X64: pushq %rsi -; X64: subq $40, %rsp -; X64: leaq 48(%rdx), %rbp +; X64: subq $32, %rsp +; X64: leaq 64(%rdx), %rbp ; arg2 is at RBP+40: ; start at arg2 ; + 8 for arg1 ; + 8 for retaddr ; + 8 for RBP -; + 8 for RSI -; + 56 for stackalloc -; - 48 for setframe +; + 64 for stackalloc +; - 64 for setframe ; = 40 -; X64: movl 40(%rbp), %eax -; X64: movl %eax, -4(%rbp) -; X64: leaq .LBB0_2(%rip), %rax -; X64: addq $40, %rsp -; X64: popq %rsi +; X64: movl 24(%rbp), %eax +; X64: movl %eax, -20(%rbp) # 4-byte Spill +; X64: leaq .LBB0_1(%rip), %rax +; X64: addq $32, %rsp ; X64: popq %rbp ; X64: retq # CATCHRET @@ -78,27 +72,33 @@ return: ; preds = %entry, %catch ; X86: pushl %ebx ; X86: pushl %edi ; X86: pushl %esi -; X86: subl $28, %esp -; X86: movl $-1, -40(%ebp) +; X86: subl $24, %esp +; X86: movl $-1, -36(%ebp) ; X86: calll _g -; X86: movl -40(%ebp), %eax -; X86: addl $28, %esp +; X86: LBB0_[[retbb:[0-9]+]]: +; X86: movl -36(%ebp), %eax +; X86: addl $24, %esp ; X86: popl %esi ; X86: popl %edi ; X86: popl %ebx ; X86: popl %ebp ; X86: retl -; X86-LABEL: "?catch$1@?0?f@4HA": -; X86: pushl %ebp -; X86: addl $12, %ebp +; X86: LBB0_[[restorebb:[0-9]+]]: # Block address taken +; X86: addl $12, %ebp ; arg2 is at EBP offset 12: ; + 4 for arg1 ; + 4 for retaddr ; + 4 for EBP +; X86: movl 12(%ebp), %eax +; X86: movl %eax, -36(%ebp) +; X86: jmp LBB0_[[retbb]] + +; X86-LABEL: "?catch${{[0-9]}}@?0?f@4HA": +; X86: pushl %ebp +; X86: addl $12, %ebp ; Done due to mov %esp, %ebp -; X86: movl 12(%ebp), %eax -; X86: movl %eax, -32(%ebp) -; X86: movl $LBB0_2, %eax +; X86: leal 12(%ebp), %eax +; X86: movl $LBB0_[[restorebb]], %eax ; X86: popl %ebp ; X86: retl # CATCHRET |