llvm.org GIT mirror llvm / a3ccaa9
[WebAssembly] Add functions for EHScopes Summary: There are functions using the term 'funclet' to refer to both 1. an EH scopes, the structure of BBs that starts with catchpad/cleanuppad and ends with catchret/cleanupret, and 2. a small function that gets outlined in AsmPrinter, which is the original meaning of 'funclet'. So far the two have been the same thing; EH scopes are always outlined in AsmPrinter as funclets at the end of the compilation pipeline. But now wasm also uses scope-based EH but does not outline those, so we now need to correctly distinguish those two use cases in functions. This patch splits `MachineBasicBlock::isFuncletEntry` into `isFuncletEntry` and `isEHScopeEntry`, and `MachineFunction::hasFunclets` into `hasFunclets` and `hasEHScopes`, in order to distinguish the two different use cases. And this also changes some uses of the term 'funclet' to 'scope' in `getFuncletMembership` and change the function name to `getEHScopeMembership` because this function is not about outlined funclets but about EH scope memberships. This change is in the same vein as D45559. Reviewers: majnemer, dschuff Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D47005 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@333045 91177308-0d34-0410-b5e6-96231b3b80d8 Heejin Ahn 2 years ago
8 changed file(s) with 63 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
123123 const TargetLoweringBase &TLI);
124124
125125 DenseMap
126 getFuncletMembership(const MachineFunction &MF);
126 getEHScopeMembership(const MachineFunction &MF);
127127
128128 } // End llvm namespace
129129
113113 /// Indicate that this basic block is potentially the target of an indirect
114114 /// branch.
115115 bool AddressTaken = false;
116
117 /// Indicate that this basic block is the entry block of an EH scope, i.e.,
118 /// the block that used to have a catchpad or cleanuppad instruction in the
119 /// LLVM IR.
120 bool IsEHScopeEntry = false;
116121
117122 /// Indicate that this basic block is the entry block of an EH funclet.
118123 bool IsEHFuncletEntry = false;
374379
375380 bool hasEHPadSuccessor() const;
376381
382 /// Returns true if this is the entry block of an EH scope, i.e., the block
383 /// that used to have a catchpad or cleanuppad instruction in the LLVM IR.
384 bool isEHScopeEntry() const { return IsEHScopeEntry; }
385
386 /// Indicates if this is the entry block of an EH scope, i.e., the block that
387 /// that used to have a catchpad or cleanuppad instruction in the LLVM IR.
388 void setIsEHScopeEntry(bool V = true) { IsEHScopeEntry = V; }
389
377390 /// Returns true if this is the entry block of an EH funclet.
378391 bool isEHFuncletEntry() const { return IsEHFuncletEntry; }
379392
318318
319319 bool CallsEHReturn = false;
320320 bool CallsUnwindInit = false;
321 bool HasEHScopes = false;
321322 bool HasEHFunclets = false;
322323
323324 /// List of C++ TypeInfo used.
759760 bool callsUnwindInit() const { return CallsUnwindInit; }
760761 void setCallsUnwindInit(bool b) { CallsUnwindInit = b; }
761762
763 bool hasEHScopes() const { return HasEHScopes; }
764 void setHasEHScopes(bool V) { HasEHScopes = V; }
765
762766 bool hasEHFunclets() const { return HasEHFunclets; }
763767 void setHasEHFunclets(bool V) { HasEHFunclets = V; }
764768
628628 return true;
629629 }
630630
631 static void collectFuncletMembers(
632 DenseMap &FuncletMembership, int Funclet,
633 const MachineBasicBlock *MBB) {
631 static void
632 collectEHScopeMembers(DenseMap &ScopeMembership,
633 int Scope, const MachineBasicBlock *MBB) {
634634 SmallVector Worklist = {MBB};
635635 while (!Worklist.empty()) {
636636 const MachineBasicBlock *Visiting = Worklist.pop_back_val();
637 // Don't follow blocks which start new funclets.
637 // Don't follow blocks which start new scopes.
638638 if (Visiting->isEHPad() && Visiting != MBB)
639639 continue;
640640
641 // Add this MBB to our funclet.
642 auto P = FuncletMembership.insert(std::make_pair(Visiting, Funclet));
641 // Add this MBB to our scope.
642 auto P = ScopeMembership.insert(std::make_pair(Visiting, Scope));
643643
644644 // Don't revisit blocks.
645645 if (!P.second) {
646 assert(P.first->second == Funclet && "MBB is part of two funclets!");
646 assert(P.first->second == Scope && "MBB is part of two scopes!");
647647 continue;
648648 }
649649
650 // Returns are boundaries where funclet transfer can occur, don't follow
650 // Returns are boundaries where scope transfer can occur, don't follow
651651 // successors.
652652 if (Visiting->isReturnBlock())
653653 continue;
658658 }
659659
660660 DenseMap
661 llvm::getFuncletMembership(const MachineFunction &MF) {
662 DenseMap FuncletMembership;
661 llvm::getEHScopeMembership(const MachineFunction &MF) {
662 DenseMap ScopeMembership;
663663
664664 // We don't have anything to do if there aren't any EH pads.
665 if (!MF.hasEHFunclets())
666 return FuncletMembership;
665 if (!MF.hasEHScopes())
666 return ScopeMembership;
667667
668668 int EntryBBNumber = MF.front().getNumber();
669669 bool IsSEH = isAsynchronousEHPersonality(
670670 classifyEHPersonality(MF.getFunction().getPersonalityFn()));
671671
672672 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
673 SmallVector FuncletBlocks;
673 SmallVector ScopeBlocks;
674674 SmallVector UnreachableBlocks;
675675 SmallVector SEHCatchPads;
676676 SmallVector, 16> CatchRetSuccessors;
677677 for (const MachineBasicBlock &MBB : MF) {
678 if (MBB.isEHFuncletEntry()) {
679 FuncletBlocks.push_back(&MBB);
678 if (MBB.isEHScopeEntry()) {
679 ScopeBlocks.push_back(&MBB);
680680 } else if (IsSEH && MBB.isEHPad()) {
681681 SEHCatchPads.push_back(&MBB);
682682 } else if (MBB.pred_empty()) {
685685
686686 MachineBasicBlock::const_iterator MBBI = MBB.getFirstTerminator();
687687
688 // CatchPads are not funclets for SEH so do not consider CatchRet to
689 // transfer control to another funclet.
688 // CatchPads are not scopes for SEH so do not consider CatchRet to
689 // transfer control to another scope.
690690 if (MBBI == MBB.end() || MBBI->getOpcode() != TII->getCatchReturnOpcode())
691691 continue;
692692
699699 }
700700
701701 // We don't have anything to do if there aren't any EH pads.
702 if (FuncletBlocks.empty())
703 return FuncletMembership;
702 if (ScopeBlocks.empty())
703 return ScopeMembership;
704704
705705 // Identify all the basic blocks reachable from the function entry.
706 collectFuncletMembers(FuncletMembership, EntryBBNumber, &MF.front());
707 // All blocks not part of a funclet are in the parent function.
706 collectEHScopeMembers(ScopeMembership, EntryBBNumber, &MF.front());
707 // All blocks not part of a scope are in the parent function.
708708 for (const MachineBasicBlock *MBB : UnreachableBlocks)
709 collectFuncletMembers(FuncletMembership, EntryBBNumber, MBB);
710 // Next, identify all the blocks inside the funclets.
711 for (const MachineBasicBlock *MBB : FuncletBlocks)
712 collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB);
713 // SEH CatchPads aren't really funclets, handle them separately.
709 collectEHScopeMembers(ScopeMembership, EntryBBNumber, MBB);
710 // Next, identify all the blocks inside the scopes.
711 for (const MachineBasicBlock *MBB : ScopeBlocks)
712 collectEHScopeMembers(ScopeMembership, MBB->getNumber(), MBB);
713 // SEH CatchPads aren't really scopes, handle them separately.
714714 for (const MachineBasicBlock *MBB : SEHCatchPads)
715 collectFuncletMembers(FuncletMembership, EntryBBNumber, MBB);
715 collectEHScopeMembers(ScopeMembership, EntryBBNumber, MBB);
716716 // Finally, identify all the targets of a catchret.
717717 for (std::pair CatchRetPair :
718718 CatchRetSuccessors)
719 collectFuncletMembers(FuncletMembership, CatchRetPair.second,
719 collectEHScopeMembers(ScopeMembership, CatchRetPair.second,
720720 CatchRetPair.first);
721 return FuncletMembership;
722 }
721 return ScopeMembership;
722 }
199199 }
200200
201201 // Recalculate funclet membership.
202 FuncletMembership = getFuncletMembership(MF);
202 FuncletMembership = getEHScopeMembership(MF);
203203
204204 bool MadeChangeThisIteration = true;
205205 while (MadeChangeThisIteration) {
12921292 // Make sure blocks are numbered in order
12931293 MF.RenumberBlocks();
12941294 // Renumbering blocks alters funclet membership, recalculate it.
1295 FuncletMembership = getFuncletMembership(MF);
1295 FuncletMembership = getEHScopeMembership(MF);
12961296
12971297 for (MachineFunction::iterator I = std::next(MF.begin()), E = MF.end();
12981298 I != E; ) {
4141
4242 bool FuncletLayout::runOnMachineFunction(MachineFunction &F) {
4343 DenseMap FuncletMembership =
44 getFuncletMembership(F);
44 getEHScopeMembership(F);
4545 if (FuncletMembership.empty())
4646 return false;
4747
225225 const Instruction *PadInst = BB.getFirstNonPHI();
226226 // If this is a non-landingpad EH pad, mark this function as using
227227 // funclets.
228 // FIXME: SEH catchpads do not create funclets, so we could avoid setting
229 // this in such cases in order to improve frame layout.
228 // FIXME: SEH catchpads do not create EH scope/funclets, so we could avoid
229 // setting this in such cases in order to improve frame layout.
230230 if (!isa(PadInst)) {
231 MF->setHasEHScopes(true);
231232 MF->setHasEHFunclets(true);
232233 MF->getFrameInfo().setHasOpaqueSPAdjustment(true);
233234 }
13781378 auto Pers = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn());
13791379 bool IsMSVCCXX = Pers == EHPersonality::MSVC_CXX;
13801380 bool IsCoreCLR = Pers == EHPersonality::CoreCLR;
1381 bool IsSEH = isAsynchronousEHPersonality(Pers);
13811382 MachineBasicBlock *CatchPadMBB = FuncInfo.MBB;
1383 if (!IsSEH)
1384 CatchPadMBB->setIsEHScopeEntry();
13821385 // In MSVC C++ and CoreCLR, catchblocks are funclets and need prologues.
13831386 if (IsMSVCCXX || IsCoreCLR)
13841387 CatchPadMBB->setIsEHFuncletEntry();
14261429
14271430 void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
14281431 // Don't emit any special code for the cleanuppad instruction. It just marks
1429 // the start of a funclet.
1432 // the start of an EH scope/funclet.
1433 FuncInfo.MBB->setIsEHScopeEntry();
14301434 FuncInfo.MBB->setIsEHFuncletEntry();
14311435 FuncInfo.MBB->setIsCleanupFuncletEntry();
14321436 }
14481452 classifyEHPersonality(FuncInfo.Fn->getPersonalityFn());
14491453 bool IsMSVCCXX = Personality == EHPersonality::MSVC_CXX;
14501454 bool IsCoreCLR = Personality == EHPersonality::CoreCLR;
1455 bool IsSEH = isAsynchronousEHPersonality(Personality);
14511456
14521457 while (EHPadBB) {
14531458 const Instruction *Pad = EHPadBB->getFirstNonPHI();
14601465 // Stop on cleanup pads. Cleanups are always funclet entries for all known
14611466 // personalities.
14621467 UnwindDests.emplace_back(FuncInfo.MBBMap[EHPadBB], Prob);
1468 UnwindDests.back().first->setIsEHScopeEntry();
14631469 UnwindDests.back().first->setIsEHFuncletEntry();
14641470 break;
14651471 } else if (auto *CatchSwitch = dyn_cast(Pad)) {
14691475 // For MSVC++ and the CLR, catchblocks are funclets and need prologues.
14701476 if (IsMSVCCXX || IsCoreCLR)
14711477 UnwindDests.back().first->setIsEHFuncletEntry();
1478 if (!IsSEH)
1479 UnwindDests.back().first->setIsEHScopeEntry();
14721480 }
14731481 NewEHPadBB = CatchSwitch->getUnwindDest();
14741482 } else {