diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index 1160b8275b1..d77aee66ed7 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -124,7 +124,7 @@ bool returnTypeIsEligibleForTailCall(const Function *F, const Instruction *I, const TargetLoweringBase &TLI); DenseMap -getFuncletMembership(const MachineFunction &MF); +getEHScopeMembership(const MachineFunction &MF); } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index c5241c0793f..c351b7228c9 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -115,6 +115,11 @@ private: /// branch. bool AddressTaken = false; + /// Indicate that this basic block is the entry block of an EH scope, i.e., + /// the block that used to have a catchpad or cleanuppad instruction in the + /// LLVM IR. + bool IsEHScopeEntry = false; + /// Indicate that this basic block is the entry block of an EH funclet. bool IsEHFuncletEntry = false; @@ -375,6 +380,14 @@ public: bool hasEHPadSuccessor() const; + /// Returns true if this is the entry block of an EH scope, i.e., the block + /// that used to have a catchpad or cleanuppad instruction in the LLVM IR. + bool isEHScopeEntry() const { return IsEHScopeEntry; } + + /// Indicates if this is the entry block of an EH scope, i.e., the block that + /// that used to have a catchpad or cleanuppad instruction in the LLVM IR. + void setIsEHScopeEntry(bool V = true) { IsEHScopeEntry = V; } + /// Returns true if this is the entry block of an EH funclet. bool isEHFuncletEntry() const { return IsEHFuncletEntry; } diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 296df8e8e37..fd0906770ba 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -319,6 +319,7 @@ class MachineFunction { bool CallsEHReturn = false; bool CallsUnwindInit = false; + bool HasEHScopes = false; bool HasEHFunclets = false; /// List of C++ TypeInfo used. @@ -760,6 +761,9 @@ public: bool callsUnwindInit() const { return CallsUnwindInit; } void setCallsUnwindInit(bool b) { CallsUnwindInit = b; } + bool hasEHScopes() const { return HasEHScopes; } + void setHasEHScopes(bool V) { HasEHScopes = V; } + bool hasEHFunclets() const { return HasEHFunclets; } void setHasEHFunclets(bool V) { HasEHFunclets = V; } diff --git a/lib/CodeGen/Analysis.cpp b/lib/CodeGen/Analysis.cpp index 0731ae57543..e7e4bc666d7 100644 --- a/lib/CodeGen/Analysis.cpp +++ b/lib/CodeGen/Analysis.cpp @@ -629,26 +629,26 @@ bool llvm::returnTypeIsEligibleForTailCall(const Function *F, return true; } -static void collectFuncletMembers( - DenseMap &FuncletMembership, int Funclet, - const MachineBasicBlock *MBB) { +static void +collectEHScopeMembers(DenseMap &ScopeMembership, + int Scope, const MachineBasicBlock *MBB) { SmallVector Worklist = {MBB}; while (!Worklist.empty()) { const MachineBasicBlock *Visiting = Worklist.pop_back_val(); - // Don't follow blocks which start new funclets. + // Don't follow blocks which start new scopes. if (Visiting->isEHPad() && Visiting != MBB) continue; - // Add this MBB to our funclet. - auto P = FuncletMembership.insert(std::make_pair(Visiting, Funclet)); + // Add this MBB to our scope. + auto P = ScopeMembership.insert(std::make_pair(Visiting, Scope)); // Don't revisit blocks. if (!P.second) { - assert(P.first->second == Funclet && "MBB is part of two funclets!"); + assert(P.first->second == Scope && "MBB is part of two scopes!"); continue; } - // Returns are boundaries where funclet transfer can occur, don't follow + // Returns are boundaries where scope transfer can occur, don't follow // successors. if (Visiting->isReturnBlock()) continue; @@ -659,25 +659,25 @@ static void collectFuncletMembers( } DenseMap -llvm::getFuncletMembership(const MachineFunction &MF) { - DenseMap FuncletMembership; +llvm::getEHScopeMembership(const MachineFunction &MF) { + DenseMap ScopeMembership; // We don't have anything to do if there aren't any EH pads. - if (!MF.hasEHFunclets()) - return FuncletMembership; + if (!MF.hasEHScopes()) + return ScopeMembership; int EntryBBNumber = MF.front().getNumber(); bool IsSEH = isAsynchronousEHPersonality( classifyEHPersonality(MF.getFunction().getPersonalityFn())); const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); - SmallVector FuncletBlocks; + SmallVector ScopeBlocks; SmallVector UnreachableBlocks; SmallVector SEHCatchPads; SmallVector, 16> CatchRetSuccessors; for (const MachineBasicBlock &MBB : MF) { - if (MBB.isEHFuncletEntry()) { - FuncletBlocks.push_back(&MBB); + if (MBB.isEHScopeEntry()) { + ScopeBlocks.push_back(&MBB); } else if (IsSEH && MBB.isEHPad()) { SEHCatchPads.push_back(&MBB); } else if (MBB.pred_empty()) { @@ -686,8 +686,8 @@ llvm::getFuncletMembership(const MachineFunction &MF) { MachineBasicBlock::const_iterator MBBI = MBB.getFirstTerminator(); - // CatchPads are not funclets for SEH so do not consider CatchRet to - // transfer control to another funclet. + // CatchPads are not scopes for SEH so do not consider CatchRet to + // transfer control to another scope. if (MBBI == MBB.end() || MBBI->getOpcode() != TII->getCatchReturnOpcode()) continue; @@ -700,24 +700,24 @@ llvm::getFuncletMembership(const MachineFunction &MF) { } // We don't have anything to do if there aren't any EH pads. - if (FuncletBlocks.empty()) - return FuncletMembership; + if (ScopeBlocks.empty()) + return ScopeMembership; // Identify all the basic blocks reachable from the function entry. - collectFuncletMembers(FuncletMembership, EntryBBNumber, &MF.front()); - // All blocks not part of a funclet are in the parent function. + collectEHScopeMembers(ScopeMembership, EntryBBNumber, &MF.front()); + // All blocks not part of a scope are in the parent function. for (const MachineBasicBlock *MBB : UnreachableBlocks) - collectFuncletMembers(FuncletMembership, EntryBBNumber, MBB); - // Next, identify all the blocks inside the funclets. - for (const MachineBasicBlock *MBB : FuncletBlocks) - collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB); - // SEH CatchPads aren't really funclets, handle them separately. + collectEHScopeMembers(ScopeMembership, EntryBBNumber, MBB); + // Next, identify all the blocks inside the scopes. + for (const MachineBasicBlock *MBB : ScopeBlocks) + collectEHScopeMembers(ScopeMembership, MBB->getNumber(), MBB); + // SEH CatchPads aren't really scopes, handle them separately. for (const MachineBasicBlock *MBB : SEHCatchPads) - collectFuncletMembers(FuncletMembership, EntryBBNumber, MBB); + collectEHScopeMembers(ScopeMembership, EntryBBNumber, MBB); // Finally, identify all the targets of a catchret. for (std::pair CatchRetPair : CatchRetSuccessors) - collectFuncletMembers(FuncletMembership, CatchRetPair.second, + collectEHScopeMembers(ScopeMembership, CatchRetPair.second, CatchRetPair.first); - return FuncletMembership; + return ScopeMembership; } diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index ef9b65d31d1..008944e5207 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -200,7 +200,7 @@ bool BranchFolder::OptimizeFunction(MachineFunction &MF, } // Recalculate funclet membership. - FuncletMembership = getFuncletMembership(MF); + FuncletMembership = getEHScopeMembership(MF); bool MadeChangeThisIteration = true; while (MadeChangeThisIteration) { @@ -1293,7 +1293,7 @@ bool BranchFolder::OptimizeBranches(MachineFunction &MF) { // Make sure blocks are numbered in order MF.RenumberBlocks(); // Renumbering blocks alters funclet membership, recalculate it. - FuncletMembership = getFuncletMembership(MF); + FuncletMembership = getEHScopeMembership(MF); for (MachineFunction::iterator I = std::next(MF.begin()), E = MF.end(); I != E; ) { diff --git a/lib/CodeGen/FuncletLayout.cpp b/lib/CodeGen/FuncletLayout.cpp index 9c71b18619a..67a4d1551c6 100644 --- a/lib/CodeGen/FuncletLayout.cpp +++ b/lib/CodeGen/FuncletLayout.cpp @@ -42,7 +42,7 @@ INITIALIZE_PASS(FuncletLayout, DEBUG_TYPE, bool FuncletLayout::runOnMachineFunction(MachineFunction &F) { DenseMap FuncletMembership = - getFuncletMembership(F); + getEHScopeMembership(F); if (FuncletMembership.empty()) return false; diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 798b924244a..a3a6d43881b 100644 --- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -226,9 +226,10 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, const Instruction *PadInst = BB.getFirstNonPHI(); // If this is a non-landingpad EH pad, mark this function as using // funclets. - // FIXME: SEH catchpads do not create funclets, so we could avoid setting - // this in such cases in order to improve frame layout. + // FIXME: SEH catchpads do not create EH scope/funclets, so we could avoid + // setting this in such cases in order to improve frame layout. if (!isa(PadInst)) { + MF->setHasEHScopes(true); MF->setHasEHFunclets(true); MF->getFrameInfo().setHasOpaqueSPAdjustment(true); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 277f48df783..118e26bcb24 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1379,7 +1379,10 @@ void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) { auto Pers = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()); bool IsMSVCCXX = Pers == EHPersonality::MSVC_CXX; bool IsCoreCLR = Pers == EHPersonality::CoreCLR; + bool IsSEH = isAsynchronousEHPersonality(Pers); MachineBasicBlock *CatchPadMBB = FuncInfo.MBB; + if (!IsSEH) + CatchPadMBB->setIsEHScopeEntry(); // In MSVC C++ and CoreCLR, catchblocks are funclets and need prologues. if (IsMSVCCXX || IsCoreCLR) CatchPadMBB->setIsEHFuncletEntry(); @@ -1427,7 +1430,8 @@ void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) { void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) { // Don't emit any special code for the cleanuppad instruction. It just marks - // the start of a funclet. + // the start of an EH scope/funclet. + FuncInfo.MBB->setIsEHScopeEntry(); FuncInfo.MBB->setIsEHFuncletEntry(); FuncInfo.MBB->setIsCleanupFuncletEntry(); } @@ -1449,6 +1453,7 @@ static void findUnwindDestinations( classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()); bool IsMSVCCXX = Personality == EHPersonality::MSVC_CXX; bool IsCoreCLR = Personality == EHPersonality::CoreCLR; + bool IsSEH = isAsynchronousEHPersonality(Personality); while (EHPadBB) { const Instruction *Pad = EHPadBB->getFirstNonPHI(); @@ -1461,6 +1466,7 @@ static void findUnwindDestinations( // Stop on cleanup pads. Cleanups are always funclet entries for all known // personalities. UnwindDests.emplace_back(FuncInfo.MBBMap[EHPadBB], Prob); + UnwindDests.back().first->setIsEHScopeEntry(); UnwindDests.back().first->setIsEHFuncletEntry(); break; } else if (auto *CatchSwitch = dyn_cast(Pad)) { @@ -1470,6 +1476,8 @@ static void findUnwindDestinations( // For MSVC++ and the CLR, catchblocks are funclets and need prologues. if (IsMSVCCXX || IsCoreCLR) UnwindDests.back().first->setIsEHFuncletEntry(); + if (!IsSEH) + UnwindDests.back().first->setIsEHScopeEntry(); } NewEHPadBB = CatchSwitch->getUnwindDest(); } else {