1//===- PassManager.cpp - Infrastructure for managing & running IR passes --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/IR/PassManager.h"
10#include "llvm/ADT/DenseMapInfo.h"
11#include "llvm/IR/PassManagerImpl.h"
12#include <optional>
13
14using namespace llvm;
15
16namespace llvm {
17// Explicit template instantiations and specialization defininitions for core
18// template typedefs.
19template class AllAnalysesOn<Module>;
20template class AllAnalysesOn<Function>;
21template class PassManager<Module>;
22template class PassManager<Function>;
23template class AnalysisManager<Module>;
24template class AnalysisManager<Function>;
25template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>;
26template class OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>;
27
28template <>
29bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
30    Module &M, const PreservedAnalyses &PA,
31    ModuleAnalysisManager::Invalidator &Inv) {
32  // If literally everything is preserved, we're done.
33  if (PA.areAllPreserved())
34    return false; // This is still a valid proxy.
35
36  // If this proxy isn't marked as preserved, then even if the result remains
37  // valid, the key itself may no longer be valid, so we clear everything.
38  //
39  // Note that in order to preserve this proxy, a module pass must ensure that
40  // the FAM has been completely updated to handle the deletion of functions.
41  // Specifically, any FAM-cached results for those functions need to have been
42  // forcibly cleared. When preserved, this proxy will only invalidate results
43  // cached on functions *still in the module* at the end of the module pass.
44  auto PAC = PA.getChecker<FunctionAnalysisManagerModuleProxy>();
45  if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {
46    InnerAM->clear();
47    return true;
48  }
49
50  // Directly check if the relevant set is preserved.
51  bool AreFunctionAnalysesPreserved =
52      PA.allAnalysesInSetPreserved<AllAnalysesOn<Function>>();
53
54  // Now walk all the functions to see if any inner analysis invalidation is
55  // necessary.
56  for (Function &F : M) {
57    std::optional<PreservedAnalyses> FunctionPA;
58
59    // Check to see whether the preserved set needs to be pruned based on
60    // module-level analysis invalidation that triggers deferred invalidation
61    // registered with the outer analysis manager proxy for this function.
62    if (auto *OuterProxy =
63            InnerAM->getCachedResult<ModuleAnalysisManagerFunctionProxy>(F))
64      for (const auto &OuterInvalidationPair :
65           OuterProxy->getOuterInvalidations()) {
66        AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;
67        const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
68        if (Inv.invalidate(OuterAnalysisID, M, PA)) {
69          if (!FunctionPA)
70            FunctionPA = PA;
71          for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
72            FunctionPA->abandon(InnerAnalysisID);
73        }
74      }
75
76    // Check if we needed a custom PA set, and if so we'll need to run the
77    // inner invalidation.
78    if (FunctionPA) {
79      InnerAM->invalidate(F, *FunctionPA);
80      continue;
81    }
82
83    // Otherwise we only need to do invalidation if the original PA set didn't
84    // preserve all function analyses.
85    if (!AreFunctionAnalysesPreserved)
86      InnerAM->invalidate(F, PA);
87  }
88
89  // Return false to indicate that this result is still a valid proxy.
90  return false;
91}
92} // namespace llvm
93
94void ModuleToFunctionPassAdaptor::printPipeline(
95    raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
96  OS << "function";
97  if (EagerlyInvalidate)
98    OS << "<eager-inv>";
99  OS << "(";
100  Pass->printPipeline(OS, MapClassName2PassName);
101  OS << ")";
102}
103
104PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M,
105                                                   ModuleAnalysisManager &AM) {
106  FunctionAnalysisManager &FAM =
107      AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
108
109  // Request PassInstrumentation from analysis manager, will use it to run
110  // instrumenting callbacks for the passes later.
111  PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(M);
112
113  PreservedAnalyses PA = PreservedAnalyses::all();
114  for (Function &F : M) {
115    if (F.isDeclaration())
116      continue;
117
118    // Check the PassInstrumentation's BeforePass callbacks before running the
119    // pass, skip its execution completely if asked to (callback returns
120    // false).
121    if (!PI.runBeforePass<Function>(*Pass, F))
122      continue;
123
124    PreservedAnalyses PassPA = Pass->run(F, FAM);
125    PI.runAfterPass(*Pass, F, PassPA);
126
127    // We know that the function pass couldn't have invalidated any other
128    // function's analyses (that's the contract of a function pass), so
129    // directly handle the function analysis manager's invalidation here.
130    FAM.invalidate(F, EagerlyInvalidate ? PreservedAnalyses::none() : PassPA);
131
132    // Then intersect the preserved set so that invalidation of module
133    // analyses will eventually occur when the module pass completes.
134    PA.intersect(std::move(PassPA));
135  }
136
137  // The FunctionAnalysisManagerModuleProxy is preserved because (we assume)
138  // the function passes we ran didn't add or remove any functions.
139  //
140  // We also preserve all analyses on Functions, because we did all the
141  // invalidation we needed to do above.
142  PA.preserveSet<AllAnalysesOn<Function>>();
143  PA.preserve<FunctionAnalysisManagerModuleProxy>();
144  return PA;
145}
146
147AnalysisSetKey CFGAnalyses::SetKey;
148
149AnalysisSetKey PreservedAnalyses::AllAnalysesKey;
150