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<Function> F;
+  Function *F;
 
   std::vector<CallRecord> 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<BasicBlock> ExitingBlock;
+    PoisoningVH<BasicBlock> ExitingBlock;
     const SCEV *ExactNotTaken;
     std::unique_ptr<SCEVUnionPredicate> Predicate;
     bool hasAlwaysTruePredicate() const {
       return !Predicate || Predicate->isAlwaysTrue();
     }
 
-    explicit ExitNotTakenInfo(AssertingVH<BasicBlock> ExitingBlock,
+    explicit ExitNotTakenInfo(PoisoningVH<BasicBlock> ExitingBlock,
                               const SCEV *ExactNotTaken,
                               std::unique_ptr<SCEVUnionPredicate> 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<AssertingVH<BasicBlock>, LVILatticeVal, 4> BlockVals;
+      SmallDenseMap<PoisoningVH<BasicBlock>, 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<AssertingVH<BasicBlock>, SmallPtrSet<Value *, 4>>
+    typedef DenseMap<PoisoningVH<BasicBlock>, SmallPtrSet<Value *, 4>>
         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<AssertingVH<BasicBlock> > SeenBlocks;
+    DenseSet<PoisoningVH<BasicBlock> > SeenBlocks;
 
   public:
     void insertResult(Value *Val, BasicBlock *BB, const LVILatticeVal &Result) {
@@ -464,10 +464,10 @@
     SmallPtrSetImpl<Value *> &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<AssertingVH<BasicBlock> >::iterator I = SeenBlocks.find(BB);
+  DenseSet<PoisoningVH<BasicBlock> >::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<CallGraphAnalysis>(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<CallGraphAnalysis>(M);
-
-  if (!Changed)
+  if (!deduceFunctionAttributeInRPO(M, CG))
     return PreservedAnalyses::all();
+
   PreservedAnalyses PA;
   PA.preserve<CallGraphAnalysis>();
   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<FunctionAnalysisManagerModuleProxy>(M))
-    FAM = &FAMProxy->getManager();
-
   // The second pass drops the bodies of functions which are dead...
   std::vector<Function *> 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<FunctionAnalysisManagerCGSCCProxy>(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<AssumptionAnalysis>(F);
   ScalarEvolution &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
   DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F);
-  bool Changed = runImpl(F, AC, &SE, &DT);
-
-  // FIXME: We need to invalidate this to avoid PR28400. Is there a better
-  // solution?
-  AM.invalidate<ScalarEvolutionAnalysis>(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<TargetLibraryAnalysis>(F);
   auto *TTI = &AM.getResult<TargetIRAnalysis>(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<ScalarEvolutionAnalysis>(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<ScalarEvolutionAnalysis>(F);
-
   if (!Changed)
     return PreservedAnalyses::all();
+
   PreservedAnalyses PA;
   PA.preserve<DominatorTreeAnalysis>();
   PA.preserve<LoopAnalysis>();
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))' \