Path: blob/main/contrib/llvm-project/llvm/lib/Analysis/CGSCCPassManager.cpp
35233 views
//===- CGSCCPassManager.cpp - Managing & running CGSCC passes -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Analysis/CGSCCPassManager.h"9#include "llvm/ADT/ArrayRef.h"10#include "llvm/ADT/PriorityWorklist.h"11#include "llvm/ADT/STLExtras.h"12#include "llvm/ADT/SetVector.h"13#include "llvm/ADT/SmallPtrSet.h"14#include "llvm/ADT/SmallVector.h"15#include "llvm/ADT/iterator_range.h"16#include "llvm/Analysis/LazyCallGraph.h"17#include "llvm/IR/Constant.h"18#include "llvm/IR/InstIterator.h"19#include "llvm/IR/Instruction.h"20#include "llvm/IR/PassManager.h"21#include "llvm/IR/PassManagerImpl.h"22#include "llvm/IR/ValueHandle.h"23#include "llvm/Support/Casting.h"24#include "llvm/Support/CommandLine.h"25#include "llvm/Support/Debug.h"26#include "llvm/Support/ErrorHandling.h"27#include "llvm/Support/TimeProfiler.h"28#include "llvm/Support/raw_ostream.h"29#include <cassert>30#include <iterator>31#include <optional>3233#define DEBUG_TYPE "cgscc"3435using namespace llvm;3637// Explicit template instantiations and specialization definitions for core38// template typedefs.39namespace llvm {40static cl::opt<bool> AbortOnMaxDevirtIterationsReached(41"abort-on-max-devirt-iterations-reached",42cl::desc("Abort when the max iterations for devirtualization CGSCC repeat "43"pass is reached"));4445AnalysisKey ShouldNotRunFunctionPassesAnalysis::Key;4647// Explicit instantiations for the core proxy templates.48template class AllAnalysesOn<LazyCallGraph::SCC>;49template class AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>;50template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager,51LazyCallGraph &, CGSCCUpdateResult &>;52template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>;53template class OuterAnalysisManagerProxy<ModuleAnalysisManager,54LazyCallGraph::SCC, LazyCallGraph &>;55template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>;5657/// Explicitly specialize the pass manager run method to handle call graph58/// updates.59template <>60PreservedAnalyses61PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,62CGSCCUpdateResult &>::run(LazyCallGraph::SCC &InitialC,63CGSCCAnalysisManager &AM,64LazyCallGraph &G, CGSCCUpdateResult &UR) {65// Request PassInstrumentation from analysis manager, will use it to run66// instrumenting callbacks for the passes later.67PassInstrumentation PI =68AM.getResult<PassInstrumentationAnalysis>(InitialC, G);6970PreservedAnalyses PA = PreservedAnalyses::all();7172// The SCC may be refined while we are running passes over it, so set up73// a pointer that we can update.74LazyCallGraph::SCC *C = &InitialC;7576// Get Function analysis manager from its proxy.77FunctionAnalysisManager &FAM =78AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(*C)->getManager();7980for (auto &Pass : Passes) {81// Check the PassInstrumentation's BeforePass callbacks before running the82// pass, skip its execution completely if asked to (callback returns false).83if (!PI.runBeforePass(*Pass, *C))84continue;8586PreservedAnalyses PassPA = Pass->run(*C, AM, G, UR);8788// Update the SCC if necessary.89C = UR.UpdatedC ? UR.UpdatedC : C;90if (UR.UpdatedC) {91// If C is updated, also create a proxy and update FAM inside the result.92auto *ResultFAMCP =93&AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G);94ResultFAMCP->updateFAM(FAM);95}9697// Intersect the final preserved analyses to compute the aggregate98// preserved set for this pass manager.99PA.intersect(PassPA);100101// If the CGSCC pass wasn't able to provide a valid updated SCC, the102// current SCC may simply need to be skipped if invalid.103if (UR.InvalidatedSCCs.count(C)) {104PI.runAfterPassInvalidated<LazyCallGraph::SCC>(*Pass, PassPA);105LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");106break;107}108109// Check that we didn't miss any update scenario.110assert(C->begin() != C->end() && "Cannot have an empty SCC!");111112// Update the analysis manager as each pass runs and potentially113// invalidates analyses.114AM.invalidate(*C, PassPA);115116PI.runAfterPass<LazyCallGraph::SCC>(*Pass, *C, PassPA);117}118119// Before we mark all of *this* SCC's analyses as preserved below, intersect120// this with the cross-SCC preserved analysis set. This is used to allow121// CGSCC passes to mutate ancestor SCCs and still trigger proper invalidation122// for them.123UR.CrossSCCPA.intersect(PA);124125// Invalidation was handled after each pass in the above loop for the current126// SCC. Therefore, the remaining analysis results in the AnalysisManager are127// preserved. We mark this with a set so that we don't need to inspect each128// one individually.129PA.preserveSet<AllAnalysesOn<LazyCallGraph::SCC>>();130131return PA;132}133134PreservedAnalyses135ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) {136// Setup the CGSCC analysis manager from its proxy.137CGSCCAnalysisManager &CGAM =138AM.getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager();139140// Get the call graph for this module.141LazyCallGraph &CG = AM.getResult<LazyCallGraphAnalysis>(M);142143// Get Function analysis manager from its proxy.144FunctionAnalysisManager &FAM =145AM.getCachedResult<FunctionAnalysisManagerModuleProxy>(M)->getManager();146147// We keep worklists to allow us to push more work onto the pass manager as148// the passes are run.149SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> RCWorklist;150SmallPriorityWorklist<LazyCallGraph::SCC *, 1> CWorklist;151152// Keep sets for invalidated SCCs that should be skipped when153// iterating off the worklists.154SmallPtrSet<LazyCallGraph::SCC *, 4> InvalidSCCSet;155156SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4>157InlinedInternalEdges;158159SmallVector<Function *, 4> DeadFunctions;160161CGSCCUpdateResult UR = {CWorklist,162InvalidSCCSet,163nullptr,164PreservedAnalyses::all(),165InlinedInternalEdges,166DeadFunctions,167{}};168169// Request PassInstrumentation from analysis manager, will use it to run170// instrumenting callbacks for the passes later.171PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(M);172173PreservedAnalyses PA = PreservedAnalyses::all();174CG.buildRefSCCs();175for (LazyCallGraph::RefSCC &RC :176llvm::make_early_inc_range(CG.postorder_ref_sccs())) {177assert(RCWorklist.empty() &&178"Should always start with an empty RefSCC worklist");179// The postorder_ref_sccs range we are walking is lazily constructed, so180// we only push the first one onto the worklist. The worklist allows us181// to capture *new* RefSCCs created during transformations.182//183// We really want to form RefSCCs lazily because that makes them cheaper184// to update as the program is simplified and allows us to have greater185// cache locality as forming a RefSCC touches all the parts of all the186// functions within that RefSCC.187//188// We also eagerly increment the iterator to the next position because189// the CGSCC passes below may delete the current RefSCC.190RCWorklist.insert(&RC);191192do {193LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val();194assert(CWorklist.empty() &&195"Should always start with an empty SCC worklist");196197LLVM_DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC198<< "\n");199200// The top of the worklist may *also* be the same SCC we just ran over201// (and invalidated for). Keep track of that last SCC we processed due202// to SCC update to avoid redundant processing when an SCC is both just203// updated itself and at the top of the worklist.204LazyCallGraph::SCC *LastUpdatedC = nullptr;205206// Push the initial SCCs in reverse post-order as we'll pop off the207// back and so see this in post-order.208for (LazyCallGraph::SCC &C : llvm::reverse(*RC))209CWorklist.insert(&C);210211do {212LazyCallGraph::SCC *C = CWorklist.pop_back_val();213// Due to call graph mutations, we may have invalid SCCs or SCCs from214// other RefSCCs in the worklist. The invalid ones are dead and the215// other RefSCCs should be queued above, so we just need to skip both216// scenarios here.217if (InvalidSCCSet.count(C)) {218LLVM_DEBUG(dbgs() << "Skipping an invalid SCC...\n");219continue;220}221if (LastUpdatedC == C) {222LLVM_DEBUG(dbgs() << "Skipping redundant run on SCC: " << *C << "\n");223continue;224}225// We used to also check if the current SCC is part of the current226// RefSCC and bail if it wasn't, since it should be in RCWorklist.227// However, this can cause compile time explosions in some cases on228// modules with a huge RefSCC. If a non-trivial amount of SCCs in the229// huge RefSCC can become their own child RefSCC, we create one child230// RefSCC, bail on the current RefSCC, visit the child RefSCC, revisit231// the huge RefSCC, and repeat. By visiting all SCCs in the original232// RefSCC we create all the child RefSCCs in one pass of the RefSCC,233// rather one pass of the RefSCC creating one child RefSCC at a time.234235// Ensure we can proxy analysis updates from the CGSCC analysis manager236// into the Function analysis manager by getting a proxy here.237// This also needs to update the FunctionAnalysisManager, as this may be238// the first time we see this SCC.239CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).updateFAM(240FAM);241242// Each time we visit a new SCC pulled off the worklist,243// a transformation of a child SCC may have also modified this parent244// and invalidated analyses. So we invalidate using the update record's245// cross-SCC preserved set. This preserved set is intersected by any246// CGSCC pass that handles invalidation (primarily pass managers) prior247// to marking its SCC as preserved. That lets us track everything that248// might need invalidation across SCCs without excessive invalidations249// on a single SCC.250//251// This essentially allows SCC passes to freely invalidate analyses252// of any ancestor SCC. If this becomes detrimental to successfully253// caching analyses, we could force each SCC pass to manually254// invalidate the analyses for any SCCs other than themselves which255// are mutated. However, that seems to lose the robustness of the256// pass-manager driven invalidation scheme.257CGAM.invalidate(*C, UR.CrossSCCPA);258259do {260// Check that we didn't miss any update scenario.261assert(!InvalidSCCSet.count(C) && "Processing an invalid SCC!");262assert(C->begin() != C->end() && "Cannot have an empty SCC!");263264LastUpdatedC = UR.UpdatedC;265UR.UpdatedC = nullptr;266267// Check the PassInstrumentation's BeforePass callbacks before268// running the pass, skip its execution completely if asked to269// (callback returns false).270if (!PI.runBeforePass<LazyCallGraph::SCC>(*Pass, *C))271continue;272273PreservedAnalyses PassPA = Pass->run(*C, CGAM, CG, UR);274275// Update the SCC and RefSCC if necessary.276C = UR.UpdatedC ? UR.UpdatedC : C;277278if (UR.UpdatedC) {279// If we're updating the SCC, also update the FAM inside the proxy's280// result.281CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).updateFAM(282FAM);283}284285// Intersect with the cross-SCC preserved set to capture any286// cross-SCC invalidation.287UR.CrossSCCPA.intersect(PassPA);288// Intersect the preserved set so that invalidation of module289// analyses will eventually occur when the module pass completes.290PA.intersect(PassPA);291292// If the CGSCC pass wasn't able to provide a valid updated SCC,293// the current SCC may simply need to be skipped if invalid.294if (UR.InvalidatedSCCs.count(C)) {295PI.runAfterPassInvalidated<LazyCallGraph::SCC>(*Pass, PassPA);296LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");297break;298}299300// Check that we didn't miss any update scenario.301assert(C->begin() != C->end() && "Cannot have an empty SCC!");302303// We handle invalidating the CGSCC analysis manager's information304// for the (potentially updated) SCC here. Note that any other SCCs305// whose structure has changed should have been invalidated by306// whatever was updating the call graph. This SCC gets invalidated307// late as it contains the nodes that were actively being308// processed.309CGAM.invalidate(*C, PassPA);310311PI.runAfterPass<LazyCallGraph::SCC>(*Pass, *C, PassPA);312313// The pass may have restructured the call graph and refined the314// current SCC and/or RefSCC. We need to update our current SCC and315// RefSCC pointers to follow these. Also, when the current SCC is316// refined, re-run the SCC pass over the newly refined SCC in order317// to observe the most precise SCC model available. This inherently318// cannot cycle excessively as it only happens when we split SCCs319// apart, at most converging on a DAG of single nodes.320// FIXME: If we ever start having RefSCC passes, we'll want to321// iterate there too.322if (UR.UpdatedC)323LLVM_DEBUG(dbgs()324<< "Re-running SCC passes after a refinement of the "325"current SCC: "326<< *UR.UpdatedC << "\n");327328// Note that both `C` and `RC` may at this point refer to deleted,329// invalid SCC and RefSCCs respectively. But we will short circuit330// the processing when we check them in the loop above.331} while (UR.UpdatedC);332} while (!CWorklist.empty());333334// We only need to keep internal inlined edge information within335// a RefSCC, clear it to save on space and let the next time we visit336// any of these functions have a fresh start.337InlinedInternalEdges.clear();338} while (!RCWorklist.empty());339}340341CG.removeDeadFunctions(DeadFunctions);342for (Function *DeadF : DeadFunctions)343DeadF->eraseFromParent();344345#if defined(EXPENSIVE_CHECKS)346// Verify that the call graph is still valid.347CG.verify();348#endif349350// By definition we preserve the call garph, all SCC analyses, and the351// analysis proxies by handling them above and in any nested pass managers.352PA.preserveSet<AllAnalysesOn<LazyCallGraph::SCC>>();353PA.preserve<LazyCallGraphAnalysis>();354PA.preserve<CGSCCAnalysisManagerModuleProxy>();355PA.preserve<FunctionAnalysisManagerModuleProxy>();356return PA;357}358359PreservedAnalyses DevirtSCCRepeatedPass::run(LazyCallGraph::SCC &InitialC,360CGSCCAnalysisManager &AM,361LazyCallGraph &CG,362CGSCCUpdateResult &UR) {363PreservedAnalyses PA = PreservedAnalyses::all();364PassInstrumentation PI =365AM.getResult<PassInstrumentationAnalysis>(InitialC, CG);366367// The SCC may be refined while we are running passes over it, so set up368// a pointer that we can update.369LazyCallGraph::SCC *C = &InitialC;370371// Struct to track the counts of direct and indirect calls in each function372// of the SCC.373struct CallCount {374int Direct;375int Indirect;376};377378// Put value handles on all of the indirect calls and return the number of379// direct calls for each function in the SCC.380auto ScanSCC = [](LazyCallGraph::SCC &C,381SmallMapVector<Value *, WeakTrackingVH, 16> &CallHandles) {382assert(CallHandles.empty() && "Must start with a clear set of handles.");383384SmallDenseMap<Function *, CallCount> CallCounts;385CallCount CountLocal = {0, 0};386for (LazyCallGraph::Node &N : C) {387CallCount &Count =388CallCounts.insert(std::make_pair(&N.getFunction(), CountLocal))389.first->second;390for (Instruction &I : instructions(N.getFunction()))391if (auto *CB = dyn_cast<CallBase>(&I)) {392if (CB->getCalledFunction()) {393++Count.Direct;394} else {395++Count.Indirect;396CallHandles.insert({CB, WeakTrackingVH(CB)});397}398}399}400401return CallCounts;402};403404UR.IndirectVHs.clear();405// Populate the initial call handles and get the initial call counts.406auto CallCounts = ScanSCC(*C, UR.IndirectVHs);407408for (int Iteration = 0;; ++Iteration) {409if (!PI.runBeforePass<LazyCallGraph::SCC>(*Pass, *C))410continue;411412PreservedAnalyses PassPA = Pass->run(*C, AM, CG, UR);413414PA.intersect(PassPA);415416// If the CGSCC pass wasn't able to provide a valid updated SCC, the417// current SCC may simply need to be skipped if invalid.418if (UR.InvalidatedSCCs.count(C)) {419PI.runAfterPassInvalidated<LazyCallGraph::SCC>(*Pass, PassPA);420LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");421break;422}423424// Update the analysis manager with each run and intersect the total set425// of preserved analyses so we're ready to iterate.426AM.invalidate(*C, PassPA);427428PI.runAfterPass<LazyCallGraph::SCC>(*Pass, *C, PassPA);429430// If the SCC structure has changed, bail immediately and let the outer431// CGSCC layer handle any iteration to reflect the refined structure.432if (UR.UpdatedC && UR.UpdatedC != C)433break;434435assert(C->begin() != C->end() && "Cannot have an empty SCC!");436437// Check whether any of the handles were devirtualized.438bool Devirt = llvm::any_of(UR.IndirectVHs, [](auto &P) -> bool {439if (P.second) {440if (CallBase *CB = dyn_cast<CallBase>(P.second)) {441if (CB->getCalledFunction()) {442LLVM_DEBUG(dbgs() << "Found devirtualized call: " << *CB << "\n");443return true;444}445}446}447return false;448});449450// Rescan to build up a new set of handles and count how many direct451// calls remain. If we decide to iterate, this also sets up the input to452// the next iteration.453UR.IndirectVHs.clear();454auto NewCallCounts = ScanSCC(*C, UR.IndirectVHs);455456// If we haven't found an explicit devirtualization already see if we457// have decreased the number of indirect calls and increased the number458// of direct calls for any function in the SCC. This can be fooled by all459// manner of transformations such as DCE and other things, but seems to460// work well in practice.461if (!Devirt)462// Iterate over the keys in NewCallCounts, if Function also exists in463// CallCounts, make the check below.464for (auto &Pair : NewCallCounts) {465auto &CallCountNew = Pair.second;466auto CountIt = CallCounts.find(Pair.first);467if (CountIt != CallCounts.end()) {468const auto &CallCountOld = CountIt->second;469if (CallCountOld.Indirect > CallCountNew.Indirect &&470CallCountOld.Direct < CallCountNew.Direct) {471Devirt = true;472break;473}474}475}476477if (!Devirt) {478break;479}480481// Otherwise, if we've already hit our max, we're done.482if (Iteration >= MaxIterations) {483if (AbortOnMaxDevirtIterationsReached)484report_fatal_error("Max devirtualization iterations reached");485LLVM_DEBUG(486dbgs() << "Found another devirtualization after hitting the max "487"number of repetitions ("488<< MaxIterations << ") on SCC: " << *C << "\n");489break;490}491492LLVM_DEBUG(493dbgs() << "Repeating an SCC pass after finding a devirtualization in: "494<< *C << "\n");495496// Move over the new call counts in preparation for iterating.497CallCounts = std::move(NewCallCounts);498}499500// Note that we don't add any preserved entries here unlike a more normal501// "pass manager" because we only handle invalidation *between* iterations,502// not after the last iteration.503return PA;504}505506PreservedAnalyses CGSCCToFunctionPassAdaptor::run(LazyCallGraph::SCC &C,507CGSCCAnalysisManager &AM,508LazyCallGraph &CG,509CGSCCUpdateResult &UR) {510// Setup the function analysis manager from its proxy.511FunctionAnalysisManager &FAM =512AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();513514SmallVector<LazyCallGraph::Node *, 4> Nodes;515for (LazyCallGraph::Node &N : C)516Nodes.push_back(&N);517518// The SCC may get split while we are optimizing functions due to deleting519// edges. If this happens, the current SCC can shift, so keep track of520// a pointer we can overwrite.521LazyCallGraph::SCC *CurrentC = &C;522523LLVM_DEBUG(dbgs() << "Running function passes across an SCC: " << C << "\n");524525PreservedAnalyses PA = PreservedAnalyses::all();526for (LazyCallGraph::Node *N : Nodes) {527// Skip nodes from other SCCs. These may have been split out during528// processing. We'll eventually visit those SCCs and pick up the nodes529// there.530if (CG.lookupSCC(*N) != CurrentC)531continue;532533Function &F = N->getFunction();534535if (NoRerun && FAM.getCachedResult<ShouldNotRunFunctionPassesAnalysis>(F))536continue;537538PassInstrumentation PI = FAM.getResult<PassInstrumentationAnalysis>(F);539if (!PI.runBeforePass<Function>(*Pass, F))540continue;541542PreservedAnalyses PassPA = Pass->run(F, FAM);543544// We know that the function pass couldn't have invalidated any other545// function's analyses (that's the contract of a function pass), so546// directly handle the function analysis manager's invalidation here.547FAM.invalidate(F, EagerlyInvalidate ? PreservedAnalyses::none() : PassPA);548549PI.runAfterPass<Function>(*Pass, F, PassPA);550551// Then intersect the preserved set so that invalidation of module552// analyses will eventually occur when the module pass completes.553PA.intersect(std::move(PassPA));554555// If the call graph hasn't been preserved, update it based on this556// function pass. This may also update the current SCC to point to557// a smaller, more refined SCC.558auto PAC = PA.getChecker<LazyCallGraphAnalysis>();559if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {560CurrentC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentC, *N,561AM, UR, FAM);562assert(CG.lookupSCC(*N) == CurrentC &&563"Current SCC not updated to the SCC containing the current node!");564}565}566567// By definition we preserve the proxy. And we preserve all analyses on568// Functions. This precludes *any* invalidation of function analyses by the569// proxy, but that's OK because we've taken care to invalidate analyses in570// the function analysis manager incrementally above.571PA.preserveSet<AllAnalysesOn<Function>>();572PA.preserve<FunctionAnalysisManagerCGSCCProxy>();573574// We've also ensured that we updated the call graph along the way.575PA.preserve<LazyCallGraphAnalysis>();576577return PA;578}579580bool CGSCCAnalysisManagerModuleProxy::Result::invalidate(581Module &M, const PreservedAnalyses &PA,582ModuleAnalysisManager::Invalidator &Inv) {583// If literally everything is preserved, we're done.584if (PA.areAllPreserved())585return false; // This is still a valid proxy.586587// If this proxy or the call graph is going to be invalidated, we also need588// to clear all the keys coming from that analysis.589//590// We also directly invalidate the FAM's module proxy if necessary, and if591// that proxy isn't preserved we can't preserve this proxy either. We rely on592// it to handle module -> function analysis invalidation in the face of593// structural changes and so if it's unavailable we conservatively clear the594// entire SCC layer as well rather than trying to do invalidation ourselves.595auto PAC = PA.getChecker<CGSCCAnalysisManagerModuleProxy>();596if (!(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>()) ||597Inv.invalidate<LazyCallGraphAnalysis>(M, PA) ||598Inv.invalidate<FunctionAnalysisManagerModuleProxy>(M, PA)) {599InnerAM->clear();600601// And the proxy itself should be marked as invalid so that we can observe602// the new call graph. This isn't strictly necessary because we cheat603// above, but is still useful.604return true;605}606607// Directly check if the relevant set is preserved so we can short circuit608// invalidating SCCs below.609bool AreSCCAnalysesPreserved =610PA.allAnalysesInSetPreserved<AllAnalysesOn<LazyCallGraph::SCC>>();611612// Ok, we have a graph, so we can propagate the invalidation down into it.613G->buildRefSCCs();614for (auto &RC : G->postorder_ref_sccs())615for (auto &C : RC) {616std::optional<PreservedAnalyses> InnerPA;617618// Check to see whether the preserved set needs to be adjusted based on619// module-level analysis invalidation triggering deferred invalidation620// for this SCC.621if (auto *OuterProxy =622InnerAM->getCachedResult<ModuleAnalysisManagerCGSCCProxy>(C))623for (const auto &OuterInvalidationPair :624OuterProxy->getOuterInvalidations()) {625AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;626const auto &InnerAnalysisIDs = OuterInvalidationPair.second;627if (Inv.invalidate(OuterAnalysisID, M, PA)) {628if (!InnerPA)629InnerPA = PA;630for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)631InnerPA->abandon(InnerAnalysisID);632}633}634635// Check if we needed a custom PA set. If so we'll need to run the inner636// invalidation.637if (InnerPA) {638InnerAM->invalidate(C, *InnerPA);639continue;640}641642// Otherwise we only need to do invalidation if the original PA set didn't643// preserve all SCC analyses.644if (!AreSCCAnalysesPreserved)645InnerAM->invalidate(C, PA);646}647648// Return false to indicate that this result is still a valid proxy.649return false;650}651652template <>653CGSCCAnalysisManagerModuleProxy::Result654CGSCCAnalysisManagerModuleProxy::run(Module &M, ModuleAnalysisManager &AM) {655// Force the Function analysis manager to also be available so that it can656// be accessed in an SCC analysis and proxied onward to function passes.657// FIXME: It is pretty awkward to just drop the result here and assert that658// we can find it again later.659(void)AM.getResult<FunctionAnalysisManagerModuleProxy>(M);660661return Result(*InnerAM, AM.getResult<LazyCallGraphAnalysis>(M));662}663664AnalysisKey FunctionAnalysisManagerCGSCCProxy::Key;665666FunctionAnalysisManagerCGSCCProxy::Result667FunctionAnalysisManagerCGSCCProxy::run(LazyCallGraph::SCC &C,668CGSCCAnalysisManager &AM,669LazyCallGraph &CG) {670// Note: unconditionally getting checking that the proxy exists may get it at671// this point. There are cases when this is being run unnecessarily, but672// it is cheap and having the assertion in place is more valuable.673auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);674Module &M = *C.begin()->getFunction().getParent();675bool ProxyExists =676MAMProxy.cachedResultExists<FunctionAnalysisManagerModuleProxy>(M);677assert(ProxyExists &&678"The CGSCC pass manager requires that the FAM module proxy is run "679"on the module prior to entering the CGSCC walk");680(void)ProxyExists;681682// We just return an empty result. The caller will use the updateFAM interface683// to correctly register the relevant FunctionAnalysisManager based on the684// context in which this proxy is run.685return Result();686}687688bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(689LazyCallGraph::SCC &C, const PreservedAnalyses &PA,690CGSCCAnalysisManager::Invalidator &Inv) {691// If literally everything is preserved, we're done.692if (PA.areAllPreserved())693return false; // This is still a valid proxy.694695// All updates to preserve valid results are done below, so we don't need to696// invalidate this proxy.697//698// Note that in order to preserve this proxy, a module pass must ensure that699// the FAM has been completely updated to handle the deletion of functions.700// Specifically, any FAM-cached results for those functions need to have been701// forcibly cleared. When preserved, this proxy will only invalidate results702// cached on functions *still in the module* at the end of the module pass.703auto PAC = PA.getChecker<FunctionAnalysisManagerCGSCCProxy>();704if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<LazyCallGraph::SCC>>()) {705for (LazyCallGraph::Node &N : C)706FAM->invalidate(N.getFunction(), PA);707708return false;709}710711// Directly check if the relevant set is preserved.712bool AreFunctionAnalysesPreserved =713PA.allAnalysesInSetPreserved<AllAnalysesOn<Function>>();714715// Now walk all the functions to see if any inner analysis invalidation is716// necessary.717for (LazyCallGraph::Node &N : C) {718Function &F = N.getFunction();719std::optional<PreservedAnalyses> FunctionPA;720721// Check to see whether the preserved set needs to be pruned based on722// SCC-level analysis invalidation that triggers deferred invalidation723// registered with the outer analysis manager proxy for this function.724if (auto *OuterProxy =725FAM->getCachedResult<CGSCCAnalysisManagerFunctionProxy>(F))726for (const auto &OuterInvalidationPair :727OuterProxy->getOuterInvalidations()) {728AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;729const auto &InnerAnalysisIDs = OuterInvalidationPair.second;730if (Inv.invalidate(OuterAnalysisID, C, PA)) {731if (!FunctionPA)732FunctionPA = PA;733for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)734FunctionPA->abandon(InnerAnalysisID);735}736}737738// Check if we needed a custom PA set, and if so we'll need to run the739// inner invalidation.740if (FunctionPA) {741FAM->invalidate(F, *FunctionPA);742continue;743}744745// Otherwise we only need to do invalidation if the original PA set didn't746// preserve all function analyses.747if (!AreFunctionAnalysesPreserved)748FAM->invalidate(F, PA);749}750751// Return false to indicate that this result is still a valid proxy.752return false;753}754755} // end namespace llvm756757/// When a new SCC is created for the graph we first update the758/// FunctionAnalysisManager in the Proxy's result.759/// As there might be function analysis results cached for the functions now in760/// that SCC, two forms of updates are required.761///762/// First, a proxy from the SCC to the FunctionAnalysisManager needs to be763/// created so that any subsequent invalidation events to the SCC are764/// propagated to the function analysis results cached for functions within it.765///766/// Second, if any of the functions within the SCC have analysis results with767/// outer analysis dependencies, then those dependencies would point to the768/// *wrong* SCC's analysis result. We forcibly invalidate the necessary769/// function analyses so that they don't retain stale handles.770static void updateNewSCCFunctionAnalyses(LazyCallGraph::SCC &C,771LazyCallGraph &G,772CGSCCAnalysisManager &AM,773FunctionAnalysisManager &FAM) {774AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, G).updateFAM(FAM);775776// Now walk the functions in this SCC and invalidate any function analysis777// results that might have outer dependencies on an SCC analysis.778for (LazyCallGraph::Node &N : C) {779Function &F = N.getFunction();780781auto *OuterProxy =782FAM.getCachedResult<CGSCCAnalysisManagerFunctionProxy>(F);783if (!OuterProxy)784// No outer analyses were queried, nothing to do.785continue;786787// Forcibly abandon all the inner analyses with dependencies, but788// invalidate nothing else.789auto PA = PreservedAnalyses::all();790for (const auto &OuterInvalidationPair :791OuterProxy->getOuterInvalidations()) {792const auto &InnerAnalysisIDs = OuterInvalidationPair.second;793for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)794PA.abandon(InnerAnalysisID);795}796797// Now invalidate anything we found.798FAM.invalidate(F, PA);799}800}801802/// Helper function to update both the \c CGSCCAnalysisManager \p AM and the \c803/// CGSCCPassManager's \c CGSCCUpdateResult \p UR based on a range of newly804/// added SCCs.805///806/// The range of new SCCs must be in postorder already. The SCC they were split807/// out of must be provided as \p C. The current node being mutated and808/// triggering updates must be passed as \p N.809///810/// This function returns the SCC containing \p N. This will be either \p C if811/// no new SCCs have been split out, or it will be the new SCC containing \p N.812template <typename SCCRangeT>813static LazyCallGraph::SCC *814incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G,815LazyCallGraph::Node &N, LazyCallGraph::SCC *C,816CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) {817using SCC = LazyCallGraph::SCC;818819if (NewSCCRange.empty())820return C;821822// Add the current SCC to the worklist as its shape has changed.823UR.CWorklist.insert(C);824LLVM_DEBUG(dbgs() << "Enqueuing the existing SCC in the worklist:" << *C825<< "\n");826827SCC *OldC = C;828829// Update the current SCC. Note that if we have new SCCs, this must actually830// change the SCC.831assert(C != &*NewSCCRange.begin() &&832"Cannot insert new SCCs without changing current SCC!");833C = &*NewSCCRange.begin();834assert(G.lookupSCC(N) == C && "Failed to update current SCC!");835836// If we had a cached FAM proxy originally, we will want to create more of837// them for each SCC that was split off.838FunctionAnalysisManager *FAM = nullptr;839if (auto *FAMProxy =840AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(*OldC))841FAM = &FAMProxy->getManager();842843// We need to propagate an invalidation call to all but the newly current SCC844// because the outer pass manager won't do that for us after splitting them.845// FIXME: We should accept a PreservedAnalysis from the CG updater so that if846// there are preserved analysis we can avoid invalidating them here for847// split-off SCCs.848// We know however that this will preserve any FAM proxy so go ahead and mark849// that.850auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();851PA.preserve<FunctionAnalysisManagerCGSCCProxy>();852AM.invalidate(*OldC, PA);853854// Ensure the now-current SCC's function analyses are updated.855if (FAM)856updateNewSCCFunctionAnalyses(*C, G, AM, *FAM);857858for (SCC &NewC : llvm::reverse(llvm::drop_begin(NewSCCRange))) {859assert(C != &NewC && "No need to re-visit the current SCC!");860assert(OldC != &NewC && "Already handled the original SCC!");861UR.CWorklist.insert(&NewC);862LLVM_DEBUG(dbgs() << "Enqueuing a newly formed SCC:" << NewC << "\n");863864// Ensure new SCCs' function analyses are updated.865if (FAM)866updateNewSCCFunctionAnalyses(NewC, G, AM, *FAM);867868// Also propagate a normal invalidation to the new SCC as only the current869// will get one from the pass manager infrastructure.870AM.invalidate(NewC, PA);871}872return C;873}874875static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(876LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N,877CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,878FunctionAnalysisManager &FAM, bool FunctionPass) {879using Node = LazyCallGraph::Node;880using Edge = LazyCallGraph::Edge;881using SCC = LazyCallGraph::SCC;882using RefSCC = LazyCallGraph::RefSCC;883884RefSCC &InitialRC = InitialC.getOuterRefSCC();885SCC *C = &InitialC;886RefSCC *RC = &InitialRC;887Function &F = N.getFunction();888889// Walk the function body and build up the set of retained, promoted, and890// demoted edges.891SmallVector<Constant *, 16> Worklist;892SmallPtrSet<Constant *, 16> Visited;893SmallPtrSet<Node *, 16> RetainedEdges;894SmallSetVector<Node *, 4> PromotedRefTargets;895SmallSetVector<Node *, 4> DemotedCallTargets;896SmallSetVector<Node *, 4> NewCallEdges;897SmallSetVector<Node *, 4> NewRefEdges;898899// First walk the function and handle all called functions. We do this first900// because if there is a single call edge, whether there are ref edges is901// irrelevant.902for (Instruction &I : instructions(F)) {903if (auto *CB = dyn_cast<CallBase>(&I)) {904if (Function *Callee = CB->getCalledFunction()) {905if (Visited.insert(Callee).second && !Callee->isDeclaration()) {906Node *CalleeN = G.lookup(*Callee);907assert(CalleeN &&908"Visited function should already have an associated node");909Edge *E = N->lookup(*CalleeN);910assert((E || !FunctionPass) &&911"No function transformations should introduce *new* "912"call edges! Any new calls should be modeled as "913"promoted existing ref edges!");914bool Inserted = RetainedEdges.insert(CalleeN).second;915(void)Inserted;916assert(Inserted && "We should never visit a function twice.");917if (!E)918NewCallEdges.insert(CalleeN);919else if (!E->isCall())920PromotedRefTargets.insert(CalleeN);921}922} else {923// We can miss devirtualization if an indirect call is created then924// promoted before updateCGAndAnalysisManagerForPass runs.925auto *Entry = UR.IndirectVHs.find(CB);926if (Entry == UR.IndirectVHs.end())927UR.IndirectVHs.insert({CB, WeakTrackingVH(CB)});928else if (!Entry->second)929Entry->second = WeakTrackingVH(CB);930}931}932}933934// Now walk all references.935for (Instruction &I : instructions(F))936for (Value *Op : I.operand_values())937if (auto *OpC = dyn_cast<Constant>(Op))938if (Visited.insert(OpC).second)939Worklist.push_back(OpC);940941auto VisitRef = [&](Function &Referee) {942Node *RefereeN = G.lookup(Referee);943assert(RefereeN &&944"Visited function should already have an associated node");945Edge *E = N->lookup(*RefereeN);946assert((E || !FunctionPass) &&947"No function transformations should introduce *new* ref "948"edges! Any new ref edges would require IPO which "949"function passes aren't allowed to do!");950bool Inserted = RetainedEdges.insert(RefereeN).second;951(void)Inserted;952assert(Inserted && "We should never visit a function twice.");953if (!E)954NewRefEdges.insert(RefereeN);955else if (E->isCall())956DemotedCallTargets.insert(RefereeN);957};958LazyCallGraph::visitReferences(Worklist, Visited, VisitRef);959960// Handle new ref edges.961for (Node *RefTarget : NewRefEdges) {962SCC &TargetC = *G.lookupSCC(*RefTarget);963RefSCC &TargetRC = TargetC.getOuterRefSCC();964(void)TargetRC;965// TODO: This only allows trivial edges to be added for now.966#ifdef EXPENSIVE_CHECKS967assert((RC == &TargetRC ||968RC->isAncestorOf(TargetRC)) && "New ref edge is not trivial!");969#endif970RC->insertTrivialRefEdge(N, *RefTarget);971}972973// Handle new call edges.974for (Node *CallTarget : NewCallEdges) {975SCC &TargetC = *G.lookupSCC(*CallTarget);976RefSCC &TargetRC = TargetC.getOuterRefSCC();977(void)TargetRC;978// TODO: This only allows trivial edges to be added for now.979#ifdef EXPENSIVE_CHECKS980assert((RC == &TargetRC ||981RC->isAncestorOf(TargetRC)) && "New call edge is not trivial!");982#endif983// Add a trivial ref edge to be promoted later on alongside984// PromotedRefTargets.985RC->insertTrivialRefEdge(N, *CallTarget);986}987988// Include synthetic reference edges to known, defined lib functions.989for (auto *LibFn : G.getLibFunctions())990// While the list of lib functions doesn't have repeats, don't re-visit991// anything handled above.992if (!Visited.count(LibFn))993VisitRef(*LibFn);994995// First remove all of the edges that are no longer present in this function.996// The first step makes these edges uniformly ref edges and accumulates them997// into a separate data structure so removal doesn't invalidate anything.998SmallVector<Node *, 4> DeadTargets;999for (Edge &E : *N) {1000if (RetainedEdges.count(&E.getNode()))1001continue;10021003SCC &TargetC = *G.lookupSCC(E.getNode());1004RefSCC &TargetRC = TargetC.getOuterRefSCC();1005if (&TargetRC == RC && E.isCall()) {1006if (C != &TargetC) {1007// For separate SCCs this is trivial.1008RC->switchTrivialInternalEdgeToRef(N, E.getNode());1009} else {1010// Now update the call graph.1011C = incorporateNewSCCRange(RC->switchInternalEdgeToRef(N, E.getNode()),1012G, N, C, AM, UR);1013}1014}10151016// Now that this is ready for actual removal, put it into our list.1017DeadTargets.push_back(&E.getNode());1018}1019// Remove the easy cases quickly and actually pull them out of our list.1020llvm::erase_if(DeadTargets, [&](Node *TargetN) {1021SCC &TargetC = *G.lookupSCC(*TargetN);1022RefSCC &TargetRC = TargetC.getOuterRefSCC();10231024// We can't trivially remove internal targets, so skip1025// those.1026if (&TargetRC == RC)1027return false;10281029LLVM_DEBUG(dbgs() << "Deleting outgoing edge from '" << N << "' to '"1030<< *TargetN << "'\n");1031RC->removeOutgoingEdge(N, *TargetN);1032return true;1033});10341035// Next demote all the call edges that are now ref edges. This helps make1036// the SCCs small which should minimize the work below as we don't want to1037// form cycles that this would break.1038for (Node *RefTarget : DemotedCallTargets) {1039SCC &TargetC = *G.lookupSCC(*RefTarget);1040RefSCC &TargetRC = TargetC.getOuterRefSCC();10411042// The easy case is when the target RefSCC is not this RefSCC. This is1043// only supported when the target RefSCC is a child of this RefSCC.1044if (&TargetRC != RC) {1045#ifdef EXPENSIVE_CHECKS1046assert(RC->isAncestorOf(TargetRC) &&1047"Cannot potentially form RefSCC cycles here!");1048#endif1049RC->switchOutgoingEdgeToRef(N, *RefTarget);1050LLVM_DEBUG(dbgs() << "Switch outgoing call edge to a ref edge from '" << N1051<< "' to '" << *RefTarget << "'\n");1052continue;1053}10541055// We are switching an internal call edge to a ref edge. This may split up1056// some SCCs.1057if (C != &TargetC) {1058// For separate SCCs this is trivial.1059RC->switchTrivialInternalEdgeToRef(N, *RefTarget);1060continue;1061}10621063// Now update the call graph.1064C = incorporateNewSCCRange(RC->switchInternalEdgeToRef(N, *RefTarget), G, N,1065C, AM, UR);1066}10671068// We added a ref edge earlier for new call edges, promote those to call edges1069// alongside PromotedRefTargets.1070for (Node *E : NewCallEdges)1071PromotedRefTargets.insert(E);10721073// Now promote ref edges into call edges.1074for (Node *CallTarget : PromotedRefTargets) {1075SCC &TargetC = *G.lookupSCC(*CallTarget);1076RefSCC &TargetRC = TargetC.getOuterRefSCC();10771078// The easy case is when the target RefSCC is not this RefSCC. This is1079// only supported when the target RefSCC is a child of this RefSCC.1080if (&TargetRC != RC) {1081#ifdef EXPENSIVE_CHECKS1082assert(RC->isAncestorOf(TargetRC) &&1083"Cannot potentially form RefSCC cycles here!");1084#endif1085RC->switchOutgoingEdgeToCall(N, *CallTarget);1086LLVM_DEBUG(dbgs() << "Switch outgoing ref edge to a call edge from '" << N1087<< "' to '" << *CallTarget << "'\n");1088continue;1089}1090LLVM_DEBUG(dbgs() << "Switch an internal ref edge to a call edge from '"1091<< N << "' to '" << *CallTarget << "'\n");10921093// Otherwise we are switching an internal ref edge to a call edge. This1094// may merge away some SCCs, and we add those to the UpdateResult. We also1095// need to make sure to update the worklist in the event SCCs have moved1096// before the current one in the post-order sequence1097bool HasFunctionAnalysisProxy = false;1098auto InitialSCCIndex = RC->find(*C) - RC->begin();1099bool FormedCycle = RC->switchInternalEdgeToCall(1100N, *CallTarget, [&](ArrayRef<SCC *> MergedSCCs) {1101for (SCC *MergedC : MergedSCCs) {1102assert(MergedC != &TargetC && "Cannot merge away the target SCC!");11031104HasFunctionAnalysisProxy |=1105AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(1106*MergedC) != nullptr;11071108// Mark that this SCC will no longer be valid.1109UR.InvalidatedSCCs.insert(MergedC);11101111// FIXME: We should really do a 'clear' here to forcibly release1112// memory, but we don't have a good way of doing that and1113// preserving the function analyses.1114auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();1115PA.preserve<FunctionAnalysisManagerCGSCCProxy>();1116AM.invalidate(*MergedC, PA);1117}1118});11191120// If we formed a cycle by creating this call, we need to update more data1121// structures.1122if (FormedCycle) {1123C = &TargetC;1124assert(G.lookupSCC(N) == C && "Failed to update current SCC!");11251126// If one of the invalidated SCCs had a cached proxy to a function1127// analysis manager, we need to create a proxy in the new current SCC as1128// the invalidated SCCs had their functions moved.1129if (HasFunctionAnalysisProxy)1130AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G).updateFAM(FAM);11311132// Any analyses cached for this SCC are no longer precise as the shape1133// has changed by introducing this cycle. However, we have taken care to1134// update the proxies so it remains valide.1135auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();1136PA.preserve<FunctionAnalysisManagerCGSCCProxy>();1137AM.invalidate(*C, PA);1138}1139auto NewSCCIndex = RC->find(*C) - RC->begin();1140// If we have actually moved an SCC to be topologically "below" the current1141// one due to merging, we will need to revisit the current SCC after1142// visiting those moved SCCs.1143//1144// It is critical that we *do not* revisit the current SCC unless we1145// actually move SCCs in the process of merging because otherwise we may1146// form a cycle where an SCC is split apart, merged, split, merged and so1147// on infinitely.1148if (InitialSCCIndex < NewSCCIndex) {1149// Put our current SCC back onto the worklist as we'll visit other SCCs1150// that are now definitively ordered prior to the current one in the1151// post-order sequence, and may end up observing more precise context to1152// optimize the current SCC.1153UR.CWorklist.insert(C);1154LLVM_DEBUG(dbgs() << "Enqueuing the existing SCC in the worklist: " << *C1155<< "\n");1156// Enqueue in reverse order as we pop off the back of the worklist.1157for (SCC &MovedC : llvm::reverse(make_range(RC->begin() + InitialSCCIndex,1158RC->begin() + NewSCCIndex))) {1159UR.CWorklist.insert(&MovedC);1160LLVM_DEBUG(dbgs() << "Enqueuing a newly earlier in post-order SCC: "1161<< MovedC << "\n");1162}1163}1164}11651166assert(!UR.InvalidatedSCCs.count(C) && "Invalidated the current SCC!");1167assert(&C->getOuterRefSCC() == RC && "Current SCC not in current RefSCC!");11681169// Record the current SCC for higher layers of the CGSCC pass manager now that1170// all the updates have been applied.1171if (C != &InitialC)1172UR.UpdatedC = C;11731174return *C;1175}11761177LazyCallGraph::SCC &llvm::updateCGAndAnalysisManagerForFunctionPass(1178LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N,1179CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,1180FunctionAnalysisManager &FAM) {1181return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, FAM,1182/* FunctionPass */ true);1183}1184LazyCallGraph::SCC &llvm::updateCGAndAnalysisManagerForCGSCCPass(1185LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N,1186CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,1187FunctionAnalysisManager &FAM) {1188return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, FAM,1189/* FunctionPass */ false);1190}119111921193