Index: include/llvm/Analysis/BlockFrequencyInfo.h =================================================================== --- include/llvm/Analysis/BlockFrequencyInfo.h +++ include/llvm/Analysis/BlockFrequencyInfo.h @@ -45,6 +45,10 @@ ~BlockFrequencyInfo(); + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); + const Function *getFunction() const; const BranchProbabilityInfo *getBPI() const; void view() const; Index: include/llvm/Analysis/DominanceFrontier.h =================================================================== --- include/llvm/Analysis/DominanceFrontier.h +++ include/llvm/Analysis/DominanceFrontier.h @@ -141,6 +141,10 @@ typedef DominanceFrontierBase::DomSetType DomSetType; typedef DominanceFrontierBase::iterator iterator; typedef DominanceFrontierBase::const_iterator const_iterator; + + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); }; class DominanceFrontierWrapperPass : public FunctionPass { Index: include/llvm/Analysis/LoopInfo.h =================================================================== --- include/llvm/Analysis/LoopInfo.h +++ include/llvm/Analysis/LoopInfo.h @@ -682,6 +682,10 @@ return *this; } + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); + // Most of the public interface is provided via LoopInfoBase. /// Update LoopInfo after removing the last backedge from a loop. This updates Index: include/llvm/Analysis/PostDominators.h =================================================================== --- include/llvm/Analysis/PostDominators.h +++ include/llvm/Analysis/PostDominators.h @@ -26,6 +26,10 @@ typedef DominatorTreeBase Base; PostDominatorTree() : DominatorTreeBase(true) {} + + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); }; /// \brief Analysis pass which computes a \c PostDominatorTree. Index: include/llvm/Analysis/RegionInfo.h =================================================================== --- include/llvm/Analysis/RegionInfo.h +++ include/llvm/Analysis/RegionInfo.h @@ -886,6 +886,10 @@ return *this; } + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); + // updateStatistics - Update statistic about created regions. void updateStatistics(Region *R) final; Index: include/llvm/IR/Dominators.h =================================================================== --- include/llvm/IR/Dominators.h +++ include/llvm/IR/Dominators.h @@ -102,6 +102,10 @@ recalculate(F); } + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); + /// \brief Returns *false* if the other dominator tree matches this dominator /// tree. inline bool compare(const DominatorTree &Other) const { Index: include/llvm/IR/PassManager.h =================================================================== --- include/llvm/IR/PassManager.h +++ include/llvm/IR/PassManager.h @@ -73,6 +73,46 @@ /// if it is, the analysis knows that it itself is preserved. struct alignas(8) AnalysisSetKey {}; +/// This templated class represents "all analyses that operate over \" (e.g. a Function or a Module) in instances of +/// PreservedAnalysis. +/// +/// This lets a transformation say e.g. "I preserved all function analyses". +/// +/// Note that you must provide an explicit instantiation declaration and +/// definition for this template in order to get the correct behavior on +/// Windows. Otherwise, the address of SetKey will not be stable. +template class AllAnalysesOn { +public: + static AnalysisSetKey *ID() { return &SetKey; } + +private: + static AnalysisSetKey SetKey; +}; + +template AnalysisSetKey AllAnalysesOn::SetKey; + +extern template class AllAnalysesOn; +extern template class AllAnalysesOn; + +/// An analysis set representing the CFG of a function. +/// +/// This can be used with \c PreservedAnalyses to mark the CFG as preserved and +/// to query whether it has been preserved. +/// +/// The CFG of a function is defined as the set of basic blocks and the edges +/// between them. Changing the set of basic blocks in a function is enough to +/// mutate the CFG. Mutating the condition of a branch or argument of an +/// invoked function does not mutate the CFG, but changing the successor labels +/// of those instructions does. +class CFGAnalyses { +public: + static AnalysisSetKey *ID() { return &SetKey; } + +private: + static AnalysisSetKey SetKey; +}; + /// A set of analyses that are preserved following a run of a transformation /// pass. /// @@ -342,29 +382,6 @@ static AnalysisKey *ID() { return &DerivedT::Key; } }; -/// This templated class represents "all analyses that operate over \" (e.g. a Function or a Module) in instances of -/// PreservedAnalysis. -/// -/// This lets a transformation say e.g. "I preserved all function analyses". -/// -/// Note that you must provide an explicit instantiation declaration and -/// definition for this template in order to get the correct behavior on -/// Windows. Otherwise, the address of SetKey will not be stable. -template -class AllAnalysesOn { -public: - static AnalysisSetKey *ID() { return &SetKey; } - -private: - static AnalysisSetKey SetKey; -}; - -template AnalysisSetKey AllAnalysesOn::SetKey; - -extern template class AllAnalysesOn; -extern template class AllAnalysesOn; - /// \brief Manages a sequence of passes over a particular unit of IR. /// /// A pass manager contains a sequence of passes to run over a particular unit Index: lib/Analysis/BlockFrequencyInfo.cpp =================================================================== --- lib/Analysis/BlockFrequencyInfo.cpp +++ lib/Analysis/BlockFrequencyInfo.cpp @@ -132,6 +132,15 @@ // template instantiated which is not available in the header. BlockFrequencyInfo::~BlockFrequencyInfo() {} +bool BlockFrequencyInfo::invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &) { + // Check whether the analysis, all analyses on functions, or the function's + // CFG have been preserved. + auto PAC = PA.getChecker(); + return !(PAC.preserved() || PAC.preservedSet>() || + PAC.preservedSet()); +} + void BlockFrequencyInfo::calculate(const Function &F, const BranchProbabilityInfo &BPI, const LoopInfo &LI) { Index: lib/Analysis/DominanceFrontier.cpp =================================================================== --- lib/Analysis/DominanceFrontier.cpp +++ lib/Analysis/DominanceFrontier.cpp @@ -56,6 +56,16 @@ } #endif +/// Handle invalidation explicitly. +bool DominanceFrontier::invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &) { + // Check whether the analysis, all analyses on functions, or the function's + // CFG have been preserved. + auto PAC = PA.getChecker(); + return !(PAC.preserved() || PAC.preservedSet>() || + PAC.preservedSet()); +} + AnalysisKey DominanceFrontierAnalysis::Key; DominanceFrontier DominanceFrontierAnalysis::run(Function &F, Index: lib/Analysis/LoopInfo.cpp =================================================================== --- lib/Analysis/LoopInfo.cpp +++ lib/Analysis/LoopInfo.cpp @@ -610,6 +610,15 @@ analyze(DomTree); } +bool LoopInfo::invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &) { + // Check whether the analysis, all analyses on functions, or the function's + // CFG have been preserved. + auto PAC = PA.getChecker(); + return !(PAC.preserved() || PAC.preservedSet>() || + PAC.preservedSet()); +} + void LoopInfo::markAsRemoved(Loop *Unloop) { assert(!Unloop->isInvalid() && "Loop has already been removed"); Unloop->invalidate(); Index: lib/Analysis/PostDominators.cpp =================================================================== --- lib/Analysis/PostDominators.cpp +++ lib/Analysis/PostDominators.cpp @@ -31,6 +31,15 @@ INITIALIZE_PASS(PostDominatorTreeWrapperPass, "postdomtree", "Post-Dominator Tree Construction", true, true) +bool PostDominatorTree::invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &) { + // Check whether the analysis, all analyses on functions, or the function's + // CFG have been preserved. + auto PAC = PA.getChecker(); + return !(PAC.preserved() || PAC.preservedSet>() || + PAC.preservedSet()); +} + bool PostDominatorTreeWrapperPass::runOnFunction(Function &F) { DT.recalculate(F); return false; Index: lib/Analysis/RegionInfo.cpp =================================================================== --- lib/Analysis/RegionInfo.cpp +++ lib/Analysis/RegionInfo.cpp @@ -83,6 +83,15 @@ } +bool RegionInfo::invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &) { + // Check whether the analysis, all analyses on functions, or the function's + // CFG have been preserved. + auto PAC = PA.getChecker(); + return !(PAC.preserved() || PAC.preservedSet>() || + PAC.preservedSet()); +} + void RegionInfo::updateStatistics(Region *R) { ++numRegions; Index: lib/IR/Dominators.cpp =================================================================== --- lib/IR/Dominators.cpp +++ lib/IR/Dominators.cpp @@ -73,6 +73,15 @@ GraphTraits>::NodeRef>::type> &DT, Function &F); +bool DominatorTree::invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &) { + // Check whether the analysis, all analyses on functions, or the function's + // CFG have been preserved. + auto PAC = PA.getChecker(); + return !(PAC.preserved() || PAC.preservedSet>() || + PAC.preservedSet()); +} + // dominates - Return true if Def dominates a use in User. This performs // the special checks necessary if Def and User are in the same basic block. // Note that Def doesn't dominate a use in Def itself! Index: lib/IR/PassManager.cpp =================================================================== --- lib/IR/PassManager.cpp +++ lib/IR/PassManager.cpp @@ -91,4 +91,6 @@ } } +AnalysisSetKey CFGAnalyses::SetKey; + AnalysisSetKey PreservedAnalyses::AllAnalysesKey; Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3176,10 +3176,9 @@ return PreservedAnalyses::all(); // Mark all the analyses that instcombine updates as preserved. - // FIXME: This should also 'preserve the CFG'. PreservedAnalyses PA; + PA.preserveSet(); PA.preserve(); - PA.preserve(); PA.preserve(); return PA; } Index: lib/Transforms/Scalar/ADCE.cpp =================================================================== --- lib/Transforms/Scalar/ADCE.cpp +++ lib/Transforms/Scalar/ADCE.cpp @@ -644,8 +644,8 @@ if (!AggressiveDeadCodeElimination(F, PDT).performDeadCodeElimination()) return PreservedAnalyses::all(); - // FIXME: This should also 'preserve the CFG'. - auto PA = PreservedAnalyses(); + PreservedAnalyses PA; + PA.preserveSet(); PA.preserve(); return PA; } Index: lib/Transforms/Scalar/AlignmentFromAssumptions.cpp =================================================================== --- lib/Transforms/Scalar/AlignmentFromAssumptions.cpp +++ lib/Transforms/Scalar/AlignmentFromAssumptions.cpp @@ -446,11 +446,11 @@ if (!Changed) return PreservedAnalyses::all(); + PreservedAnalyses PA; + PA.preserveSet(); PA.preserve(); PA.preserve(); PA.preserve(); - PA.preserve(); - PA.preserve(); return PA; } Index: lib/Transforms/Scalar/BDCE.cpp =================================================================== --- lib/Transforms/Scalar/BDCE.cpp +++ lib/Transforms/Scalar/BDCE.cpp @@ -80,8 +80,8 @@ if (!bitTrackingDCE(F, DB)) return PreservedAnalyses::all(); - // FIXME: This should also 'preserve the CFG'. - auto PA = PreservedAnalyses(); + PreservedAnalyses PA; + PA.preserveSet(); PA.preserve(); return PA; } Index: lib/Transforms/Scalar/ConstantHoisting.cpp =================================================================== --- lib/Transforms/Scalar/ConstantHoisting.cpp +++ lib/Transforms/Scalar/ConstantHoisting.cpp @@ -623,6 +623,7 @@ if (!runImpl(F, TTI, DT, F.getEntryBlock())) return PreservedAnalyses::all(); - // FIXME: This should also 'preserve the CFG'. - return PreservedAnalyses::none(); + PreservedAnalyses PA; + PA.preserveSet(); + return PA; } Index: lib/Transforms/Scalar/DCE.cpp =================================================================== --- lib/Transforms/Scalar/DCE.cpp +++ lib/Transforms/Scalar/DCE.cpp @@ -124,9 +124,12 @@ } PreservedAnalyses DCEPass::run(Function &F, FunctionAnalysisManager &AM) { - if (eliminateDeadCode(F, AM.getCachedResult(F))) - return PreservedAnalyses::none(); - return PreservedAnalyses::all(); + if (!eliminateDeadCode(F, AM.getCachedResult(F))) + return PreservedAnalyses::all(); + + PreservedAnalyses PA; + PA.preserveSet(); + return PA; } namespace { Index: lib/Transforms/Scalar/DeadStoreElimination.cpp =================================================================== --- lib/Transforms/Scalar/DeadStoreElimination.cpp +++ lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -1186,8 +1186,9 @@ if (!eliminateDeadStores(F, AA, MD, DT, TLI)) return PreservedAnalyses::all(); + PreservedAnalyses PA; - PA.preserve(); + PA.preserveSet(); PA.preserve(); PA.preserve(); return PA; Index: lib/Transforms/Scalar/EarlyCSE.cpp =================================================================== --- lib/Transforms/Scalar/EarlyCSE.cpp +++ lib/Transforms/Scalar/EarlyCSE.cpp @@ -967,10 +967,8 @@ if (!CSE.run()) return PreservedAnalyses::all(); - // CSE preserves the dominator tree because it doesn't mutate the CFG. - // FIXME: Bundle this with other CFG-preservation. PreservedAnalyses PA; - PA.preserve(); + PA.preserveSet(); PA.preserve(); if (UseMemorySSA) PA.preserve(); Index: lib/Transforms/Scalar/Float2Int.cpp =================================================================== --- lib/Transforms/Scalar/Float2Int.cpp +++ lib/Transforms/Scalar/Float2Int.cpp @@ -516,11 +516,10 @@ PreservedAnalyses Float2IntPass::run(Function &F, FunctionAnalysisManager &) { if (!runImpl(F)) return PreservedAnalyses::all(); - else { - // FIXME: This should also 'preserve the CFG'. - PreservedAnalyses PA; - PA.preserve(); - return PA; - } + + PreservedAnalyses PA; + PA.preserveSet(); + PA.preserve(); + return PA; } } // End namespace llvm Index: lib/Transforms/Scalar/GuardWidening.cpp =================================================================== --- lib/Transforms/Scalar/GuardWidening.cpp +++ lib/Transforms/Scalar/GuardWidening.cpp @@ -658,8 +658,12 @@ auto &DT = AM.getResult(F); auto &LI = AM.getResult(F); auto &PDT = AM.getResult(F); - bool Changed = GuardWideningImpl(DT, PDT, LI).run(); - return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); + if (!GuardWideningImpl(DT, PDT, LI).run()) + return PreservedAnalyses::all(); + + PreservedAnalyses PA; + PA.preserveSet(); + return PA; } StringRef GuardWideningImpl::scoreTypeToString(WideningScore WS) { Index: lib/Transforms/Scalar/IndVarSimplify.cpp =================================================================== --- lib/Transforms/Scalar/IndVarSimplify.cpp +++ lib/Transforms/Scalar/IndVarSimplify.cpp @@ -2492,8 +2492,9 @@ if (!IVS.run(&L)) return PreservedAnalyses::all(); - // FIXME: This should also 'preserve the CFG'. - return getLoopPassPreservedAnalyses(); + auto PA = getLoopPassPreservedAnalyses(); + PA.preserveSet(); + return PA; } namespace { Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -201,9 +201,9 @@ if (!LICM.runOnLoop(&L, &AR.AA, &AR.LI, &AR.DT, &AR.TLI, &AR.SE, ORE, true)) return PreservedAnalyses::all(); - // FIXME: There is no setPreservesCFG in the new PM. When that becomes - // available, it should be used here. - return getLoopPassPreservedAnalyses(); + auto PA = getLoopPassPreservedAnalyses(); + PA.preserveSet(); + return PA; } char LegacyLICMPass::ID = 0; Index: lib/Transforms/Scalar/LoopInstSimplify.cpp =================================================================== --- lib/Transforms/Scalar/LoopInstSimplify.cpp +++ lib/Transforms/Scalar/LoopInstSimplify.cpp @@ -189,7 +189,9 @@ if (!SimplifyLoopInst(&L, &AR.DT, &AR.LI, &AR.AC, &AR.TLI)) return PreservedAnalyses::all(); - return getLoopPassPreservedAnalyses(); + auto PA = getLoopPassPreservedAnalyses(); + PA.preserveSet(); + return PA; } char LoopInstSimplifyLegacyPass::ID = 0; Index: lib/Transforms/Scalar/LoopRotation.cpp =================================================================== --- lib/Transforms/Scalar/LoopRotation.cpp +++ lib/Transforms/Scalar/LoopRotation.cpp @@ -634,6 +634,7 @@ bool Changed = LR.processLoop(&L); if (!Changed) return PreservedAnalyses::all(); + return getLoopPassPreservedAnalyses(); } Index: lib/Transforms/Scalar/LoopSimplifyCFG.cpp =================================================================== --- lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -69,6 +69,7 @@ LPMUpdater &) { if (!simplifyLoopCFG(L, AR.DT, AR.LI)) return PreservedAnalyses::all(); + return getLoopPassPreservedAnalyses(); } Index: lib/Transforms/Scalar/LoopUnrollPass.cpp =================================================================== --- lib/Transforms/Scalar/LoopUnrollPass.cpp +++ lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -1128,8 +1128,8 @@ /*PreserveLCSSA*/ true, ProvidedCount, ProvidedThreshold, ProvidedAllowPartial, ProvidedRuntime, ProvidedUpperBound); - if (!Changed) return PreservedAnalyses::all(); + return getLoopPassPreservedAnalyses(); } Index: lib/Transforms/Scalar/MemCpyOptimizer.cpp =================================================================== --- lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -1393,7 +1393,9 @@ LookupAssumptionCache, LookupDomTree); if (!MadeChange) return PreservedAnalyses::all(); + PreservedAnalyses PA; + PA.preserveSet(); PA.preserve(); PA.preserve(); return PA; Index: lib/Transforms/Scalar/MergedLoadStoreMotion.cpp =================================================================== --- lib/Transforms/Scalar/MergedLoadStoreMotion.cpp +++ lib/Transforms/Scalar/MergedLoadStoreMotion.cpp @@ -596,8 +596,8 @@ if (!Impl.run(F, MD, AA)) return PreservedAnalyses::all(); - // FIXME: This should also 'preserve the CFG'. PreservedAnalyses PA; + PA.preserveSet(); PA.preserve(); PA.preserve(); return PA; Index: lib/Transforms/Scalar/NaryReassociate.cpp =================================================================== --- lib/Transforms/Scalar/NaryReassociate.cpp +++ lib/Transforms/Scalar/NaryReassociate.cpp @@ -165,11 +165,9 @@ if (!Changed) return PreservedAnalyses::all(); - // FIXME: This should also 'preserve the CFG'. PreservedAnalyses PA; - PA.preserve(); + PA.preserveSet(); PA.preserve(); - PA.preserve(); return PA; } Index: lib/Transforms/Scalar/Reassociate.cpp =================================================================== --- lib/Transforms/Scalar/Reassociate.cpp +++ lib/Transforms/Scalar/Reassociate.cpp @@ -2236,8 +2236,8 @@ ValueRankMap.clear(); if (MadeChange) { - // FIXME: This should also 'preserve the CFG'. - auto PA = PreservedAnalyses(); + PreservedAnalyses PA; + PA.preserveSet(); PA.preserve(); return PA; } Index: lib/Transforms/Scalar/SROA.cpp =================================================================== --- lib/Transforms/Scalar/SROA.cpp +++ lib/Transforms/Scalar/SROA.cpp @@ -4235,9 +4235,8 @@ if (!Changed) return PreservedAnalyses::all(); - // FIXME: Even when promoting allocas we should preserve some abstract set of - // CFG-specific analyses. PreservedAnalyses PA; + PA.preserveSet(); PA.preserve(); return PA; } Index: lib/Transforms/Scalar/Sink.cpp =================================================================== --- lib/Transforms/Scalar/Sink.cpp +++ lib/Transforms/Scalar/Sink.cpp @@ -262,9 +262,8 @@ if (!iterativelySinkInstructions(F, DT, LI, AA)) return PreservedAnalyses::all(); - auto PA = PreservedAnalyses(); - PA.preserve(); - PA.preserve(); + PreservedAnalyses PA; + PA.preserveSet(); return PA; } Index: lib/Transforms/Utils/LCSSA.cpp =================================================================== --- lib/Transforms/Utils/LCSSA.cpp +++ lib/Transforms/Utils/LCSSA.cpp @@ -395,8 +395,8 @@ if (!formLCSSAOnAllLoops(&LI, DT, SE)) return PreservedAnalyses::all(); - // FIXME: This should also 'preserve the CFG'. PreservedAnalyses PA; + PA.preserveSet(); PA.preserve(); PA.preserve(); PA.preserve(); Index: lib/Transforms/Utils/Mem2Reg.cpp =================================================================== --- lib/Transforms/Utils/Mem2Reg.cpp +++ lib/Transforms/Utils/Mem2Reg.cpp @@ -59,8 +59,9 @@ if (!promoteMemoryToRegister(F, DT, AC)) return PreservedAnalyses::all(); - // FIXME: This should also 'preserve the CFG'. - return PreservedAnalyses::none(); + PreservedAnalyses PA; + PA.preserveSet(); + return PA; } namespace { Index: lib/Transforms/Utils/SimplifyInstructions.cpp =================================================================== --- lib/Transforms/Utils/SimplifyInstructions.cpp +++ lib/Transforms/Utils/SimplifyInstructions.cpp @@ -136,6 +136,8 @@ bool Changed = runImpl(F, &DT, &TLI, &AC); if (!Changed) return PreservedAnalyses::all(); - // FIXME: This should also 'preserve the CFG'. - return PreservedAnalyses::none(); + + PreservedAnalyses PA; + PA.preserveSet(); + return PA; } Index: lib/Transforms/Vectorize/SLPVectorizer.cpp =================================================================== --- lib/Transforms/Vectorize/SLPVectorizer.cpp +++ lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -3645,9 +3645,9 @@ bool Changed = runImpl(F, SE, TTI, TLI, AA, LI, DT, AC, DB); if (!Changed) return PreservedAnalyses::all(); + PreservedAnalyses PA; - PA.preserve(); - PA.preserve(); + PA.preserveSet(); PA.preserve(); PA.preserve(); return PA;