summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/FuncletLayout.cpp37
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp4
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp14
-rw-r--r--llvm/lib/CodeGen/WinEHPrepare.cpp97
4 files changed, 131 insertions, 21 deletions
diff --git a/llvm/lib/CodeGen/FuncletLayout.cpp b/llvm/lib/CodeGen/FuncletLayout.cpp
index 0cda11f53db..e1e185b4752 100644
--- a/llvm/lib/CodeGen/FuncletLayout.cpp
+++ b/llvm/lib/CodeGen/FuncletLayout.cpp
@@ -16,6 +16,8 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;
#define DEBUG_TYPE "funclet-layout"
@@ -36,8 +38,21 @@ static void
collectFuncletMembers(DenseMap<MachineBasicBlock *, int> &FuncletMembership,
int Funclet, MachineBasicBlock *MBB) {
// Don't revisit blocks.
- if (FuncletMembership.count(MBB) > 0)
+ if (FuncletMembership.count(MBB) > 0) {
+ // FIXME: This is a hack, we need to assert this unconditionally.
+ bool IsProbablyUnreachableBlock =
+ MBB->empty() ||
+ (MBB->succ_empty() && !MBB->getFirstTerminator()->isReturn() &&
+ MBB->size() == 1);
+
+ if (!IsProbablyUnreachableBlock) {
+ if (FuncletMembership[MBB] != Funclet) {
+ assert(false && "MBB is part of two funclets!");
+ report_fatal_error("MBB is part of two funclets!");
+ }
+ }
return;
+ }
// Add this MBB to our funclet.
FuncletMembership[MBB] = Funclet;
@@ -71,18 +86,36 @@ bool FuncletLayout::runOnMachineFunction(MachineFunction &F) {
if (!F.getMMI().hasEHFunclets())
return false;
+ const TargetInstrInfo *TII = F.getSubtarget().getInstrInfo();
SmallVector<MachineBasicBlock *, 16> FuncletBlocks;
- for (MachineBasicBlock &MBB : F)
+ SmallVector<std::pair<MachineBasicBlock *, int>, 16> CatchRetSuccessors;
+ for (MachineBasicBlock &MBB : F) {
if (MBB.isEHFuncletEntry())
FuncletBlocks.push_back(&MBB);
+ MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
+ if (MBBI->getOpcode() != TII->getCatchReturnOpcode())
+ continue;
+
+ MachineBasicBlock *Successor = MBBI->getOperand(0).getMBB();
+ MachineBasicBlock *SuccessorColor = MBBI->getOperand(1).getMBB();
+ CatchRetSuccessors.push_back({Successor, SuccessorColor->getNumber()});
+ }
+
// We don't have anything to do if there aren't any EH pads.
if (FuncletBlocks.empty())
return false;
DenseMap<MachineBasicBlock *, int> FuncletMembership;
+ // Identify all the basic blocks reachable from the function entry.
+ collectFuncletMembers(FuncletMembership, F.front().getNumber(), F.begin());
+ // Next, identify all the blocks inside the funclets.
for (MachineBasicBlock *MBB : FuncletBlocks)
collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB);
+ // Finally, identify all the targets of a catchret.
+ for (std::pair<MachineBasicBlock *, int> CatchRetPair : CatchRetSuccessors)
+ collectFuncletMembers(FuncletMembership, CatchRetPair.second,
+ CatchRetPair.first);
F.sort([&](MachineBasicBlock &x, MachineBasicBlock &y) {
return FuncletMembership[&x] < FuncletMembership[&y];
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index baf9ee990ea..7da68deaaa3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -290,9 +290,11 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
if (Personality == EHPersonality::MSVC_CXX)
calculateWinCXXEHStateNumbers(WinEHParentFn, EHInfo);
- else
+ else if (isAsynchronousEHPersonality(Personality))
calculateSEHStateNumbers(WinEHParentFn, EHInfo);
+ calculateCatchReturnSuccessorColors(WinEHParentFn, EHInfo);
+
// Map all BB references in the WinEH data to MBBs.
for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
for (WinEHHandlerType &H : TBME.HandlerArray) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 4f9656532c2..f779fd1b03a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1168,9 +1168,21 @@ void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
MachineBasicBlock *TargetMBB = FuncInfo.MBBMap[I.getSuccessor()];
FuncInfo.MBB->addSuccessor(TargetMBB);
+ // Figure out the funclet membership for the catchret's successor.
+ // This will be used by the FuncletLayout pass to determine how to order the
+ // BB's.
+ MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI();
+ WinEHFuncInfo &EHInfo =
+ MMI.getWinEHFuncInfo(DAG.getMachineFunction().getFunction());
+ const BasicBlock *SuccessorColor = EHInfo.CatchRetSuccessorColorMap[&I];
+ assert(SuccessorColor && "No parent funclet for catchret!");
+ MachineBasicBlock *SuccessorColorMBB = FuncInfo.MBBMap[SuccessorColor];
+ assert(SuccessorColorMBB && "No MBB for SuccessorColor!");
+
// Create the terminator node.
SDValue Ret = DAG.getNode(ISD::CATCHRET, getCurSDLoc(), MVT::Other,
- getControlRoot(), DAG.getBasicBlock(TargetMBB));
+ getControlRoot(), DAG.getBasicBlock(TargetMBB),
+ DAG.getBasicBlock(SuccessorColorMBB));
DAG.setRoot(Ret);
}
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index 7240159b083..07734c352c0 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -399,6 +399,29 @@ FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
return new WinEHPrepare(TM);
}
+static bool
+findExceptionalConstructs(Function &Fn,
+ SmallVectorImpl<LandingPadInst *> &LPads,
+ SmallVectorImpl<ResumeInst *> &Resumes,
+ SmallVectorImpl<BasicBlock *> &EntryBlocks) {
+ bool ForExplicitEH = false;
+ for (BasicBlock &BB : Fn) {
+ Instruction *First = BB.getFirstNonPHI();
+ if (auto *LP = dyn_cast<LandingPadInst>(First)) {
+ LPads.push_back(LP);
+ } else if (First->isEHPad()) {
+ if (!ForExplicitEH)
+ EntryBlocks.push_back(&Fn.getEntryBlock());
+ if (!isa<CatchEndPadInst>(First) && !isa<CleanupEndPadInst>(First))
+ EntryBlocks.push_back(&BB);
+ ForExplicitEH = true;
+ }
+ if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))
+ Resumes.push_back(Resume);
+ }
+ return ForExplicitEH;
+}
+
bool WinEHPrepare::runOnFunction(Function &Fn) {
if (!Fn.hasPersonalityFn())
return false;
@@ -417,21 +440,8 @@ bool WinEHPrepare::runOnFunction(Function &Fn) {
SmallVector<LandingPadInst *, 4> LPads;
SmallVector<ResumeInst *, 4> Resumes;
SmallVector<BasicBlock *, 4> EntryBlocks;
- bool ForExplicitEH = false;
- for (BasicBlock &BB : Fn) {
- Instruction *First = BB.getFirstNonPHI();
- if (auto *LP = dyn_cast<LandingPadInst>(First)) {
- LPads.push_back(LP);
- } else if (First->isEHPad()) {
- if (!ForExplicitEH)
- EntryBlocks.push_back(&Fn.getEntryBlock());
- if (!isa<CatchEndPadInst>(First) && !isa<CleanupEndPadInst>(First))
- EntryBlocks.push_back(&BB);
- ForExplicitEH = true;
- }
- if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))
- Resumes.push_back(Resume);
- }
+ bool ForExplicitEH =
+ findExceptionalConstructs(Fn, LPads, Resumes, EntryBlocks);
if (ForExplicitEH)
return prepareExplicitEH(Fn, EntryBlocks);
@@ -2878,8 +2888,11 @@ void WinEHPrepare::replaceTerminatePadWithCleanup(Function &F) {
}
}
-void WinEHPrepare::colorFunclets(Function &F,
- SmallVectorImpl<BasicBlock *> &EntryBlocks) {
+static void
+colorFunclets(Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks,
+ std::map<BasicBlock *, std::set<BasicBlock *>> &BlockColors,
+ std::map<BasicBlock *, std::set<BasicBlock *>> &FuncletBlocks,
+ std::map<BasicBlock *, std::set<BasicBlock *>> &FuncletChildren) {
SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;
BasicBlock *EntryBlock = &F.getEntryBlock();
@@ -2976,6 +2989,56 @@ void WinEHPrepare::colorFunclets(Function &F,
}
}
+void WinEHPrepare::colorFunclets(Function &F,
+ SmallVectorImpl<BasicBlock *> &EntryBlocks) {
+ ::colorFunclets(F, EntryBlocks, BlockColors, FuncletBlocks, FuncletChildren);
+}
+
+void llvm::calculateCatchReturnSuccessorColors(const Function *Fn,
+ WinEHFuncInfo &FuncInfo) {
+ SmallVector<LandingPadInst *, 4> LPads;
+ SmallVector<ResumeInst *, 4> Resumes;
+ SmallVector<BasicBlock *, 4> EntryBlocks;
+ // colorFunclets needs the set of EntryBlocks, get them using
+ // findExceptionalConstructs.
+ bool ForExplicitEH = findExceptionalConstructs(const_cast<Function &>(*Fn),
+ LPads, Resumes, EntryBlocks);
+ if (!ForExplicitEH)
+ return;
+
+ std::map<BasicBlock *, std::set<BasicBlock *>> BlockColors;
+ std::map<BasicBlock *, std::set<BasicBlock *>> FuncletBlocks;
+ std::map<BasicBlock *, std::set<BasicBlock *>> FuncletChildren;
+ // Figure out which basic blocks belong to which funclets.
+ colorFunclets(const_cast<Function &>(*Fn), EntryBlocks, BlockColors,
+ FuncletBlocks, FuncletChildren);
+
+ // We need to find the catchret successors. To do this, we must first find
+ // all the catchpad funclets.
+ for (auto &Funclet : FuncletBlocks) {
+ // Figure out what kind of funclet we are looking at; We only care about
+ // catchpads.
+ BasicBlock *FuncletPadBB = Funclet.first;
+ Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
+ auto *CatchPad = dyn_cast<CatchPadInst>(FirstNonPHI);
+ if (!CatchPad)
+ continue;
+
+ // The users of a catchpad are always catchrets.
+ for (User *Exit : CatchPad->users()) {
+ auto *CatchReturn = cast<CatchReturnInst>(Exit);
+ BasicBlock *CatchRetSuccessor = CatchReturn->getSuccessor();
+ std::set<BasicBlock *> &SuccessorColors = BlockColors[CatchRetSuccessor];
+ assert(SuccessorColors.size() == 1 && "Expected BB to be monochrome!");
+ BasicBlock *Color = *SuccessorColors.begin();
+ if (auto *CPI = dyn_cast<CatchPadInst>(Color->getFirstNonPHI()))
+ Color = CPI->getNormalDest();
+ // Record the catchret successor's funclet membership.
+ FuncInfo.CatchRetSuccessorColorMap[CatchReturn] = Color;
+ }
+ }
+}
+
void WinEHPrepare::demotePHIsOnFunclets(Function &F) {
// Strip PHI nodes off of EH pads.
SmallVector<PHINode *, 16> PHINodes;
OpenPOWER on IntegriCloud