diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/Analysis/CGSCCPassManager.h | 8 | ||||
-rw-r--r-- | llvm/lib/Analysis/CGSCCPassManager.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/CallGraphUpdater.cpp | 10 | ||||
-rw-r--r-- | llvm/unittests/Analysis/CGSCCPassManagerTest.cpp | 55 |
4 files changed, 58 insertions, 25 deletions
diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h index 59974d1..406d349 100644 --- a/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -245,14 +245,6 @@ struct CGSCCUpdateResult { /// in reverse post-order. SmallPriorityWorklist<LazyCallGraph::SCC *, 1> &CWorklist; - /// The set of invalidated RefSCCs which should be skipped if they are found - /// in \c RCWorklist. - /// - /// This is used to quickly prune out RefSCCs when they get deleted and - /// happen to already be on the worklist. We use this primarily to avoid - /// scanning the list and removing entries from it. - SmallPtrSetImpl<LazyCallGraph::RefSCC *> &InvalidatedRefSCCs; - /// The set of invalidated SCCs which should be skipped if they are found /// in \c CWorklist. /// diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp index 24b3c6e..c32739a 100644 --- a/llvm/lib/Analysis/CGSCCPassManager.cpp +++ b/llvm/lib/Analysis/CGSCCPassManager.cpp @@ -150,9 +150,8 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) { SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> RCWorklist; SmallPriorityWorklist<LazyCallGraph::SCC *, 1> CWorklist; - // Keep sets for invalidated SCCs and RefSCCs that should be skipped when + // Keep sets for invalidated SCCs that should be skipped when // iterating off the worklists. - SmallPtrSet<LazyCallGraph::RefSCC *, 4> InvalidRefSCCSet; SmallPtrSet<LazyCallGraph::SCC *, 4> InvalidSCCSet; SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4> @@ -161,7 +160,6 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) { SmallVector<Function *, 4> DeadFunctions; CGSCCUpdateResult UR = {CWorklist, - InvalidRefSCCSet, InvalidSCCSet, nullptr, PreservedAnalyses::all(), @@ -194,11 +192,6 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) { do { LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val(); - if (InvalidRefSCCSet.count(RC)) { - LLVM_DEBUG(dbgs() << "Skipping an invalid RefSCC...\n"); - continue; - } - assert(CWorklist.empty() && "Should always start with an empty SCC worklist"); @@ -1172,7 +1165,6 @@ static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass( } assert(!UR.InvalidatedSCCs.count(C) && "Invalidated the current SCC!"); - assert(!UR.InvalidatedRefSCCs.count(RC) && "Invalidated the current RefSCC!"); assert(&C->getOuterRefSCC() == RC && "Current SCC not in current RefSCC!"); // Record the current SCC for higher layers of the CGSCC pass manager now that diff --git a/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp b/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp index e9f37d4..7cba482 100644 --- a/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp +++ b/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp @@ -59,20 +59,14 @@ bool CallGraphUpdater::finalize() { auto *DeadSCC = LCG->lookupSCC(N); assert(DeadSCC && DeadSCC->size() == 1 && &DeadSCC->begin()->getFunction() == DeadFn); - auto &DeadRC = DeadSCC->getOuterRefSCC(); - FunctionAnalysisManager &FAM = - AM->getResult<FunctionAnalysisManagerCGSCCProxy>(*DeadSCC, *LCG) - .getManager(); - - FAM.clear(*DeadFn, DeadFn->getName()); + FAM->clear(*DeadFn, DeadFn->getName()); AM->clear(*DeadSCC, DeadSCC->getName()); LCG->markDeadFunction(*DeadFn); // Mark the relevant parts of the call graph as invalid so we don't // visit them. - UR->InvalidatedSCCs.insert(DeadSCC); - UR->InvalidatedRefSCCs.insert(&DeadRC); + UR->InvalidatedSCCs.insert(LCG->lookupSCC(N)); UR->DeadFunctions.push_back(DeadFn); } else { // The CGSCC infrastructure batch deletes functions at the end of the diff --git a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp index 1532379..9fd782d1 100644 --- a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp +++ b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp @@ -1878,6 +1878,61 @@ TEST_F(CGSCCPassManagerTest, TestInsertionOfNewFunctions2) { ASSERT_TRUE(Ran); } +TEST_F(CGSCCPassManagerTest, TestDeletionOfFunctionInNonTrivialRefSCC) { + std::unique_ptr<Module> M = parseIR("define void @f1() {\n" + "entry:\n" + " call void @f2()\n" + " ret void\n" + "}\n" + "define void @f2() {\n" + "entry:\n" + " call void @f1()\n" + " ret void\n" + "}\n"); + + bool Ran = false; + CGSCCPassManager CGPM; + CGPM.addPass(LambdaSCCPassNoPreserve( + [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, + CGSCCUpdateResult &UR) { + if (Ran) + return; + + LazyCallGraph::Node *N1 = nullptr; + + for (LazyCallGraph::Node *N : SCCNodes(C)) { + Function &F = N->getFunction(); + if (F.getName() != "f1") + continue; + N1 = N; + + Function &F2 = *F.getParent()->getFunction("f2"); + + // Remove f1 <-> f2 references + F.getEntryBlock().front().eraseFromParent(); + F2.getEntryBlock().front().eraseFromParent(); + + CallGraphUpdater CGU; + CGU.initialize(CG, C, AM, UR); + CGU.removeFunction(F2); + CGU.reanalyzeFunction(F); + + Ran = true; + } + + // Check that updateCGAndAnalysisManagerForCGSCCPass() after + // CallGraphUpdater::removeFunction() succeeds. + updateCGAndAnalysisManagerForCGSCCPass(CG, *CG.lookupSCC(*N1), *N1, AM, + UR, FAM); + })); + + ModulePassManager MPM; + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); + MPM.run(*M, MAM); + + ASSERT_TRUE(Ran); +} + TEST_F(CGSCCPassManagerTest, TestInsertionOfNewNonTrivialCallEdge) { std::unique_ptr<Module> M = parseIR("define void @f1() {\n" "entry:\n" |