xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/IR/PassManagerImpl.h (revision 6b986646d434baa21ae3d74d6a662ad206c7ddbd)
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 ///
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/PassManager.h"
19 
20 namespace llvm {
21 
22 template <typename IRUnitT, typename... ExtraArgTs>
23 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager(
24     bool DebugLogging)
25     : DebugLogging(DebugLogging) {}
26 
27 template <typename IRUnitT, typename... ExtraArgTs>
28 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager(
29     AnalysisManager &&) = default;
30 
31 template <typename IRUnitT, typename... ExtraArgTs>
32 inline AnalysisManager<IRUnitT, ExtraArgTs...> &
33 AnalysisManager<IRUnitT, ExtraArgTs...>::operator=(AnalysisManager &&) =
34     default;
35 
36 template <typename IRUnitT, typename... ExtraArgTs>
37 inline void
38 AnalysisManager<IRUnitT, ExtraArgTs...>::clear(IRUnitT &IR,
39                                                llvm::StringRef Name) {
40   if (DebugLogging)
41     dbgs() << "Clearing all analysis results for: " << Name << "\n";
42 
43   auto ResultsListI = AnalysisResultLists.find(&IR);
44   if (ResultsListI == AnalysisResultLists.end())
45     return;
46   // Delete the map entries that point into the results list.
47   for (auto &IDAndResult : ResultsListI->second)
48     AnalysisResults.erase({IDAndResult.first, &IR});
49 
50   // And actually destroy and erase the results associated with this IR.
51   AnalysisResultLists.erase(ResultsListI);
52 }
53 
54 template <typename IRUnitT, typename... ExtraArgTs>
55 inline typename AnalysisManager<IRUnitT, ExtraArgTs...>::ResultConceptT &
56 AnalysisManager<IRUnitT, ExtraArgTs...>::getResultImpl(
57     AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) {
58   typename AnalysisResultMapT::iterator RI;
59   bool Inserted;
60   std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair(
61       std::make_pair(ID, &IR), typename AnalysisResultListT::iterator()));
62 
63   // If we don't have a cached result for this function, look up the pass and
64   // run it to produce a result, which we then add to the cache.
65   if (Inserted) {
66     auto &P = this->lookUpPass(ID);
67     if (DebugLogging)
68       dbgs() << "Running analysis: " << P.name() << " on " << IR.getName()
69              << "\n";
70 
71     PassInstrumentation PI;
72     if (ID != PassInstrumentationAnalysis::ID()) {
73       PI = getResult<PassInstrumentationAnalysis>(IR, ExtraArgs...);
74       PI.runBeforeAnalysis(P, IR);
75     }
76 
77     AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
78     ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...));
79 
80     PI.runAfterAnalysis(P, IR);
81 
82     // P.run may have inserted elements into AnalysisResults and invalidated
83     // RI.
84     RI = AnalysisResults.find({ID, &IR});
85     assert(RI != AnalysisResults.end() && "we just inserted it!");
86 
87     RI->second = std::prev(ResultList.end());
88   }
89 
90   return *RI->second->second;
91 }
92 
93 template <typename IRUnitT, typename... ExtraArgTs>
94 inline void AnalysisManager<IRUnitT, ExtraArgTs...>::invalidate(
95     IRUnitT &IR, const PreservedAnalyses &PA) {
96   // We're done if all analyses on this IR unit are preserved.
97   if (PA.allAnalysesInSetPreserved<AllAnalysesOn<IRUnitT>>())
98     return;
99 
100   if (DebugLogging)
101     dbgs() << "Invalidating all non-preserved analyses for: " << IR.getName()
102            << "\n";
103 
104   // Track whether each analysis's result is invalidated in
105   // IsResultInvalidated.
106   SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
107   Invalidator Inv(IsResultInvalidated, AnalysisResults);
108   AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];
109   for (auto &AnalysisResultPair : ResultsList) {
110     // This is basically the same thing as Invalidator::invalidate, but we
111     // can't call it here because we're operating on the type-erased result.
112     // Moreover if we instead called invalidate() directly, it would do an
113     // unnecessary look up in ResultsList.
114     AnalysisKey *ID = AnalysisResultPair.first;
115     auto &Result = *AnalysisResultPair.second;
116 
117     auto IMapI = IsResultInvalidated.find(ID);
118     if (IMapI != IsResultInvalidated.end())
119       // This result was already handled via the Invalidator.
120       continue;
121 
122     // Try to invalidate the result, giving it the Invalidator so it can
123     // recursively query for any dependencies it has and record the result.
124     // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as
125     // Result.invalidate may insert things into the map, invalidating our
126     // iterator.
127     bool Inserted =
128         IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}).second;
129     (void)Inserted;
130     assert(Inserted && "Should never have already inserted this ID, likely "
131                        "indicates a cycle!");
132   }
133 
134   // Now erase the results that were marked above as invalidated.
135   if (!IsResultInvalidated.empty()) {
136     for (auto I = ResultsList.begin(), E = ResultsList.end(); I != E;) {
137       AnalysisKey *ID = I->first;
138       if (!IsResultInvalidated.lookup(ID)) {
139         ++I;
140         continue;
141       }
142 
143       if (DebugLogging)
144         dbgs() << "Invalidating analysis: " << this->lookUpPass(ID).name()
145                << " on " << IR.getName() << "\n";
146 
147       I = ResultsList.erase(I);
148       AnalysisResults.erase({ID, &IR});
149     }
150   }
151 
152   if (ResultsList.empty())
153     AnalysisResultLists.erase(&IR);
154 }
155 } // end namespace llvm
156 
157 #endif // LLVM_IR_PASSMANAGERIMPL_H
158