xref: /openbsd-src/gnu/llvm/llvm/lib/Transforms/Scalar/LoopRotation.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- LoopRotation.cpp - Loop Rotation Pass ------------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements Loop Rotation Pass.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "llvm/Transforms/Scalar/LoopRotation.h"
1473471bf0Spatrick #include "llvm/Analysis/AssumptionCache.h"
1509467b48Spatrick #include "llvm/Analysis/InstructionSimplify.h"
1673471bf0Spatrick #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
17*d415bd75Srobert #include "llvm/Analysis/LoopInfo.h"
1809467b48Spatrick #include "llvm/Analysis/LoopPass.h"
1909467b48Spatrick #include "llvm/Analysis/MemorySSA.h"
2009467b48Spatrick #include "llvm/Analysis/MemorySSAUpdater.h"
2109467b48Spatrick #include "llvm/Analysis/ScalarEvolution.h"
2209467b48Spatrick #include "llvm/Analysis/TargetTransformInfo.h"
2309467b48Spatrick #include "llvm/InitializePasses.h"
2409467b48Spatrick #include "llvm/Support/CommandLine.h"
2509467b48Spatrick #include "llvm/Transforms/Scalar.h"
2609467b48Spatrick #include "llvm/Transforms/Utils/LoopRotationUtils.h"
2709467b48Spatrick #include "llvm/Transforms/Utils/LoopUtils.h"
28*d415bd75Srobert #include <optional>
2909467b48Spatrick using namespace llvm;
3009467b48Spatrick 
3109467b48Spatrick #define DEBUG_TYPE "loop-rotate"
3209467b48Spatrick 
3309467b48Spatrick static cl::opt<unsigned> DefaultRotationThreshold(
3409467b48Spatrick     "rotation-max-header-size", cl::init(16), cl::Hidden,
3509467b48Spatrick     cl::desc("The default maximum header size for automatic loop rotation"));
3609467b48Spatrick 
3773471bf0Spatrick static cl::opt<bool> PrepareForLTOOption(
3873471bf0Spatrick     "rotation-prepare-for-lto", cl::init(false), cl::Hidden,
3973471bf0Spatrick     cl::desc("Run loop-rotation in the prepare-for-lto stage. This option "
4073471bf0Spatrick              "should be used for testing only."));
4173471bf0Spatrick 
LoopRotatePass(bool EnableHeaderDuplication,bool PrepareForLTO)4273471bf0Spatrick LoopRotatePass::LoopRotatePass(bool EnableHeaderDuplication, bool PrepareForLTO)
4373471bf0Spatrick     : EnableHeaderDuplication(EnableHeaderDuplication),
4473471bf0Spatrick       PrepareForLTO(PrepareForLTO) {}
4509467b48Spatrick 
run(Loop & L,LoopAnalysisManager & AM,LoopStandardAnalysisResults & AR,LPMUpdater &)4609467b48Spatrick PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM,
4709467b48Spatrick                                       LoopStandardAnalysisResults &AR,
4809467b48Spatrick                                       LPMUpdater &) {
4973471bf0Spatrick   // Vectorization requires loop-rotation. Use default threshold for loops the
5073471bf0Spatrick   // user explicitly marked for vectorization, even when header duplication is
5173471bf0Spatrick   // disabled.
5273471bf0Spatrick   int Threshold = EnableHeaderDuplication ||
5373471bf0Spatrick                           hasVectorizeTransformation(&L) == TM_ForcedByUser
5473471bf0Spatrick                       ? DefaultRotationThreshold
5573471bf0Spatrick                       : 0;
5609467b48Spatrick   const DataLayout &DL = L.getHeader()->getModule()->getDataLayout();
5709467b48Spatrick   const SimplifyQuery SQ = getBestSimplifyQuery(AR, DL);
5809467b48Spatrick 
59*d415bd75Srobert   std::optional<MemorySSAUpdater> MSSAU;
6009467b48Spatrick   if (AR.MSSA)
6109467b48Spatrick     MSSAU = MemorySSAUpdater(AR.MSSA);
62*d415bd75Srobert   bool Changed = LoopRotation(&L, &AR.LI, &AR.TTI, &AR.AC, &AR.DT, &AR.SE,
63*d415bd75Srobert                               MSSAU ? &*MSSAU : nullptr, SQ, false, Threshold,
64*d415bd75Srobert                               false, PrepareForLTO || PrepareForLTOOption);
6509467b48Spatrick 
6609467b48Spatrick   if (!Changed)
6709467b48Spatrick     return PreservedAnalyses::all();
6809467b48Spatrick 
6909467b48Spatrick   if (AR.MSSA && VerifyMemorySSA)
7009467b48Spatrick     AR.MSSA->verifyMemorySSA();
7109467b48Spatrick 
7209467b48Spatrick   auto PA = getLoopPassPreservedAnalyses();
7309467b48Spatrick   if (AR.MSSA)
7409467b48Spatrick     PA.preserve<MemorySSAAnalysis>();
7509467b48Spatrick   return PA;
7609467b48Spatrick }
7709467b48Spatrick 
7809467b48Spatrick namespace {
7909467b48Spatrick 
8009467b48Spatrick class LoopRotateLegacyPass : public LoopPass {
8109467b48Spatrick   unsigned MaxHeaderSize;
8273471bf0Spatrick   bool PrepareForLTO;
8309467b48Spatrick 
8409467b48Spatrick public:
8509467b48Spatrick   static char ID; // Pass ID, replacement for typeid
LoopRotateLegacyPass(int SpecifiedMaxHeaderSize=-1,bool PrepareForLTO=false)8673471bf0Spatrick   LoopRotateLegacyPass(int SpecifiedMaxHeaderSize = -1,
8773471bf0Spatrick                        bool PrepareForLTO = false)
8873471bf0Spatrick       : LoopPass(ID), PrepareForLTO(PrepareForLTO) {
8909467b48Spatrick     initializeLoopRotateLegacyPassPass(*PassRegistry::getPassRegistry());
9009467b48Spatrick     if (SpecifiedMaxHeaderSize == -1)
9109467b48Spatrick       MaxHeaderSize = DefaultRotationThreshold;
9209467b48Spatrick     else
9309467b48Spatrick       MaxHeaderSize = unsigned(SpecifiedMaxHeaderSize);
9409467b48Spatrick   }
9509467b48Spatrick 
9609467b48Spatrick   // LCSSA form makes instruction renaming easier.
getAnalysisUsage(AnalysisUsage & AU) const9709467b48Spatrick   void getAnalysisUsage(AnalysisUsage &AU) const override {
9809467b48Spatrick     AU.addRequired<AssumptionCacheTracker>();
9909467b48Spatrick     AU.addRequired<TargetTransformInfoWrapperPass>();
10009467b48Spatrick     AU.addPreserved<MemorySSAWrapperPass>();
10109467b48Spatrick     getLoopAnalysisUsage(AU);
10273471bf0Spatrick 
10373471bf0Spatrick     // Lazy BFI and BPI are marked as preserved here so LoopRotate
10473471bf0Spatrick     // can remain part of the same loop pass manager as LICM.
10573471bf0Spatrick     AU.addPreserved<LazyBlockFrequencyInfoPass>();
10673471bf0Spatrick     AU.addPreserved<LazyBranchProbabilityInfoPass>();
10709467b48Spatrick   }
10809467b48Spatrick 
runOnLoop(Loop * L,LPPassManager & LPM)10909467b48Spatrick   bool runOnLoop(Loop *L, LPPassManager &LPM) override {
11009467b48Spatrick     if (skipLoop(L))
11109467b48Spatrick       return false;
11209467b48Spatrick     Function &F = *L->getHeader()->getParent();
11309467b48Spatrick 
11409467b48Spatrick     auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
11509467b48Spatrick     const auto *TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
11609467b48Spatrick     auto *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
11709467b48Spatrick     auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
11809467b48Spatrick     auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
11909467b48Spatrick     const SimplifyQuery SQ = getBestSimplifyQuery(*this, F);
120*d415bd75Srobert     std::optional<MemorySSAUpdater> MSSAU;
12109467b48Spatrick     // Not requiring MemorySSA and getting it only if available will split
12209467b48Spatrick     // the loop pass pipeline when LoopRotate is being run first.
12309467b48Spatrick     auto *MSSAA = getAnalysisIfAvailable<MemorySSAWrapperPass>();
12409467b48Spatrick     if (MSSAA)
12509467b48Spatrick       MSSAU = MemorySSAUpdater(&MSSAA->getMSSA());
12673471bf0Spatrick     // Vectorization requires loop-rotation. Use default threshold for loops the
12773471bf0Spatrick     // user explicitly marked for vectorization, even when header duplication is
12873471bf0Spatrick     // disabled.
12973471bf0Spatrick     int Threshold = hasVectorizeTransformation(L) == TM_ForcedByUser
13073471bf0Spatrick                         ? DefaultRotationThreshold
13173471bf0Spatrick                         : MaxHeaderSize;
13273471bf0Spatrick 
133*d415bd75Srobert     return LoopRotation(L, LI, TTI, AC, &DT, &SE, MSSAU ? &*MSSAU : nullptr, SQ,
13473471bf0Spatrick                         false, Threshold, false,
13573471bf0Spatrick                         PrepareForLTO || PrepareForLTOOption);
13609467b48Spatrick   }
13709467b48Spatrick };
138097a140dSpatrick } // end namespace
13909467b48Spatrick 
14009467b48Spatrick char LoopRotateLegacyPass::ID = 0;
14109467b48Spatrick INITIALIZE_PASS_BEGIN(LoopRotateLegacyPass, "loop-rotate", "Rotate Loops",
14209467b48Spatrick                       false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)14309467b48Spatrick INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
14409467b48Spatrick INITIALIZE_PASS_DEPENDENCY(LoopPass)
14509467b48Spatrick INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
14609467b48Spatrick INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
14709467b48Spatrick INITIALIZE_PASS_END(LoopRotateLegacyPass, "loop-rotate", "Rotate Loops", false,
14809467b48Spatrick                     false)
14909467b48Spatrick 
15073471bf0Spatrick Pass *llvm::createLoopRotatePass(int MaxHeaderSize, bool PrepareForLTO) {
15173471bf0Spatrick   return new LoopRotateLegacyPass(MaxHeaderSize, PrepareForLTO);
15209467b48Spatrick }
153