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... ExtraArgs) {
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(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(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