diff options
| author | David Majnemer <david.majnemer@gmail.com> | 2015-08-17 20:56:39 +0000 |
|---|---|---|
| committer | David Majnemer <david.majnemer@gmail.com> | 2015-08-17 20:56:39 +0000 |
| commit | 83f4bb23c47323e8d584665310ff44ca126266e3 (patch) | |
| tree | b883bc20b7347d72a8baca639fe4383261e32986 /llvm/lib/CodeGen/WinEHPrepare.cpp | |
| parent | 196e8cd792dba6c01ba69030122b4e8fc47aab8b (diff) | |
| download | bcm5719-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.cpp | 36 |
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;) { |

