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