[llvm] r245218 - [WinEHPrepare] Fix catchret successor phi demotion
Joseph Tremoulet via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 17 06:51:37 PDT 2015
Author: josepht
Date: Mon Aug 17 08:51:37 2015
New Revision: 245218
URL: http://llvm.org/viewvc/llvm-project?rev=245218&view=rev
Log:
[WinEHPrepare] Fix catchret successor phi demotion
Summary:
When demoting an SSA value that has a use on a phi and one of the phi's
predecessors terminates with catchret, the edge needs to be split and the
load inserted in the new block, else we'll still have a cross-funclet SSA
value.
Add a test for this, and for the similar case where a def to be spilled is
on and invoke and a critical edge, which was already implemented but
missing a test.
Reviewers: majnemer
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D12065
Modified:
llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll
Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=245218&r1=245217&r2=245218&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Mon Aug 17 08:51:37 2015
@@ -3289,6 +3289,42 @@ void WinEHPrepare::replaceUseWithLoad(Va
// coming in from the same block, which is illegal SSA form.
// For this reason, we keep track of and reuse loads we insert.
BasicBlock *IncomingBlock = UsingPHI->getIncomingBlock(U);
+ if (auto *CatchRet =
+ dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) {
+ // Putting a load above a catchret and use on the phi would still leave
+ // a cross-funclet def/use. We need to split the edge, change the
+ // catchret to target the new block, and put the load there.
+ BasicBlock *PHIBlock = UsingInst->getParent();
+ BasicBlock *NewBlock = SplitEdge(IncomingBlock, PHIBlock);
+ // SplitEdge gives us:
+ // IncomingBlock:
+ // ...
+ // br label %NewBlock
+ // NewBlock:
+ // catchret label %PHIBlock
+ // But we need:
+ // IncomingBlock:
+ // ...
+ // catchret label %NewBlock
+ // NewBlock:
+ // br label %PHIBlock
+ // So move the terminators to each others' blocks and swap their
+ // successors.
+ BranchInst *Goto = cast<BranchInst>(IncomingBlock->getTerminator());
+ Goto->removeFromParent();
+ CatchRet->removeFromParent();
+ IncomingBlock->getInstList().push_back(CatchRet);
+ NewBlock->getInstList().push_back(Goto);
+ Goto->setSuccessor(0, PHIBlock);
+ CatchRet->setSuccessor(NewBlock);
+ // Update the color mapping for the newly split edge.
+ std::set<BasicBlock *> &ColorsForPHIBlock = BlockColors[PHIBlock];
+ BlockColors[NewBlock] = ColorsForPHIBlock;
+ for (BasicBlock *FuncletPad : ColorsForPHIBlock)
+ FuncletBlocks[FuncletPad].insert(NewBlock);
+ // Treat the new block as incoming for load insertion.
+ IncomingBlock = NewBlock;
+ }
Value *&Load = Loads[IncomingBlock];
// Insert the load into the predecessor block
if (!Load)
Modified: llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll?rev=245218&r1=245217&r2=245218&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll Mon Aug 17 08:51:37 2015
@@ -294,3 +294,89 @@ catchend:
exit:
ret void
}
+
+; 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
+ %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:
+ cleanuppad void []
+ cleanupret void unwind to caller
+loop:
+ invoke void @f()
+ to label %loop unwind label %cleanup
+cleanup:
+ ; CHECK: cleanup:
+ ; CHECK: [[Load:%[^ ]+]] = load i32, i32* [[SpillSlot]]
+ ; CHECK: call void @h(i32 [[Load]])
+ cleanuppad void []
+ call void @h(i32 %x)
+ cleanupret void unwind to caller
+}
+
+; CHECK-LABEL: @test7(
+define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+ ; %x is an EH pad phi, so gets stored in pred here
+ ; CHECK: entry:
+ ; CHECK: store i32 1, i32* [[SlotX:%[^ ]+]]
+ ; CHECK: invoke void @f()
+ invoke void @f()
+ to label %invoke.cont unwind label %catchpad
+invoke.cont:
+ ; %x is an EH pad phi, so gets stored in pred here
+ ; CHECK: invoke.cont:
+ ; CHECK: store i32 2, i32* [[SlotX]]
+ ; CHECK: invoke void @f()
+ invoke void @f()
+ to label %exit unwind label %catchpad
+catchpad:
+ ; %x phi should be eliminated
+ ; CHECK: catchpad:
+ ; CHECK-NEXT: catchpad void
+ %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
+ catchpad void [] to label %catch unwind label %catchend
+catch:
+ %b = call i1 @i()
+ br i1 %b, label %left, label %right
+left:
+ ; Edge from %left to %join needs to be split so that
+ ; the load of %x can be inserted *after* the catchret
+ ; CHECK: left:
+ ; CHECK-NEXT: catchret void to label %[[SplitLeft:[^ ]+]]
+ catchret void to label %join
+ ; CHECK: [[SplitLeft]]:
+ ; CHECK: [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
+ ; CHECK: br label %join
+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 void to label %[[SplitRight:[^ ]+]]
+ %y = call i32 @g()
+ catchret void 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]] ]
+ %phi = phi i32 [ %x, %left ], [ %y, %right ]
+ call void @h(i32 %phi)
+ br label %exit
+exit:
+ ret void
+}
More information about the llvm-commits
mailing list