llvm.org GIT mirror llvm / d5ab13d
[WinEH] Update catchrets with cloned successors Summary: Add a pass to update catchrets when their successors get cloned; the existing pass doesn't catch these because it walks the funclet whose blocks are being cloned but the catchret is in a child funclet. Also update the test for removing incoming PHI values; when the predecessor is a catchret, the relevant color is the catchret's parentPad, not its block's color. Reviewers: andrew.w.kaylor, rnk, majnemer Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D15840 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256689 91177308-0d34-0410-b5e6-96231b3b80d8 Joseph Tremoulet 4 years ago
2 changed file(s) with 83 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
597597 for (auto &Funclets : FuncletBlocks) {
598598 BasicBlock *FuncletPadBB = Funclets.first;
599599 std::vector &BlocksInFunclet = Funclets.second;
600 Value *FuncletToken;
601 if (FuncletPadBB == &F.getEntryBlock())
602 FuncletToken = ConstantTokenNone::get(F.getContext());
603 else
604 FuncletToken = FuncletPadBB->getFirstNonPHI();
600605
601606 std::vector> Orig2Clone;
602607 ValueToValueMapTy VMap;
668673 RemapInstruction(&I, VMap,
669674 RF_IgnoreMissingEntries | RF_NoModuleLevelChanges);
670675
676 // Catchrets targeting cloned blocks need to be updated separately from
677 // the loop above because they are not in the current funclet.
678 SmallVector FixupCatchrets;
679 for (auto &BBMapping : Orig2Clone) {
680 BasicBlock *OldBlock = BBMapping.first;
681 BasicBlock *NewBlock = BBMapping.second;
682
683 FixupCatchrets.clear();
684 for (BasicBlock *Pred : predecessors(OldBlock))
685 if (auto *CatchRet = dyn_cast(Pred->getTerminator()))
686 if (CatchRet->getParentPad() == FuncletToken)
687 FixupCatchrets.push_back(CatchRet);
688
689 for (CatchReturnInst *CatchRet : FixupCatchrets)
690 CatchRet->setSuccessor(NewBlock);
691 }
692
671693 auto UpdatePHIOnClonedBlock = [&](PHINode *PN, bool IsForOldBlock) {
672694 unsigned NumPreds = PN->getNumIncomingValues();
673695 for (unsigned PredIdx = 0, PredEnd = NumPreds; PredIdx != PredEnd;
674696 ++PredIdx) {
675697 BasicBlock *IncomingBlock = PN->getIncomingBlock(PredIdx);
676 ColorVector &IncomingColors = BlockColors[IncomingBlock];
677 bool BlockInFunclet = IncomingColors.size() == 1 &&
678 IncomingColors.front() == FuncletPadBB;
679 if (IsForOldBlock != BlockInFunclet)
698 bool EdgeTargetsFunclet;
699 if (auto *CRI =
700 dyn_cast(IncomingBlock->getTerminator())) {
701 EdgeTargetsFunclet = (CRI->getParentPad() == FuncletToken);
702 } else {
703 ColorVector &IncomingColors = BlockColors[IncomingBlock];
704 assert(!IncomingColors.empty() && "Block not colored!");
705 assert((IncomingColors.size() == 1 ||
706 llvm::all_of(IncomingColors,
707 [&](BasicBlock *Color) {
708 return Color != FuncletPadBB;
709 })) &&
710 "Cloning should leave this funclet's blocks monochromatic");
711 EdgeTargetsFunclet = (IncomingColors.front() == FuncletPadBB);
712 }
713 if (IsForOldBlock != EdgeTargetsFunclet)
680714 continue;
681715 PN->removeIncomingValue(IncomingBlock, /*DeletePHIIfEmpty=*/false);
682716 // Revisit the next entry.
11
22 declare i32 @__CxxFrameHandler3(...)
33 declare i32 @__C_specific_handler(...)
4 declare void @ProcessCLRException(...)
45
56 declare void @f()
67
368369 unreachable
369370 }
370371
372 define void @test14() personality void (...)* @ProcessCLRException {
373 entry:
374 invoke void @f()
375 to label %cont unwind label %cleanup
376 cont:
377 invoke void @f()
378 to label %exit unwind label %switch.outer
379 cleanup:
380 %cleanpad = cleanuppad within none []
381 invoke void @f() [ "funclet" (token %cleanpad) ]
382 to label %cleanret unwind label %switch.inner
383 switch.inner:
384 %cs.inner = catchswitch within %cleanpad [label %pad.inner] unwind to caller
385 pad.inner:
386 %cp.inner = catchpad within %cs.inner [i32 1]
387 catchret from %cp.inner to label %join
388 cleanret:
389 cleanupret from %cleanpad unwind to caller
390 switch.outer:
391 %cs.outer = catchswitch within none [label %pad.outer] unwind to caller
392 pad.outer:
393 %cp.outer = catchpad within %cs.outer [i32 2]
394 catchret from %cp.outer to label %join
395 join:
396 %phi = phi i32 [ 1, %pad.inner ], [ 2, %pad.outer ]
397 call void @llvm.foo(i32 %phi)
398 unreachable
399 exit:
400 ret void
401 }
402 ; Both catchrets target %join, but the catchret from %cp.inner
403 ; returns to %cleanpad and the catchret from %cp.outer returns to the
404 ; main function, so %join needs to get cloned and one of the cleanuprets
405 ; needs to be updated to target the clone
406 ; CHECK-LABEL: define void @test14()
407 ; CHECK: catchret from %cp.inner to label %[[Clone1:.+]]
408 ; CHECK: catchret from %cp.outer to label %[[Clone2:.+]]
409 ; CHECK: [[Clone1]]:
410 ; CHECK-NEXT: call void @llvm.foo(i32 1)
411 ; CHECK-NEXT: unreachable
412 ; CHECK: [[Clone2]]:
413 ; CHECK-NEXT: call void @llvm.foo(i32 2)
414 ; CHECK-NEXT: unreachable
415
371416 ;; Debug info (from test12)
372417
373418 ; Make sure the DISubprogram doesn't get cloned