summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/WinEHPrepare.cpp
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2015-08-17 20:56:39 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2015-08-17 20:56:39 +0000
commit83f4bb23c47323e8d584665310ff44ca126266e3 (patch)
treeb883bc20b7347d72a8baca639fe4383261e32986 /llvm/lib/CodeGen/WinEHPrepare.cpp
parent196e8cd792dba6c01ba69030122b4e8fc47aab8b (diff)
downloadbcm5719-llvm-83f4bb23c47323e8d584665310ff44ca126266e3.tar.gz
bcm5719-llvm-83f4bb23c47323e8d584665310ff44ca126266e3.zip
[WinEHPrepare] Replace unreasonable funclet terminators with unreachable
It is possible to be in a situation where more than one funclet token is a valid SSA value. If we see a terminator which exits a funclet which doesn't use the funclet's token, replace it with unreachable. Differential Revision: http://reviews.llvm.org/D12074 llvm-svn: 245238
Diffstat (limited to 'llvm/lib/CodeGen/WinEHPrepare.cpp')
-rw-r--r--llvm/lib/CodeGen/WinEHPrepare.cpp36
1 files changed, 33 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index a299c4fcfb1..4fb08ac200e 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -3085,6 +3085,33 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) {
RemapInstruction(&I, VMap, RF_IgnoreMissingEntries);
}
+ // Remove implausible terminators and replace them with UnreachableInst.
+ for (auto &Funclet : FuncletBlocks) {
+ BasicBlock *FuncletPadBB = Funclet.first;
+ std::set<BasicBlock *> &BlocksInFunclet = Funclet.second;
+ Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
+ auto *CatchPad = dyn_cast<CatchPadInst>(FirstNonPHI);
+ auto *CleanupPad = dyn_cast<CleanupPadInst>(FirstNonPHI);
+
+ for (BasicBlock *BB : BlocksInFunclet) {
+ TerminatorInst *TI = BB->getTerminator();
+ // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
+ bool IsUnreachableRet = isa<ReturnInst>(TI) && (CatchPad || CleanupPad);
+ // The token consumed by a CatchReturnInst must match the funclet token.
+ bool IsUnreachableCatchret = false;
+ if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
+ IsUnreachableCatchret = CRI->getReturnValue() != CatchPad;
+ // The token consumed by a CleanupPadInst must match the funclet token.
+ bool IsUnreachableCleanupret = false;
+ if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
+ IsUnreachableCleanupret = CRI->getReturnValue() != CleanupPad;
+ if (IsUnreachableRet || IsUnreachableCatchret || IsUnreachableCleanupret) {
+ new UnreachableInst(BB->getContext(), TI);
+ TI->eraseFromParent();
+ }
+ }
+ }
+
// Clean-up some of the mess we made by removing useles PHI nodes, trivial
// branches, etc.
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) {
@@ -3094,9 +3121,6 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) {
MergeBlockIntoPredecessor(BB);
}
- // TODO: Do something about cleanupblocks which branch to implausible
- // cleanuprets.
-
// We might have some unreachable blocks after cleaning up some impossible
// control flow.
removeUnreachableBlocks(F);
@@ -3215,6 +3239,12 @@ void WinEHPrepare::insertPHIStore(
void WinEHPrepare::demoteNonlocalUses(Value *V,
std::set<BasicBlock *> &ColorsForBB,
Function &F) {
+ // Tokens can only be used non-locally due to control flow involving
+ // unreachable edges. Don't try to demote the token usage, we'll simply
+ // delete the cloned user later.
+ if (isa<CatchPadInst>(V) || isa<CleanupPadInst>(V))
+ return;
+
DenseMap<BasicBlock *, Value *> Loads;
AllocaInst *SpillSlot = nullptr;
for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;) {
OpenPOWER on IntegriCloud