diff options
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/Reassociate.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/SCCP.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/Sink.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/CodeExtractor.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/InlineFunction.cpp | 142 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/LCSSA.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/Local.cpp | 18 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 23 |
9 files changed, 148 insertions, 79 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 218e3e96c23..91bb3337509 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -2684,12 +2684,12 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { setOrigin(&I, getCleanOrigin()); } - void visitCleanupPadInst(CleanupPadInst &I) { + void visitCatchSwitchInst(CatchSwitchInst &I) { setShadow(&I, getCleanShadow(&I)); setOrigin(&I, getCleanOrigin()); } - void visitCatchPad(CatchPadInst &I) { + void visitFuncletPadInst(FuncletPadInst &I) { setShadow(&I, getCleanShadow(&I)); setOrigin(&I, getCleanOrigin()); } @@ -2699,16 +2699,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { // Nothing to do here. } - void visitCatchEndPadInst(CatchEndPadInst &I) { - DEBUG(dbgs() << "CatchEndPad: " << I << "\n"); - // Nothing to do here. - } - - void visitCleanupEndPadInst(CleanupEndPadInst &I) { - DEBUG(dbgs() << "CleanupEndPad: " << I << "\n"); - // Nothing to do here. - } - void visitGetElementPtrInst(GetElementPtrInst &I) { handleShadowOr(I); } diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp index fa2f7d995c6..13d9b6d4fee 100644 --- a/llvm/lib/Transforms/Scalar/Reassociate.cpp +++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -947,8 +947,6 @@ static Value *NegateValue(Value *V, Instruction *BI, if (Instruction *InstInput = dyn_cast<Instruction>(V)) { if (InvokeInst *II = dyn_cast<InvokeInst>(InstInput)) { InsertPt = II->getNormalDest()->begin(); - } else if (auto *CPI = dyn_cast<CatchPadInst>(InstInput)) { - InsertPt = CPI->getNormalDest()->begin(); } else { InsertPt = ++InstInput->getIterator(); } diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp index 52281d4e044..2fca803adde 100644 --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -480,8 +480,10 @@ private: void visitExtractValueInst(ExtractValueInst &EVI); void visitInsertValueInst(InsertValueInst &IVI); void visitLandingPadInst(LandingPadInst &I) { markAnythingOverdefined(&I); } - void visitCleanupPadInst(CleanupPadInst &CPI) { markAnythingOverdefined(&CPI); } - void visitCatchPadInst(CatchPadInst &CPI) { + void visitFuncletPadInst(FuncletPadInst &FPI) { + markAnythingOverdefined(&FPI); + } + void visitCatchSwitchInst(CatchSwitchInst &CPI) { markAnythingOverdefined(&CPI); visitTerminatorInst(CPI); } diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index 7c0ac7aa6fa..64109b2df11 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -169,7 +169,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, return false; } - if (isa<TerminatorInst>(Inst) || isa<PHINode>(Inst) || Inst->isEHPad()) + if (isa<TerminatorInst>(Inst) || isa<PHINode>(Inst) || Inst->isEHPad() || + Inst->mayThrow()) return false; // Convergent operations cannot be made control-dependent on additional @@ -194,6 +195,11 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, if (Inst->getParent() == SuccToSinkTo) return false; + // It's never legal to sink an instruction into a block which terminates in an + // EH-pad. + if (SuccToSinkTo->getTerminator()->isExceptional()) + return false; + // If the block has multiple predecessors, this would introduce computation // on different code paths. We could split the critical edge, but for now we // just punt. diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 8ee596e5323..823696d88e6 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -560,8 +560,8 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer, // Restore values just before we exit Function::arg_iterator OAI = OutputArgBegin; for (unsigned out = 0, e = outputs.size(); out != e; ++out) { - // For an invoke/catchpad, the normal destination is the only one - // that is dominated by the result of the invocation + // For an invoke, the normal destination is the only one that is + // dominated by the result of the invocation BasicBlock *DefBlock = cast<Instruction>(outputs[out])->getParent(); bool DominatesDef = true; @@ -569,8 +569,6 @@ emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer, BasicBlock *NormalDest = nullptr; if (auto *Invoke = dyn_cast<InvokeInst>(outputs[out])) NormalDest = Invoke->getNormalDest(); - if (auto *CatchPad = dyn_cast<CatchPadInst>(outputs[out])) - NormalDest = CatchPad->getNormalDest(); if (NormalDest) { DefBlock = NormalDest; diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index cafd1818fed..74ece385581 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -21,6 +21,7 @@ #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Attributes.h" @@ -192,8 +193,6 @@ HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB, BasicBlock *UnwindEdge) { // instructions require no special handling. CallInst *CI = dyn_cast<CallInst>(I); - // If this call cannot unwind, don't convert it to an invoke. - // Inline asm calls cannot throw. if (!CI || CI->doesNotThrow() || isa<InlineAsm>(CI->getCalledValue())) continue; @@ -327,40 +326,10 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock, } }; - // Forward EH terminator instructions to the caller's invoke destination. - // This is as simple as connect all the instructions which 'unwind to caller' - // to the invoke destination. + // This connects all the instructions which 'unwind to caller' to the invoke + // destination. for (Function::iterator BB = FirstNewBlock->getIterator(), E = Caller->end(); BB != E; ++BB) { - Instruction *I = BB->getFirstNonPHI(); - if (I->isEHPad()) { - if (auto *CEPI = dyn_cast<CatchEndPadInst>(I)) { - if (CEPI->unwindsToCaller()) { - CatchEndPadInst::Create(CEPI->getContext(), UnwindDest, CEPI); - CEPI->eraseFromParent(); - UpdatePHINodes(&*BB); - } - } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(I)) { - if (CEPI->unwindsToCaller()) { - CleanupEndPadInst::Create(CEPI->getCleanupPad(), UnwindDest, CEPI); - CEPI->eraseFromParent(); - UpdatePHINodes(&*BB); - } - } else if (auto *TPI = dyn_cast<TerminatePadInst>(I)) { - if (TPI->unwindsToCaller()) { - SmallVector<Value *, 3> TerminatePadArgs; - for (Value *ArgOperand : TPI->arg_operands()) - TerminatePadArgs.push_back(ArgOperand); - TerminatePadInst::Create(TPI->getContext(), UnwindDest, - TerminatePadArgs, TPI); - TPI->eraseFromParent(); - UpdatePHINodes(&*BB); - } - } else { - assert(isa<CatchPadInst>(I) || isa<CleanupPadInst>(I)); - } - } - if (auto *CRI = dyn_cast<CleanupReturnInst>(BB->getTerminator())) { if (CRI->unwindsToCaller()) { CleanupReturnInst::Create(CRI->getCleanupPad(), UnwindDest, CRI); @@ -368,6 +337,40 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock, UpdatePHINodes(&*BB); } } + + Instruction *I = BB->getFirstNonPHI(); + if (!I->isEHPad()) + continue; + + Instruction *Replacement = nullptr; + if (auto *TPI = dyn_cast<TerminatePadInst>(I)) { + if (TPI->unwindsToCaller()) { + SmallVector<Value *, 3> TerminatePadArgs; + for (Value *ArgOperand : TPI->arg_operands()) + TerminatePadArgs.push_back(ArgOperand); + Replacement = TerminatePadInst::Create(TPI->getParentPad(), UnwindDest, + TerminatePadArgs, TPI); + } + } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) { + if (CatchSwitch->unwindsToCaller()) { + auto *NewCatchSwitch = CatchSwitchInst::Create( + CatchSwitch->getParentPad(), UnwindDest, + CatchSwitch->getNumHandlers(), CatchSwitch->getName(), + CatchSwitch); + for (BasicBlock *PadBB : CatchSwitch->handlers()) + NewCatchSwitch->addHandler(PadBB); + Replacement = NewCatchSwitch; + } + } else if (!isa<FuncletPadInst>(I)) { + llvm_unreachable("unexpected EHPad!"); + } + + if (Replacement) { + Replacement->takeName(I); + I->replaceAllUsesWith(Replacement); + I->eraseFromParent(); + UpdatePHINodes(&*BB); + } } if (InlinedCodeInfo.ContainsCalls) @@ -1090,6 +1093,53 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI, return false; } + // We need to figure out which funclet the callsite was in so that we may + // properly nest the callee. + Instruction *CallSiteEHPad = nullptr; + if (CalledPersonality && CallerPersonality) { + EHPersonality Personality = classifyEHPersonality(CalledPersonality); + if (isFuncletEHPersonality(Personality)) { + DenseMap<BasicBlock *, ColorVector> CallerBlockColors = + colorEHFunclets(*Caller); + ColorVector &CallSiteColors = CallerBlockColors[OrigBB]; + size_t NumColors = CallSiteColors.size(); + // There is no single parent, inlining will not succeed. + if (NumColors > 1) + return false; + if (NumColors == 1) { + BasicBlock *CallSiteFuncletBB = CallSiteColors.front(); + if (CallSiteFuncletBB != Caller->begin()) { + CallSiteEHPad = CallSiteFuncletBB->getFirstNonPHI(); + assert(CallSiteEHPad->isEHPad() && "Expected an EHPad!"); + } + } + + // OK, the inlining site is legal. What about the target function? + + if (CallSiteEHPad) { + if (Personality == EHPersonality::MSVC_CXX) { + // The MSVC personality cannot tolerate catches getting inlined into + // cleanup funclets. + if (isa<CleanupPadInst>(CallSiteEHPad)) { + // Ok, the call site is within a cleanuppad. Let's check the callee + // for catchpads. + for (const BasicBlock &CalledBB : *CalledFunc) { + if (isa<CatchPadInst>(CalledBB.getFirstNonPHI())) + return false; + } + } + } else if (isAsynchronousEHPersonality(Personality)) { + // SEH is even less tolerant, there may not be any sort of exceptional + // funclet in the callee. + for (const BasicBlock &CalledBB : *CalledFunc) { + if (CalledBB.isEHPad()) + return false; + } + } + } + } + } + // Get an iterator to the last basic block in the function, which will have // the new function inlined after it. Function::iterator LastBlock = --Caller->end(); @@ -1381,6 +1431,30 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI, } } + // Update the lexical scopes of the new funclets. Anything that had 'none' as + // its parent is now nested inside the callsite's EHPad. + if (CallSiteEHPad) { + for (Function::iterator BB = FirstNewBlock->getIterator(), + E = Caller->end(); + BB != E; ++BB) { + Instruction *I = BB->getFirstNonPHI(); + if (!I->isEHPad()) + continue; + + if (auto *TPI = dyn_cast<TerminatePadInst>(I)) { + if (isa<ConstantTokenNone>(TPI->getParentPad())) + TPI->setParentPad(CallSiteEHPad); + } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) { + if (isa<ConstantTokenNone>(CatchSwitch->getParentPad())) + CatchSwitch->setParentPad(CallSiteEHPad); + } else { + auto *FPI = cast<FuncletPadInst>(I); + if (isa<ConstantTokenNone>(FPI->getParentPad())) + FPI->setParentPad(CallSiteEHPad); + } + } + } + // If we are inlining for an invoke instruction, we must make sure to rewrite // any call instructions into invoke instructions. if (auto *II = dyn_cast<InvokeInst>(TheCall)) { diff --git a/llvm/lib/Transforms/Utils/LCSSA.cpp b/llvm/lib/Transforms/Utils/LCSSA.cpp index 12a8c71d829..ef2f5042169 100644 --- a/llvm/lib/Transforms/Utils/LCSSA.cpp +++ b/llvm/lib/Transforms/Utils/LCSSA.cpp @@ -84,15 +84,13 @@ static bool processInstruction(Loop &L, Instruction &Inst, DominatorTree &DT, ++NumLCSSA; // We are applying the transformation - // Invoke/CatchPad instructions are special in that their result value is not - // available along their unwind edge. The code below tests to see whether - // DomBB dominates the value, so adjust DomBB to the normal destination block, + // Invoke instructions are special in that their result value is not available + // along their unwind edge. The code below tests to see whether DomBB + // dominates the value, so adjust DomBB to the normal destination block, // which is effectively where the value is first usable. BasicBlock *DomBB = Inst.getParent(); if (InvokeInst *Inv = dyn_cast<InvokeInst>(&Inst)) DomBB = Inv->getNormalDest(); - if (auto *CPI = dyn_cast<CatchPadInst>(&Inst)) - DomBB = CPI->getNormalDest(); DomTreeNode *DomNode = DT.getNode(DomBB); diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 391ed685766..cb17b603ae5 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1338,19 +1338,22 @@ void llvm::removeUnwindEdge(BasicBlock *BB) { if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) { NewTI = CleanupReturnInst::Create(CRI->getCleanupPad(), nullptr, CRI); UnwindDest = CRI->getUnwindDest(); - } else if (auto *CEP = dyn_cast<CleanupEndPadInst>(TI)) { - NewTI = CleanupEndPadInst::Create(CEP->getCleanupPad(), nullptr, CEP); - UnwindDest = CEP->getUnwindDest(); - } else if (auto *CEP = dyn_cast<CatchEndPadInst>(TI)) { - NewTI = CatchEndPadInst::Create(CEP->getContext(), nullptr, CEP); - UnwindDest = CEP->getUnwindDest(); } else if (auto *TPI = dyn_cast<TerminatePadInst>(TI)) { SmallVector<Value *, 3> TerminatePadArgs; for (Value *Operand : TPI->arg_operands()) TerminatePadArgs.push_back(Operand); - NewTI = TerminatePadInst::Create(TPI->getContext(), nullptr, + NewTI = TerminatePadInst::Create(TPI->getParentPad(), nullptr, TerminatePadArgs, TPI); UnwindDest = TPI->getUnwindDest(); + } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) { + auto *NewCatchSwitch = CatchSwitchInst::Create( + CatchSwitch->getParentPad(), nullptr, CatchSwitch->getNumHandlers(), + CatchSwitch->getName(), CatchSwitch); + for (BasicBlock *PadBB : CatchSwitch->handlers()) + NewCatchSwitch->addHandler(PadBB); + + NewTI = NewCatchSwitch; + UnwindDest = CatchSwitch->getUnwindDest(); } else { llvm_unreachable("Could not find unwind successor"); } @@ -1358,6 +1361,7 @@ void llvm::removeUnwindEdge(BasicBlock *BB) { NewTI->takeName(TI); NewTI->setDebugLoc(TI->getDebugLoc()); UnwindDest->removePredecessor(BB); + TI->replaceAllUsesWith(NewTI); TI->eraseFromParent(); } diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index fe9fd18292c..cbb8cf234aa 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -3254,8 +3254,8 @@ bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) { // updated to continue to the unwind destination of the cleanup pad being // simplified. BasicBlock *BB = RI->getParent(); - Instruction *CPInst = dyn_cast<CleanupPadInst>(BB->getFirstNonPHI()); - if (!CPInst) + CleanupPadInst *CPInst = RI->getCleanupPad(); + if (CPInst->getParent() != BB) // This isn't an empty cleanup. return false; @@ -3265,9 +3265,10 @@ bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) { if (!isa<DbgInfoIntrinsic>(I)) return false; - // If the cleanup return we are simplifying unwinds to the caller, this - // will set UnwindDest to nullptr. + // If the cleanup return we are simplifying unwinds to the caller, this will + // set UnwindDest to nullptr. BasicBlock *UnwindDest = RI->getUnwindDest(); + Instruction *DestEHPad = UnwindDest ? UnwindDest->getFirstNonPHI() : nullptr; // We're about to remove BB from the control flow. Before we do, sink any // PHINodes into the unwind destination. Doing this before changing the @@ -3278,7 +3279,7 @@ bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) { // First, go through the PHI nodes in UnwindDest and update any nodes that // reference the block we are removing for (BasicBlock::iterator I = UnwindDest->begin(), - IE = UnwindDest->getFirstNonPHI()->getIterator(); + IE = DestEHPad->getIterator(); I != IE; ++I) { PHINode *DestPN = cast<PHINode>(I); @@ -3322,7 +3323,7 @@ bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) { } // Sink any remaining PHI nodes directly into UnwindDest. - Instruction *InsertPt = UnwindDest->getFirstNonPHI(); + Instruction *InsertPt = DestEHPad; for (BasicBlock::iterator I = BB->begin(), IE = BB->getFirstNonPHI()->getIterator(); I != IE;) { @@ -3492,18 +3493,16 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) { } } else if ((isa<InvokeInst>(TI) && cast<InvokeInst>(TI)->getUnwindDest() == BB) || - isa<CatchEndPadInst>(TI) || isa<TerminatePadInst>(TI)) { + isa<TerminatePadInst>(TI) || isa<CatchSwitchInst>(TI)) { removeUnwindEdge(TI->getParent()); Changed = true; - } else if (isa<CleanupReturnInst>(TI) || isa<CleanupEndPadInst>(TI)) { + } else if (isa<CleanupReturnInst>(TI)) { new UnreachableInst(TI->getContext(), TI); TI->eraseFromParent(); Changed = true; } - // TODO: If TI is a CatchPadInst, then (BB must be its normal dest and) - // we can eliminate it, redirecting its preds to its unwind successor, - // or to the next outer handler if the removed catch is the last for its - // catchendpad. + // TODO: We can remove a catchswitch if all it's catchpads end in + // unreachable. } // If this block is now dead, remove it. |