Index: llvm/trunk/include/llvm/Analysis/CallGraph.h =================================================================== --- llvm/trunk/include/llvm/Analysis/CallGraph.h +++ llvm/trunk/include/llvm/Analysis/CallGraph.h @@ -272,7 +272,7 @@ private: friend class CallGraph; - AssertingVH F; + Function *F; std::vector CalledFunctions; Index: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h =================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h +++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h @@ -600,14 +600,14 @@ /// Information about the number of times a particular loop exit may be /// reached before exiting the loop. struct ExitNotTakenInfo { - AssertingVH ExitingBlock; + PoisoningVH ExitingBlock; const SCEV *ExactNotTaken; std::unique_ptr Predicate; bool hasAlwaysTruePredicate() const { return !Predicate || Predicate->isAlwaysTrue(); } - explicit ExitNotTakenInfo(AssertingVH ExitingBlock, + explicit ExitNotTakenInfo(PoisoningVH ExitingBlock, const SCEV *ExactNotTaken, std::unique_ptr Predicate) : ExitingBlock(ExitingBlock), ExactNotTaken(ExactNotTaken), Index: llvm/trunk/lib/Analysis/LazyValueInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/LazyValueInfo.cpp +++ llvm/trunk/lib/Analysis/LazyValueInfo.cpp @@ -366,7 +366,7 @@ struct ValueCacheEntryTy { ValueCacheEntryTy(Value *V, LazyValueInfoCache *P) : Handle(V, P) {} LVIValueHandle Handle; - SmallDenseMap, LVILatticeVal, 4> BlockVals; + SmallDenseMap, LVILatticeVal, 4> BlockVals; }; /// This is all of the cached information for all values, @@ -375,13 +375,13 @@ /// This tracks, on a per-block basis, the set of values that are /// over-defined at the end of that block. - typedef DenseMap, SmallPtrSet> + typedef DenseMap, SmallPtrSet> OverDefinedCacheTy; OverDefinedCacheTy OverDefinedCache; /// Keep track of all blocks that we have ever seen, so we /// don't spend time removing unused blocks from our caches. - DenseSet > SeenBlocks; + DenseSet > SeenBlocks; public: void insertResult(Value *Val, BasicBlock *BB, const LVILatticeVal &Result) { @@ -464,10 +464,10 @@ SmallPtrSetImpl &ValueSet = I.second; ValueSet.erase(V); if (ValueSet.empty()) - ToErase.push_back(I.first); + ToErase.push_back(&*I.first); } for (auto &BB : ToErase) - OverDefinedCache.erase(BB); + OverDefinedCache.erase(&*BB); ValueCache.erase(V); } @@ -480,7 +480,7 @@ void LazyValueInfoCache::eraseBlock(BasicBlock *BB) { // Shortcut if we have never seen this block. - DenseSet >::iterator I = SeenBlocks.find(BB); + DenseSet >::iterator I = SeenBlocks.find(BB); if (I == SeenBlocks.end()) return; SeenBlocks.erase(I); Index: llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp +++ llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp @@ -1275,16 +1275,9 @@ ReversePostOrderFunctionAttrsPass::run(Module &M, ModuleAnalysisManager &AM) { auto &CG = AM.getResult(M); - bool Changed = deduceFunctionAttributeInRPO(M, CG); - - // CallGraphAnalysis holds AssertingVH and must be invalidated eagerly so - // that other passes don't delete stuff from under it. - // FIXME: We need to invalidate this to avoid PR28400. Is there a better - // solution? - AM.invalidate(M); - - if (!Changed) + if (!deduceFunctionAttributeInRPO(M, CG)) return PreservedAnalyses::all(); + PreservedAnalyses PA; PA.preserve(); return PA; Index: llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp +++ llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp @@ -144,29 +144,13 @@ } } - // Because we may have cached analyses for functions we take extra care when - // deleting them if there is an active proxy. If there isn't, then we get to - // assume that everything in the function AM has been cleared already. - // FIXME: Note that all of this will happen automatically when this pass - // finishes. Unfortuantely there are analyses which hold asserting VHs to - // IR units. We could make those weak VHs that would assert if ever used - // without asserting eagerly and then all of this knowledge of the analysis - // manager could go away. - FunctionAnalysisManager *FAM = nullptr; - if (auto *FAMProxy = - MAM.getCachedResult(M)) - FAM = &FAMProxy->getManager(); - // The second pass drops the bodies of functions which are dead... std::vector DeadFunctions; for (Function &F : M) if (!AliveGlobals.count(&F)) { DeadFunctions.push_back(&F); // Keep track of dead globals - if (!F.isDeclaration()) { - if (FAM) - FAM->clear(F); + if (!F.isDeclaration()) F.deleteBody(); - } } // The third pass drops targets of aliases which are dead... Index: llvm/trunk/lib/Transforms/IPO/Inliner.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/Inliner.cpp +++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp @@ -887,11 +887,10 @@ // made dead by this operation on other functions). Callee.removeDeadConstantUsers(); if (Callee.use_empty()) { - // Clear all analyses and the body and queue the function itself for - // deletion when we finish inlining and call graph updates. + // Clear the body and queue the function itself for deletion when we + // finish inlining and call graph updates. // Note that after this point, it is an error to do anything other // than use the callee's address or delete it. - FAM.clear(Callee); Callee.dropAllReferences(); assert(find(DeadFunctions, &Callee) == DeadFunctions.end() && "Cannot put cause a function to become dead twice!"); @@ -939,8 +938,13 @@ // sets. for (Function *DeadF : DeadFunctions) { // Get the necessary information out of the call graph and nuke the - // function there. + // function there. Also, cclear out any cached analyses. auto &DeadC = *CG.lookupSCC(*CG.lookup(*DeadF)); + FunctionAnalysisManager &FAM = + AM.getResult(DeadC, CG) + .getManager(); + FAM.clear(*DeadF); + AM.clear(DeadC); auto &DeadRC = DeadC.getOuterRefSCC(); CG.removeDeadFunction(*DeadF); Index: llvm/trunk/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp +++ llvm/trunk/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp @@ -438,13 +438,7 @@ AssumptionCache &AC = AM.getResult(F); ScalarEvolution &SE = AM.getResult(F); DominatorTree &DT = AM.getResult(F); - bool Changed = runImpl(F, AC, &SE, &DT); - - // FIXME: We need to invalidate this to avoid PR28400. Is there a better - // solution? - AM.invalidate(F); - - if (!Changed) + if (!runImpl(F, AC, &SE, &DT)) return PreservedAnalyses::all(); PreservedAnalyses PA; Index: llvm/trunk/lib/Transforms/Scalar/NaryReassociate.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/NaryReassociate.cpp +++ llvm/trunk/lib/Transforms/Scalar/NaryReassociate.cpp @@ -156,13 +156,7 @@ auto *TLI = &AM.getResult(F); auto *TTI = &AM.getResult(F); - bool Changed = runImpl(F, AC, DT, SE, TLI, TTI); - - // FIXME: We need to invalidate this to avoid PR28400. Is there a better - // solution? - AM.invalidate(F); - - if (!Changed) + if (!runImpl(F, AC, DT, SE, TLI, TTI)) return PreservedAnalyses::all(); PreservedAnalyses PA; Index: llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp +++ llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp @@ -853,12 +853,9 @@ for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I) Changed |= simplifyLoop(*I, DT, LI, SE, AC, /*PreserveLCSSA*/ false); - // FIXME: We need to invalidate this to avoid PR28400. Is there a better - // solution? - AM.invalidate(F); - if (!Changed) return PreservedAnalyses::all(); + PreservedAnalyses PA; PA.preserve(); PA.preserve(); Index: llvm/trunk/test/Other/new-pm-defaults.ll =================================================================== --- llvm/trunk/test/Other/new-pm-defaults.ll +++ llvm/trunk/test/Other/new-pm-defaults.ll @@ -91,8 +91,6 @@ ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running pass: InstCombinePass ; CHECK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LoopStandardAnalysisResults{{.*}}> -; CHECK-O-NEXT: Invalidating analysis: ScalarEvolutionAnalysis -; CHECK-O-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-O-NEXT: Starting Loop pass manager run. ; CHECK-O-NEXT: Finished Loop pass manager run. ; CHECK-Os-NEXT: Running pass: MergedLoadStoreMotionPass @@ -120,7 +118,6 @@ ; CHECK-O-NEXT: Running pass: EliminateAvailableExternallyPass ; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: CallGraphAnalysis -; CHECK-O-NEXT: Invalidating analysis: CallGraphAnalysis ; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> ; CHECK-O-NEXT: Starting llvm::Function pass manager run. ; CHECK-O-NEXT: Running pass: Float2IntPass @@ -133,7 +130,6 @@ ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running pass: InstCombinePass ; CHECK-O-NEXT: Running pass: AlignmentFromAssumptionsPass -; CHECK-O-NEXT: Invalidating analysis: ScalarEvolutionAnalysis ; CHECK-O-NEXT: Finished llvm::Function pass manager run. ; CHECK-O-NEXT: Running pass: GlobalDCEPass ; CHECK-O-NEXT: Running pass: ConstantMergePass Index: llvm/trunk/test/Other/new-pm-lto-defaults.ll =================================================================== --- llvm/trunk/test/Other/new-pm-lto-defaults.ll +++ llvm/trunk/test/Other/new-pm-lto-defaults.ll @@ -37,7 +37,6 @@ ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis ; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: CallGraphAnalysis -; CHECK-O-NEXT: Invalidating analysis: CallGraphAnalysis ; CHECK-O-NEXT: Running pass: GlobalSplitPass ; CHECK-O-NEXT: Running pass: WholeProgramDevirtPass ; CHECK-O2-NEXT: Running pass: GlobalOptPass Index: llvm/trunk/test/Transforms/GlobalDCE/crash-assertingvh.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalDCE/crash-assertingvh.ll +++ llvm/trunk/test/Transforms/GlobalDCE/crash-assertingvh.ll @@ -3,6 +3,7 @@ ; to assert when global DCE deletes the body of the function. ; ; RUN: opt -disable-output < %s -passes='module(function(jump-threading),globaldce)' +; RUN: opt -disable-output < %s -passes='module(rpo-functionattrs,globaldce)' target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: llvm/trunk/test/Transforms/Inline/clear-analyses.ll =================================================================== --- llvm/trunk/test/Transforms/Inline/clear-analyses.ll +++ llvm/trunk/test/Transforms/Inline/clear-analyses.ll @@ -1,8 +1,7 @@ -; Test that the inliner clears analyses which may hold references to function -; bodies when it decides to delete them after inlining the last caller. -; We check this by using correlated-propagation to populate LVI with basic -; block references that would dangle if we failed to clear the inlined function -; body. +; Test that when a pass like correlated-propagation populates an analysis such +; as LVI with references back into the IR of a function that the inliner will +; delete, this doesn't crash or go awry despite the inliner clearing the analyses +; separately from when it deletes the function. ; ; RUN: opt -debug-pass-manager -S < %s 2>&1 \ ; RUN: -passes='cgscc(inline,function(correlated-propagation))' \