Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:09

0001 //===- PassManagerImpl.h - Pass management infrastructure -------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 /// \file
0009 /// Provides implementations for PassManager and AnalysisManager template
0010 /// methods. These classes should be explicitly instantiated for any IR unit,
0011 /// and files doing the explicit instantiation should include this header.
0012 ///
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_IR_PASSMANAGERIMPL_H
0016 #define LLVM_IR_PASSMANAGERIMPL_H
0017 
0018 #include "llvm/IR/Function.h"
0019 #include "llvm/IR/PassInstrumentation.h"
0020 #include "llvm/IR/PassManager.h"
0021 #include "llvm/Support/CommandLine.h"
0022 #include "llvm/Support/PrettyStackTrace.h"
0023 
0024 extern llvm::cl::opt<bool> UseNewDbgInfoFormat;
0025 
0026 namespace llvm {
0027 
0028 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
0029 PreservedAnalyses PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>::run(
0030     IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
0031   class StackTraceEntry : public PrettyStackTraceEntry {
0032     const PassInstrumentation &PI;
0033     IRUnitT &IR;
0034     PassConceptT *Pass = nullptr;
0035 
0036   public:
0037     explicit StackTraceEntry(const PassInstrumentation &PI, IRUnitT &IR)
0038         : PI(PI), IR(IR) {}
0039 
0040     void setPass(PassConceptT *P) { Pass = P; }
0041 
0042     void print(raw_ostream &OS) const override {
0043       OS << "Running pass \"";
0044       if (Pass)
0045         Pass->printPipeline(OS, [this](StringRef ClassName) {
0046           auto PassName = PI.getPassNameForClassName(ClassName);
0047           return PassName.empty() ? ClassName : PassName;
0048         });
0049       else
0050         OS << "unknown";
0051       OS << "\" on ";
0052       printIRUnitNameForStackTrace(OS, IR);
0053       OS << "\n";
0054     }
0055   };
0056 
0057   PreservedAnalyses PA = PreservedAnalyses::all();
0058 
0059   // Request PassInstrumentation from analysis manager, will use it to run
0060   // instrumenting callbacks for the passes later.
0061   // Here we use std::tuple wrapper over getResult which helps to extract
0062   // AnalysisManager's arguments out of the whole ExtraArgs set.
0063   PassInstrumentation PI =
0064       detail::getAnalysisResult<PassInstrumentationAnalysis>(
0065           AM, IR, std::tuple<ExtraArgTs...>(ExtraArgs...));
0066 
0067   // RemoveDIs: if requested, convert debug-info to DbgRecord representation
0068   // for duration of these passes.
0069   ScopedDbgInfoFormatSetter FormatSetter(IR, UseNewDbgInfoFormat);
0070 
0071   StackTraceEntry Entry(PI, IR);
0072   for (auto &Pass : Passes) {
0073     Entry.setPass(&*Pass);
0074 
0075     // Check the PassInstrumentation's BeforePass callbacks before running the
0076     // pass, skip its execution completely if asked to (callback returns
0077     // false).
0078     if (!PI.runBeforePass<IRUnitT>(*Pass, IR))
0079       continue;
0080 
0081     PreservedAnalyses PassPA = Pass->run(IR, AM, ExtraArgs...);
0082 
0083     // Update the analysis manager as each pass runs and potentially
0084     // invalidates analyses.
0085     AM.invalidate(IR, PassPA);
0086 
0087     // Call onto PassInstrumentation's AfterPass callbacks immediately after
0088     // running the pass.
0089     PI.runAfterPass<IRUnitT>(*Pass, IR, PassPA);
0090 
0091     // Finally, intersect the preserved analyses to compute the aggregate
0092     // preserved set for this pass manager.
0093     PA.intersect(std::move(PassPA));
0094   }
0095 
0096   // Invalidation was handled after each pass in the above loop for the
0097   // current unit of IR. Therefore, the remaining analysis results in the
0098   // AnalysisManager are preserved. We mark this with a set so that we don't
0099   // need to inspect each one individually.
0100   PA.preserveSet<AllAnalysesOn<IRUnitT>>();
0101 
0102   return PA;
0103 }
0104 
0105 template <typename IRUnitT, typename... ExtraArgTs>
0106 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager() = default;
0107 
0108 template <typename IRUnitT, typename... ExtraArgTs>
0109 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager(
0110     AnalysisManager &&) = default;
0111 
0112 template <typename IRUnitT, typename... ExtraArgTs>
0113 inline AnalysisManager<IRUnitT, ExtraArgTs...> &
0114 AnalysisManager<IRUnitT, ExtraArgTs...>::operator=(AnalysisManager &&) =
0115     default;
0116 
0117 template <typename IRUnitT, typename... ExtraArgTs>
0118 inline void
0119 AnalysisManager<IRUnitT, ExtraArgTs...>::clear(IRUnitT &IR,
0120                                                llvm::StringRef Name) {
0121   if (auto *PI = getCachedResult<PassInstrumentationAnalysis>(IR))
0122     PI->runAnalysesCleared(Name);
0123 
0124   auto ResultsListI = AnalysisResultLists.find(&IR);
0125   if (ResultsListI == AnalysisResultLists.end())
0126     return;
0127   // Delete the map entries that point into the results list.
0128   for (auto &IDAndResult : ResultsListI->second)
0129     AnalysisResults.erase({IDAndResult.first, &IR});
0130 
0131   // And actually destroy and erase the results associated with this IR.
0132   AnalysisResultLists.erase(ResultsListI);
0133 }
0134 
0135 template <typename IRUnitT, typename... ExtraArgTs>
0136 inline typename AnalysisManager<IRUnitT, ExtraArgTs...>::ResultConceptT &
0137 AnalysisManager<IRUnitT, ExtraArgTs...>::getResultImpl(
0138     AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) {
0139   typename AnalysisResultMapT::iterator RI;
0140   bool Inserted;
0141   std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair(
0142       std::make_pair(ID, &IR), typename AnalysisResultListT::iterator()));
0143 
0144   // If we don't have a cached result for this function, look up the pass and
0145   // run it to produce a result, which we then add to the cache.
0146   if (Inserted) {
0147     auto &P = this->lookUpPass(ID);
0148 
0149     PassInstrumentation PI;
0150     if (ID != PassInstrumentationAnalysis::ID()) {
0151       PI = getResult<PassInstrumentationAnalysis>(IR, ExtraArgs...);
0152       PI.runBeforeAnalysis(P, IR);
0153     }
0154 
0155     AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
0156     ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...));
0157 
0158     PI.runAfterAnalysis(P, IR);
0159 
0160     // P.run may have inserted elements into AnalysisResults and invalidated
0161     // RI.
0162     RI = AnalysisResults.find({ID, &IR});
0163     assert(RI != AnalysisResults.end() && "we just inserted it!");
0164 
0165     RI->second = std::prev(ResultList.end());
0166   }
0167 
0168   return *RI->second->second;
0169 }
0170 
0171 template <typename IRUnitT, typename... ExtraArgTs>
0172 inline void AnalysisManager<IRUnitT, ExtraArgTs...>::invalidate(
0173     IRUnitT &IR, const PreservedAnalyses &PA) {
0174   // We're done if all analyses on this IR unit are preserved.
0175   if (PA.allAnalysesInSetPreserved<AllAnalysesOn<IRUnitT>>())
0176     return;
0177 
0178   // Track whether each analysis's result is invalidated in
0179   // IsResultInvalidated.
0180   SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
0181   Invalidator Inv(IsResultInvalidated, AnalysisResults);
0182   AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];
0183   for (auto &AnalysisResultPair : ResultsList) {
0184     // This is basically the same thing as Invalidator::invalidate, but we
0185     // can't call it here because we're operating on the type-erased result.
0186     // Moreover if we instead called invalidate() directly, it would do an
0187     // unnecessary look up in ResultsList.
0188     AnalysisKey *ID = AnalysisResultPair.first;
0189     auto &Result = *AnalysisResultPair.second;
0190 
0191     auto IMapI = IsResultInvalidated.find(ID);
0192     if (IMapI != IsResultInvalidated.end())
0193       // This result was already handled via the Invalidator.
0194       continue;
0195 
0196     // Try to invalidate the result, giving it the Invalidator so it can
0197     // recursively query for any dependencies it has and record the result.
0198     // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as
0199     // Result.invalidate may insert things into the map, invalidating our
0200     // iterator.
0201     bool Inserted =
0202         IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}).second;
0203     (void)Inserted;
0204     assert(Inserted && "Should never have already inserted this ID, likely "
0205                        "indicates a cycle!");
0206   }
0207 
0208   // Now erase the results that were marked above as invalidated.
0209   if (!IsResultInvalidated.empty()) {
0210     for (auto I = ResultsList.begin(), E = ResultsList.end(); I != E;) {
0211       AnalysisKey *ID = I->first;
0212       if (!IsResultInvalidated.lookup(ID)) {
0213         ++I;
0214         continue;
0215       }
0216 
0217       if (auto *PI = getCachedResult<PassInstrumentationAnalysis>(IR))
0218         PI->runAnalysisInvalidated(this->lookUpPass(ID), IR);
0219 
0220       I = ResultsList.erase(I);
0221       AnalysisResults.erase({ID, &IR});
0222     }
0223   }
0224 
0225   if (ResultsList.empty())
0226     AnalysisResultLists.erase(&IR);
0227 }
0228 } // end namespace llvm
0229 
0230 #endif // LLVM_IR_PASSMANAGERIMPL_H