xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopRotation.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- LoopRotation.cpp - Loop Rotation Pass ------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements Loop Rotation Pass.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopRotation.h"
14e8d8bef9SDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
150b57cec5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h"
16fe6060f1SDimitry Andric #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
1781ad6265SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
180b57cec5SDimitry Andric #include "llvm/Analysis/LoopPass.h"
190b57cec5SDimitry Andric #include "llvm/Analysis/MemorySSA.h"
200b57cec5SDimitry Andric #include "llvm/Analysis/MemorySSAUpdater.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h"
220b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
23480093f4SDimitry Andric #include "llvm/InitializePasses.h"
24480093f4SDimitry Andric #include "llvm/Support/CommandLine.h"
250b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h"
260b57cec5SDimitry Andric #include "llvm/Transforms/Utils/LoopRotationUtils.h"
270b57cec5SDimitry Andric #include "llvm/Transforms/Utils/LoopUtils.h"
28bdd1243dSDimitry Andric #include <optional>
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #define DEBUG_TYPE "loop-rotate"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric static cl::opt<unsigned> DefaultRotationThreshold(
340b57cec5SDimitry Andric     "rotation-max-header-size", cl::init(16), cl::Hidden,
350b57cec5SDimitry Andric     cl::desc("The default maximum header size for automatic loop rotation"));
360b57cec5SDimitry Andric 
37e8d8bef9SDimitry Andric static cl::opt<bool> PrepareForLTOOption(
38e8d8bef9SDimitry Andric     "rotation-prepare-for-lto", cl::init(false), cl::Hidden,
39e8d8bef9SDimitry Andric     cl::desc("Run loop-rotation in the prepare-for-lto stage. This option "
40e8d8bef9SDimitry Andric              "should be used for testing only."));
41e8d8bef9SDimitry Andric 
LoopRotatePass(bool EnableHeaderDuplication,bool PrepareForLTO)42e8d8bef9SDimitry Andric LoopRotatePass::LoopRotatePass(bool EnableHeaderDuplication, bool PrepareForLTO)
43e8d8bef9SDimitry Andric     : EnableHeaderDuplication(EnableHeaderDuplication),
44e8d8bef9SDimitry Andric       PrepareForLTO(PrepareForLTO) {}
450b57cec5SDimitry Andric 
printPipeline(raw_ostream & OS,function_ref<StringRef (StringRef)> MapClassName2PassName)4606c3fb27SDimitry Andric void LoopRotatePass::printPipeline(
4706c3fb27SDimitry Andric     raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
4806c3fb27SDimitry Andric   static_cast<PassInfoMixin<LoopRotatePass> *>(this)->printPipeline(
4906c3fb27SDimitry Andric       OS, MapClassName2PassName);
5006c3fb27SDimitry Andric   OS << "<";
5106c3fb27SDimitry Andric   if (!EnableHeaderDuplication)
5206c3fb27SDimitry Andric     OS << "no-";
5306c3fb27SDimitry Andric   OS << "header-duplication;";
5406c3fb27SDimitry Andric 
5506c3fb27SDimitry Andric   if (!PrepareForLTO)
5606c3fb27SDimitry Andric     OS << "no-";
5706c3fb27SDimitry Andric   OS << "prepare-for-lto";
5806c3fb27SDimitry Andric   OS << ">";
5906c3fb27SDimitry Andric }
6006c3fb27SDimitry Andric 
run(Loop & L,LoopAnalysisManager & AM,LoopStandardAnalysisResults & AR,LPMUpdater &)610b57cec5SDimitry Andric PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM,
620b57cec5SDimitry Andric                                       LoopStandardAnalysisResults &AR,
630b57cec5SDimitry Andric                                       LPMUpdater &) {
64e8d8bef9SDimitry Andric   // Vectorization requires loop-rotation. Use default threshold for loops the
65e8d8bef9SDimitry Andric   // user explicitly marked for vectorization, even when header duplication is
66e8d8bef9SDimitry Andric   // disabled.
67*0fca6ea1SDimitry Andric   int Threshold =
68*0fca6ea1SDimitry Andric       (EnableHeaderDuplication && !L.getHeader()->getParent()->hasMinSize()) ||
69e8d8bef9SDimitry Andric               hasVectorizeTransformation(&L) == TM_ForcedByUser
70e8d8bef9SDimitry Andric           ? DefaultRotationThreshold
71e8d8bef9SDimitry Andric           : 0;
72*0fca6ea1SDimitry Andric   const DataLayout &DL = L.getHeader()->getDataLayout();
730b57cec5SDimitry Andric   const SimplifyQuery SQ = getBestSimplifyQuery(AR, DL);
740b57cec5SDimitry Andric 
75bdd1243dSDimitry Andric   std::optional<MemorySSAUpdater> MSSAU;
760b57cec5SDimitry Andric   if (AR.MSSA)
770b57cec5SDimitry Andric     MSSAU = MemorySSAUpdater(AR.MSSA);
78bdd1243dSDimitry Andric   bool Changed = LoopRotation(&L, &AR.LI, &AR.TTI, &AR.AC, &AR.DT, &AR.SE,
79bdd1243dSDimitry Andric                               MSSAU ? &*MSSAU : nullptr, SQ, false, Threshold,
8081ad6265SDimitry Andric                               false, PrepareForLTO || PrepareForLTOOption);
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   if (!Changed)
830b57cec5SDimitry Andric     return PreservedAnalyses::all();
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   if (AR.MSSA && VerifyMemorySSA)
860b57cec5SDimitry Andric     AR.MSSA->verifyMemorySSA();
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   auto PA = getLoopPassPreservedAnalyses();
898bcb0991SDimitry Andric   if (AR.MSSA)
900b57cec5SDimitry Andric     PA.preserve<MemorySSAAnalysis>();
910b57cec5SDimitry Andric   return PA;
920b57cec5SDimitry Andric }
93