File indexing completed on 2026-05-10 08:44:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #ifndef LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H
0037 #define LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H
0038
0039 #include "llvm/ADT/PriorityWorklist.h"
0040 #include "llvm/Analysis/LoopAnalysisManager.h"
0041 #include "llvm/Analysis/LoopInfo.h"
0042 #include "llvm/Analysis/LoopNestAnalysis.h"
0043 #include "llvm/IR/PassManager.h"
0044 #include "llvm/IR/PassInstrumentation.h"
0045 #include "llvm/Transforms/Utils/LCSSA.h"
0046 #include "llvm/Transforms/Utils/LoopSimplify.h"
0047 #include "llvm/Transforms/Utils/LoopUtils.h"
0048 #include <memory>
0049
0050 namespace llvm {
0051
0052
0053 class LPMUpdater;
0054 class PassInstrumentation;
0055
0056 namespace {
0057
0058 template <typename PassT>
0059 using HasRunOnLoopT = decltype(std::declval<PassT>().run(
0060 std::declval<Loop &>(), std::declval<LoopAnalysisManager &>(),
0061 std::declval<LoopStandardAnalysisResults &>(),
0062 std::declval<LPMUpdater &>()));
0063
0064 }
0065
0066
0067
0068
0069 template <>
0070 class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
0071 LPMUpdater &>
0072 : public PassInfoMixin<
0073 PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
0074 LPMUpdater &>> {
0075 public:
0076 explicit PassManager() = default;
0077
0078
0079
0080
0081
0082 PassManager(PassManager &&Arg)
0083 : IsLoopNestPass(std::move(Arg.IsLoopNestPass)),
0084 LoopPasses(std::move(Arg.LoopPasses)),
0085 LoopNestPasses(std::move(Arg.LoopNestPasses)) {}
0086
0087 PassManager &operator=(PassManager &&RHS) {
0088 IsLoopNestPass = std::move(RHS.IsLoopNestPass);
0089 LoopPasses = std::move(RHS.LoopPasses);
0090 LoopNestPasses = std::move(RHS.LoopNestPasses);
0091 return *this;
0092 }
0093
0094 PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
0095 LoopStandardAnalysisResults &AR, LPMUpdater &U);
0096
0097 void printPipeline(raw_ostream &OS,
0098 function_ref<StringRef(StringRef)> MapClassName2PassName);
0099
0100
0101
0102
0103
0104
0105 template <typename PassT>
0106 LLVM_ATTRIBUTE_MINSIZE
0107 std::enable_if_t<is_detected<HasRunOnLoopT, PassT>::value>
0108 addPass(PassT &&Pass) {
0109 using LoopPassModelT =
0110 detail::PassModel<Loop, PassT, LoopAnalysisManager,
0111 LoopStandardAnalysisResults &, LPMUpdater &>;
0112 IsLoopNestPass.push_back(false);
0113
0114
0115 LoopPasses.push_back(std::unique_ptr<LoopPassConceptT>(
0116 new LoopPassModelT(std::forward<PassT>(Pass))));
0117 }
0118
0119 template <typename PassT>
0120 LLVM_ATTRIBUTE_MINSIZE
0121 std::enable_if_t<!is_detected<HasRunOnLoopT, PassT>::value>
0122 addPass(PassT &&Pass) {
0123 using LoopNestPassModelT =
0124 detail::PassModel<LoopNest, PassT, LoopAnalysisManager,
0125 LoopStandardAnalysisResults &, LPMUpdater &>;
0126 IsLoopNestPass.push_back(true);
0127
0128
0129 LoopNestPasses.push_back(std::unique_ptr<LoopNestPassConceptT>(
0130 new LoopNestPassModelT(std::forward<PassT>(Pass))));
0131 }
0132
0133 bool isEmpty() const { return LoopPasses.empty() && LoopNestPasses.empty(); }
0134
0135 static bool isRequired() { return true; }
0136
0137 size_t getNumLoopPasses() const { return LoopPasses.size(); }
0138 size_t getNumLoopNestPasses() const { return LoopNestPasses.size(); }
0139
0140 protected:
0141 using LoopPassConceptT =
0142 detail::PassConcept<Loop, LoopAnalysisManager,
0143 LoopStandardAnalysisResults &, LPMUpdater &>;
0144 using LoopNestPassConceptT =
0145 detail::PassConcept<LoopNest, LoopAnalysisManager,
0146 LoopStandardAnalysisResults &, LPMUpdater &>;
0147
0148
0149
0150 BitVector IsLoopNestPass;
0151 std::vector<std::unique_ptr<LoopPassConceptT>> LoopPasses;
0152 std::vector<std::unique_ptr<LoopNestPassConceptT>> LoopNestPasses;
0153
0154
0155
0156
0157 template <typename IRUnitT, typename PassT>
0158 std::optional<PreservedAnalyses>
0159 runSinglePass(IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM,
0160 LoopStandardAnalysisResults &AR, LPMUpdater &U,
0161 PassInstrumentation &PI);
0162
0163 PreservedAnalyses runWithLoopNestPasses(Loop &L, LoopAnalysisManager &AM,
0164 LoopStandardAnalysisResults &AR,
0165 LPMUpdater &U);
0166 PreservedAnalyses runWithoutLoopNestPasses(Loop &L, LoopAnalysisManager &AM,
0167 LoopStandardAnalysisResults &AR,
0168 LPMUpdater &U);
0169
0170 private:
0171 static const Loop &getLoopFromIR(Loop &L) { return L; }
0172 static const Loop &getLoopFromIR(LoopNest &LN) {
0173 return LN.getOutermostLoop();
0174 }
0175 };
0176
0177
0178
0179
0180
0181
0182 typedef PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
0183 LPMUpdater &>
0184 LoopPassManager;
0185
0186
0187
0188
0189 template <typename AnalysisT>
0190 struct RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
0191 LoopStandardAnalysisResults &, LPMUpdater &>
0192 : PassInfoMixin<
0193 RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
0194 LoopStandardAnalysisResults &, LPMUpdater &>> {
0195 PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
0196 LoopStandardAnalysisResults &AR, LPMUpdater &) {
0197 (void)AM.template getResult<AnalysisT>(L, AR);
0198 return PreservedAnalyses::all();
0199 }
0200 void printPipeline(raw_ostream &OS,
0201 function_ref<StringRef(StringRef)> MapClassName2PassName) {
0202 auto ClassName = AnalysisT::name();
0203 auto PassName = MapClassName2PassName(ClassName);
0204 OS << "require<" << PassName << '>';
0205 }
0206 };
0207
0208
0209 template <typename AnalysisT>
0210 using RequireAnalysisLoopPass =
0211 RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
0212 LoopStandardAnalysisResults &, LPMUpdater &>;
0213
0214 class FunctionToLoopPassAdaptor;
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 class LPMUpdater {
0230 public:
0231
0232
0233
0234
0235
0236
0237 bool skipCurrentLoop() const { return SkipCurrentLoop; }
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 void markLoopAsDeleted(Loop &L, llvm::StringRef Name) {
0250 LAM.clear(L, Name);
0251 assert((&L == CurrentL || CurrentL->contains(&L)) &&
0252 "Cannot delete a loop outside of the "
0253 "subloop tree currently being processed.");
0254 if (&L == CurrentL)
0255 SkipCurrentLoop = true;
0256 }
0257
0258 void setParentLoop(Loop *L) {
0259 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0260 ParentL = L;
0261 #endif
0262 }
0263
0264
0265
0266
0267
0268
0269
0270 void addChildLoops(ArrayRef<Loop *> NewChildLoops) {
0271 assert(!LoopNestMode &&
0272 "Child loops should not be pushed in loop-nest mode.");
0273
0274
0275 Worklist.insert(CurrentL);
0276
0277 #ifndef NDEBUG
0278 for (Loop *NewL : NewChildLoops)
0279 assert(NewL->getParentLoop() == CurrentL && "All of the new loops must "
0280 "be immediate children of "
0281 "the current loop!");
0282 #endif
0283
0284 appendLoopsToWorklist(NewChildLoops, Worklist);
0285
0286
0287
0288 SkipCurrentLoop = true;
0289 }
0290
0291
0292
0293
0294
0295
0296
0297 void addSiblingLoops(ArrayRef<Loop *> NewSibLoops) {
0298 #if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
0299 for (Loop *NewL : NewSibLoops)
0300 assert(NewL->getParentLoop() == ParentL &&
0301 "All of the new loops must be siblings of the current loop!");
0302 #endif
0303
0304 if (LoopNestMode)
0305 Worklist.insert(NewSibLoops);
0306 else
0307 appendLoopsToWorklist(NewSibLoops, Worklist);
0308
0309
0310
0311 }
0312
0313
0314
0315
0316
0317
0318 void revisitCurrentLoop() {
0319
0320 SkipCurrentLoop = true;
0321
0322
0323 Worklist.insert(CurrentL);
0324 }
0325
0326 bool isLoopNestChanged() const {
0327 return LoopNestChanged;
0328 }
0329
0330
0331
0332 void markLoopNestChanged(bool Changed) {
0333 LoopNestChanged = Changed;
0334 }
0335
0336 private:
0337 friend class llvm::FunctionToLoopPassAdaptor;
0338
0339
0340 SmallPriorityWorklist<Loop *, 4> &Worklist;
0341
0342
0343 LoopAnalysisManager &LAM;
0344
0345 Loop *CurrentL;
0346 bool SkipCurrentLoop;
0347 const bool LoopNestMode;
0348 bool LoopNestChanged;
0349
0350 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0351
0352
0353 Loop *ParentL;
0354 #endif
0355
0356 LPMUpdater(SmallPriorityWorklist<Loop *, 4> &Worklist,
0357 LoopAnalysisManager &LAM, bool LoopNestMode = false,
0358 bool LoopNestChanged = false)
0359 : Worklist(Worklist), LAM(LAM), LoopNestMode(LoopNestMode),
0360 LoopNestChanged(LoopNestChanged) {}
0361 };
0362
0363 template <typename IRUnitT, typename PassT>
0364 std::optional<PreservedAnalyses> LoopPassManager::runSinglePass(
0365 IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM,
0366 LoopStandardAnalysisResults &AR, LPMUpdater &U, PassInstrumentation &PI) {
0367
0368
0369 const Loop &L = getLoopFromIR(IR);
0370
0371
0372 if (!PI.runBeforePass<Loop>(*Pass, L))
0373 return std::nullopt;
0374
0375 PreservedAnalyses PA = Pass->run(IR, AM, AR, U);
0376
0377
0378 if (U.skipCurrentLoop())
0379 PI.runAfterPassInvalidated<IRUnitT>(*Pass, PA);
0380 else
0381 PI.runAfterPass<Loop>(*Pass, L, PA);
0382 return PA;
0383 }
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401 class FunctionToLoopPassAdaptor
0402 : public PassInfoMixin<FunctionToLoopPassAdaptor> {
0403 public:
0404 using PassConceptT =
0405 detail::PassConcept<Loop, LoopAnalysisManager,
0406 LoopStandardAnalysisResults &, LPMUpdater &>;
0407
0408 explicit FunctionToLoopPassAdaptor(std::unique_ptr<PassConceptT> Pass,
0409 bool UseMemorySSA = false,
0410 bool UseBlockFrequencyInfo = false,
0411 bool UseBranchProbabilityInfo = false,
0412 bool LoopNestMode = false)
0413 : Pass(std::move(Pass)), UseMemorySSA(UseMemorySSA),
0414 UseBlockFrequencyInfo(UseBlockFrequencyInfo),
0415 UseBranchProbabilityInfo(UseBranchProbabilityInfo),
0416 LoopNestMode(LoopNestMode) {
0417 LoopCanonicalizationFPM.addPass(LoopSimplifyPass());
0418 LoopCanonicalizationFPM.addPass(LCSSAPass());
0419 }
0420
0421
0422 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0423 void printPipeline(raw_ostream &OS,
0424 function_ref<StringRef(StringRef)> MapClassName2PassName);
0425
0426 static bool isRequired() { return true; }
0427
0428 bool isLoopNestMode() const { return LoopNestMode; }
0429
0430 private:
0431 std::unique_ptr<PassConceptT> Pass;
0432
0433 FunctionPassManager LoopCanonicalizationFPM;
0434
0435 bool UseMemorySSA = false;
0436 bool UseBlockFrequencyInfo = false;
0437 bool UseBranchProbabilityInfo = false;
0438 const bool LoopNestMode;
0439 };
0440
0441
0442
0443
0444
0445 template <typename LoopPassT>
0446 inline std::enable_if_t<is_detected<HasRunOnLoopT, LoopPassT>::value,
0447 FunctionToLoopPassAdaptor>
0448 createFunctionToLoopPassAdaptor(LoopPassT &&Pass, bool UseMemorySSA = false,
0449 bool UseBlockFrequencyInfo = false,
0450 bool UseBranchProbabilityInfo = false) {
0451 using PassModelT =
0452 detail::PassModel<Loop, LoopPassT, LoopAnalysisManager,
0453 LoopStandardAnalysisResults &, LPMUpdater &>;
0454
0455
0456 return FunctionToLoopPassAdaptor(
0457 std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>(
0458 new PassModelT(std::forward<LoopPassT>(Pass))),
0459 UseMemorySSA, UseBlockFrequencyInfo, UseBranchProbabilityInfo, false);
0460 }
0461
0462
0463
0464 template <typename LoopNestPassT>
0465 inline std::enable_if_t<!is_detected<HasRunOnLoopT, LoopNestPassT>::value,
0466 FunctionToLoopPassAdaptor>
0467 createFunctionToLoopPassAdaptor(LoopNestPassT &&Pass, bool UseMemorySSA = false,
0468 bool UseBlockFrequencyInfo = false,
0469 bool UseBranchProbabilityInfo = false) {
0470 LoopPassManager LPM;
0471 LPM.addPass(std::forward<LoopNestPassT>(Pass));
0472 using PassModelT =
0473 detail::PassModel<Loop, LoopPassManager, LoopAnalysisManager,
0474 LoopStandardAnalysisResults &, LPMUpdater &>;
0475
0476
0477 return FunctionToLoopPassAdaptor(
0478 std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>(
0479 new PassModelT(std::move(LPM))),
0480 UseMemorySSA, UseBlockFrequencyInfo, UseBranchProbabilityInfo, true);
0481 }
0482
0483
0484
0485 template <>
0486 inline FunctionToLoopPassAdaptor
0487 createFunctionToLoopPassAdaptor<LoopPassManager>(
0488 LoopPassManager &&LPM, bool UseMemorySSA, bool UseBlockFrequencyInfo,
0489 bool UseBranchProbabilityInfo) {
0490
0491
0492 using PassModelT =
0493 detail::PassModel<Loop, LoopPassManager, LoopAnalysisManager,
0494 LoopStandardAnalysisResults &, LPMUpdater &>;
0495 bool LoopNestMode = (LPM.getNumLoopPasses() == 0);
0496
0497
0498 return FunctionToLoopPassAdaptor(
0499 std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>(
0500 new PassModelT(std::move(LPM))),
0501 UseMemorySSA, UseBlockFrequencyInfo, UseBranchProbabilityInfo,
0502 LoopNestMode);
0503 }
0504
0505
0506 class PrintLoopPass : public PassInfoMixin<PrintLoopPass> {
0507 raw_ostream &OS;
0508 std::string Banner;
0509
0510 public:
0511 PrintLoopPass();
0512 PrintLoopPass(raw_ostream &OS, const std::string &Banner = "");
0513
0514 PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
0515 LoopStandardAnalysisResults &, LPMUpdater &);
0516 };
0517 }
0518
0519 #endif