PassManagerImpl.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- PassManagerImpl.h - Pass management infrastructure -------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// Provides implementations for PassManager and AnalysisManager template
  15. /// methods. These classes should be explicitly instantiated for any IR unit,
  16. /// and files doing the explicit instantiation should include this header.
  17. ///
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_IR_PASSMANAGERIMPL_H
  20. #define LLVM_IR_PASSMANAGERIMPL_H
  21. #include "llvm/IR/PassManager.h"
  22. namespace llvm {
  23. template <typename IRUnitT, typename... ExtraArgTs>
  24. inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager(
  25. bool DebugLogging)
  26. : DebugLogging(DebugLogging) {}
  27. template <typename IRUnitT, typename... ExtraArgTs>
  28. inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager(
  29. AnalysisManager &&) = default;
  30. template <typename IRUnitT, typename... ExtraArgTs>
  31. inline AnalysisManager<IRUnitT, ExtraArgTs...> &
  32. AnalysisManager<IRUnitT, ExtraArgTs...>::operator=(AnalysisManager &&) =
  33. default;
  34. template <typename IRUnitT, typename... ExtraArgTs>
  35. inline void
  36. AnalysisManager<IRUnitT, ExtraArgTs...>::clear(IRUnitT &IR,
  37. llvm::StringRef Name) {
  38. if (DebugLogging)
  39. dbgs() << "Clearing all analysis results for: " << Name << "\n";
  40. auto ResultsListI = AnalysisResultLists.find(&IR);
  41. if (ResultsListI == AnalysisResultLists.end())
  42. return;
  43. // Delete the map entries that point into the results list.
  44. for (auto &IDAndResult : ResultsListI->second)
  45. AnalysisResults.erase({IDAndResult.first, &IR});
  46. // And actually destroy and erase the results associated with this IR.
  47. AnalysisResultLists.erase(ResultsListI);
  48. }
  49. template <typename IRUnitT, typename... ExtraArgTs>
  50. inline typename AnalysisManager<IRUnitT, ExtraArgTs...>::ResultConceptT &
  51. AnalysisManager<IRUnitT, ExtraArgTs...>::getResultImpl(
  52. AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) {
  53. typename AnalysisResultMapT::iterator RI;
  54. bool Inserted;
  55. std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair(
  56. std::make_pair(ID, &IR), typename AnalysisResultListT::iterator()));
  57. // If we don't have a cached result for this function, look up the pass and
  58. // run it to produce a result, which we then add to the cache.
  59. if (Inserted) {
  60. auto &P = this->lookUpPass(ID);
  61. PassInstrumentation PI;
  62. if (ID != PassInstrumentationAnalysis::ID()) {
  63. PI = getResult<PassInstrumentationAnalysis>(IR, ExtraArgs...);
  64. PI.runBeforeAnalysis(P, IR);
  65. }
  66. AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
  67. ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...));
  68. PI.runAfterAnalysis(P, IR);
  69. // P.run may have inserted elements into AnalysisResults and invalidated
  70. // RI.
  71. RI = AnalysisResults.find({ID, &IR});
  72. assert(RI != AnalysisResults.end() && "we just inserted it!");
  73. RI->second = std::prev(ResultList.end());
  74. }
  75. return *RI->second->second;
  76. }
  77. template <typename IRUnitT, typename... ExtraArgTs>
  78. inline void AnalysisManager<IRUnitT, ExtraArgTs...>::invalidate(
  79. IRUnitT &IR, const PreservedAnalyses &PA) {
  80. // We're done if all analyses on this IR unit are preserved.
  81. if (PA.allAnalysesInSetPreserved<AllAnalysesOn<IRUnitT>>())
  82. return;
  83. // Track whether each analysis's result is invalidated in
  84. // IsResultInvalidated.
  85. SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
  86. Invalidator Inv(IsResultInvalidated, AnalysisResults);
  87. AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];
  88. for (auto &AnalysisResultPair : ResultsList) {
  89. // This is basically the same thing as Invalidator::invalidate, but we
  90. // can't call it here because we're operating on the type-erased result.
  91. // Moreover if we instead called invalidate() directly, it would do an
  92. // unnecessary look up in ResultsList.
  93. AnalysisKey *ID = AnalysisResultPair.first;
  94. auto &Result = *AnalysisResultPair.second;
  95. auto IMapI = IsResultInvalidated.find(ID);
  96. if (IMapI != IsResultInvalidated.end())
  97. // This result was already handled via the Invalidator.
  98. continue;
  99. // Try to invalidate the result, giving it the Invalidator so it can
  100. // recursively query for any dependencies it has and record the result.
  101. // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as
  102. // Result.invalidate may insert things into the map, invalidating our
  103. // iterator.
  104. bool Inserted =
  105. IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}).second;
  106. (void)Inserted;
  107. assert(Inserted && "Should never have already inserted this ID, likely "
  108. "indicates a cycle!");
  109. }
  110. // Now erase the results that were marked above as invalidated.
  111. if (!IsResultInvalidated.empty()) {
  112. for (auto I = ResultsList.begin(), E = ResultsList.end(); I != E;) {
  113. AnalysisKey *ID = I->first;
  114. if (!IsResultInvalidated.lookup(ID)) {
  115. ++I;
  116. continue;
  117. }
  118. if (DebugLogging)
  119. dbgs() << "Invalidating analysis: " << this->lookUpPass(ID).name()
  120. << " on " << IR.getName() << "\n";
  121. I = ResultsList.erase(I);
  122. AnalysisResults.erase({ID, &IR});
  123. }
  124. }
  125. if (ResultsList.empty())
  126. AnalysisResultLists.erase(&IR);
  127. }
  128. } // end namespace llvm
  129. #endif // LLVM_IR_PASSMANAGERIMPL_H
  130. #ifdef __GNUC__
  131. #pragma GCC diagnostic pop
  132. #endif