xref: /freebsd/contrib/llvm-project/llvm/include/llvm/IR/PassManagerImpl.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- PassManagerImpl.h - Pass management infrastructure -------*- C++ -*-===//
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 /// \file
9 /// Provides implementations for PassManager and AnalysisManager template
10 /// methods. These classes should be explicitly instantiated for any IR unit,
11 /// and files doing the explicit instantiation should include this header.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_IR_PASSMANAGERIMPL_H
16 #define LLVM_IR_PASSMANAGERIMPL_H
17 
18 #include "llvm/IR/Function.h"
19 #include "llvm/IR/PassInstrumentation.h"
20 #include "llvm/IR/PassManager.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/PrettyStackTrace.h"
23 
24 extern llvm::cl::opt<bool> UseNewDbgInfoFormat;
25 
26 namespace llvm {
27 
28 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
run(IRUnitT & IR,AnalysisManagerT & AM,ExtraArgTs...ExtraArgs)29 PreservedAnalyses PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>::run(
30     IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
31   class StackTraceEntry : public PrettyStackTraceEntry {
32     const PassInstrumentation &PI;
33     IRUnitT &IR;
34     PassConceptT *Pass = nullptr;
35 
36   public:
37     explicit StackTraceEntry(const PassInstrumentation &PI, IRUnitT &IR)
38         : PI(PI), IR(IR) {}
39 
40     void setPass(PassConceptT *P) { Pass = P; }
41 
42     void print(raw_ostream &OS) const override {
43       OS << "Running pass \"";
44       if (Pass)
45         Pass->printPipeline(OS, [this](StringRef ClassName) {
46           auto PassName = PI.getPassNameForClassName(ClassName);
47           return PassName.empty() ? ClassName : PassName;
48         });
49       else
50         OS << "unknown";
51       OS << "\" on ";
52       printIRUnitNameForStackTrace(OS, IR);
53       OS << "\n";
54     }
55   };
56 
57   PreservedAnalyses PA = PreservedAnalyses::all();
58 
59   // Request PassInstrumentation from analysis manager, will use it to run
60   // instrumenting callbacks for the passes later.
61   // Here we use std::tuple wrapper over getResult which helps to extract
62   // AnalysisManager's arguments out of the whole ExtraArgs set.
63   PassInstrumentation PI =
64       detail::getAnalysisResult<PassInstrumentationAnalysis>(
65           AM, IR, std::tuple<ExtraArgTs...>(ExtraArgs...));
66 
67   // RemoveDIs: if requested, convert debug-info to DbgRecord representation
68   // for duration of these passes.
69   ScopedDbgInfoFormatSetter FormatSetter(IR, UseNewDbgInfoFormat);
70 
71   StackTraceEntry Entry(PI, IR);
72   for (auto &Pass : Passes) {
73     Entry.setPass(&*Pass);
74 
75     // Check the PassInstrumentation's BeforePass callbacks before running the
76     // pass, skip its execution completely if asked to (callback returns
77     // false).
78     if (!PI.runBeforePass<IRUnitT>(*Pass, IR))
79       continue;
80 
81     PreservedAnalyses PassPA = Pass->run(IR, AM, ExtraArgs...);
82 
83     // Update the analysis manager as each pass runs and potentially
84     // invalidates analyses.
85     AM.invalidate(IR, PassPA);
86 
87     // Call onto PassInstrumentation's AfterPass callbacks immediately after
88     // running the pass.
89     PI.runAfterPass<IRUnitT>(*Pass, IR, PassPA);
90 
91     // Finally, intersect the preserved analyses to compute the aggregate
92     // preserved set for this pass manager.
93     PA.intersect(std::move(PassPA));
94   }
95 
96   // Invalidation was handled after each pass in the above loop for the
97   // current unit of IR. Therefore, the remaining analysis results in the
98   // AnalysisManager are preserved. We mark this with a set so that we don't
99   // need to inspect each one individually.
100   PA.preserveSet<AllAnalysesOn<IRUnitT>>();
101 
102   return PA;
103 }
104 
105 template <typename IRUnitT, typename... ExtraArgTs>
106 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager() = default;
107 
108 template <typename IRUnitT, typename... ExtraArgTs>
109 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager(
110     AnalysisManager &&) = default;
111 
112 template <typename IRUnitT, typename... ExtraArgTs>
113 inline AnalysisManager<IRUnitT, ExtraArgTs...> &
114 AnalysisManager<IRUnitT, ExtraArgTs...>::operator=(AnalysisManager &&) =
115     default;
116 
117 template <typename IRUnitT, typename... ExtraArgTs>
118 inline void
clear(IRUnitT & IR,llvm::StringRef Name)119 AnalysisManager<IRUnitT, ExtraArgTs...>::clear(IRUnitT &IR,
120                                                llvm::StringRef Name) {
121   if (auto *PI = getCachedResult<PassInstrumentationAnalysis>(IR))
122     PI->runAnalysesCleared(Name);
123 
124   auto ResultsListI = AnalysisResultLists.find(&IR);
125   if (ResultsListI == AnalysisResultLists.end())
126     return;
127   // Delete the map entries that point into the results list.
128   for (auto &IDAndResult : ResultsListI->second)
129     AnalysisResults.erase({IDAndResult.first, &IR});
130 
131   // And actually destroy and erase the results associated with this IR.
132   AnalysisResultLists.erase(ResultsListI);
133 }
134 
135 template <typename IRUnitT, typename... ExtraArgTs>
136 inline typename AnalysisManager<IRUnitT, ExtraArgTs...>::ResultConceptT &
getResultImpl(AnalysisKey * ID,IRUnitT & IR,ExtraArgTs...ExtraArgs)137 AnalysisManager<IRUnitT, ExtraArgTs...>::getResultImpl(
138     AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) {
139   typename AnalysisResultMapT::iterator RI;
140   bool Inserted;
141   std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair(
142       std::make_pair(ID, &IR), typename AnalysisResultListT::iterator()));
143 
144   // If we don't have a cached result for this function, look up the pass and
145   // run it to produce a result, which we then add to the cache.
146   if (Inserted) {
147     auto &P = this->lookUpPass(ID);
148 
149     PassInstrumentation PI;
150     if (ID != PassInstrumentationAnalysis::ID()) {
151       PI = getResult<PassInstrumentationAnalysis>(IR, ExtraArgs...);
152       PI.runBeforeAnalysis(P, IR);
153     }
154 
155     AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
156     ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...));
157 
158     PI.runAfterAnalysis(P, IR);
159 
160     // P.run may have inserted elements into AnalysisResults and invalidated
161     // RI.
162     RI = AnalysisResults.find({ID, &IR});
163     assert(RI != AnalysisResults.end() && "we just inserted it!");
164 
165     RI->second = std::prev(ResultList.end());
166   }
167 
168   return *RI->second->second;
169 }
170 
171 template <typename IRUnitT, typename... ExtraArgTs>
invalidate(IRUnitT & IR,const PreservedAnalyses & PA)172 inline void AnalysisManager<IRUnitT, ExtraArgTs...>::invalidate(
173     IRUnitT &IR, const PreservedAnalyses &PA) {
174   // We're done if all analyses on this IR unit are preserved.
175   if (PA.allAnalysesInSetPreserved<AllAnalysesOn<IRUnitT>>())
176     return;
177 
178   // Track whether each analysis's result is invalidated in
179   // IsResultInvalidated.
180   SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
181   Invalidator Inv(IsResultInvalidated, AnalysisResults);
182   AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];
183   for (auto &AnalysisResultPair : ResultsList) {
184     // This is basically the same thing as Invalidator::invalidate, but we
185     // can't call it here because we're operating on the type-erased result.
186     // Moreover if we instead called invalidate() directly, it would do an
187     // unnecessary look up in ResultsList.
188     AnalysisKey *ID = AnalysisResultPair.first;
189     auto &Result = *AnalysisResultPair.second;
190 
191     auto IMapI = IsResultInvalidated.find(ID);
192     if (IMapI != IsResultInvalidated.end())
193       // This result was already handled via the Invalidator.
194       continue;
195 
196     // Try to invalidate the result, giving it the Invalidator so it can
197     // recursively query for any dependencies it has and record the result.
198     // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as
199     // Result.invalidate may insert things into the map, invalidating our
200     // iterator.
201     bool Inserted =
202         IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}).second;
203     (void)Inserted;
204     assert(Inserted && "Should never have already inserted this ID, likely "
205                        "indicates a cycle!");
206   }
207 
208   // Now erase the results that were marked above as invalidated.
209   if (!IsResultInvalidated.empty()) {
210     for (auto I = ResultsList.begin(), E = ResultsList.end(); I != E;) {
211       AnalysisKey *ID = I->first;
212       if (!IsResultInvalidated.lookup(ID)) {
213         ++I;
214         continue;
215       }
216 
217       if (auto *PI = getCachedResult<PassInstrumentationAnalysis>(IR))
218         PI->runAnalysisInvalidated(this->lookUpPass(ID), IR);
219 
220       I = ResultsList.erase(I);
221       AnalysisResults.erase({ID, &IR});
222     }
223   }
224 
225   if (ResultsList.empty())
226     AnalysisResultLists.erase(&IR);
227 }
228 } // end namespace llvm
229 
230 #endif // LLVM_IR_PASSMANAGERIMPL_H
231