diff --git a/llvm/include/llvm/Transforms/Scalar.h b/llvm/include/llvm/Transforms/Scalar.h --- a/llvm/include/llvm/Transforms/Scalar.h +++ b/llvm/include/llvm/Transforms/Scalar.h @@ -211,7 +211,7 @@ // // LoopRotate - This pass is a simple loop rotating pass. // -Pass *createLoopRotatePass(int MaxHeaderSize = -1, bool PrepareForLTO = false); +Pass *createLoopRotatePass(bool PrepareForLTO = false); //===----------------------------------------------------------------------===// // diff --git a/llvm/include/llvm/Transforms/Scalar/LoopRotation.h b/llvm/include/llvm/Transforms/Scalar/LoopRotation.h --- a/llvm/include/llvm/Transforms/Scalar/LoopRotation.h +++ b/llvm/include/llvm/Transforms/Scalar/LoopRotation.h @@ -22,13 +22,11 @@ /// A simple loop rotation transformation. class LoopRotatePass : public PassInfoMixin { public: - LoopRotatePass(bool EnableHeaderDuplication = true, - bool PrepareForLTO = false); + LoopRotatePass(bool PrepareForLTO = false); PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U); private: - const bool EnableHeaderDuplication; const bool PrepareForLTO; }; } diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -295,8 +295,9 @@ // TODO: Investigate promotion cap for O1. LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap)); - LPM1.addPass(LoopRotatePass(/* Disable header duplication */ true, - isLTOPreLink(Phase))); + // Note that this LoopRotate pass doesn't disable header duplication, but + // perhaps it should. + LPM1.addPass(LoopRotatePass(isLTOPreLink(Phase))); // TODO: Investigate promotion cap for O1. LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap)); LPM1.addPass(SimpleLoopUnswitchPass()); @@ -467,9 +468,7 @@ // TODO: Investigate promotion cap for O1. LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap)); - // Disable header duplication in loop rotation at -Oz. - LPM1.addPass( - LoopRotatePass(Level != OptimizationLevel::Oz, isLTOPreLink(Phase))); + LPM1.addPass(LoopRotatePass(isLTOPreLink(Phase))); // TODO: Investigate promotion cap for O1. LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap)); LPM1.addPass( @@ -641,10 +640,9 @@ MPM.addPass(PGOInstrumentationGen(IsCS)); FunctionPassManager FPM; - // Disable header duplication in loop rotation at -Oz. - FPM.addPass(createFunctionToLoopPassAdaptor( - LoopRotatePass(Level != OptimizationLevel::Oz), /*UseMemorySSA=*/false, - /*UseBlockFrequencyInfo=*/false)); + FPM.addPass(createFunctionToLoopPassAdaptor(LoopRotatePass(), + /*UseMemorySSA=*/false, + /*UseBlockFrequencyInfo=*/false)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM), PTO.EagerlyInvalidateAnalyses)); @@ -1163,8 +1161,7 @@ LoopPassManager LPM; // First rotate loops that may have been un-rotated by prior passes. - // Disable header duplication at -Oz. - LPM.addPass(LoopRotatePass(Level != OptimizationLevel::Oz, LTOPreLink)); + LPM.addPass(LoopRotatePass(LTOPreLink)); // Some loops may have become dead by now. Try to delete them. // FIXME: see discussion in https://reviews.llvm.org/D112851, // this may need to be revisited once we run GVN before loop deletion diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -454,8 +454,8 @@ // to reduce amount of IR that will have to be duplicated. // TODO: Investigate promotion cap for O1. MPM.add(createLICMPass(LicmMssaOptCap, LicmMssaNoAccForPromotionCap)); - // Rotate Loop - disable header duplication at -Oz - MPM.add(createLoopRotatePass(SizeLevel == 2 ? 0 : -1, PrepareForLTO)); + // Rotate Loop - header duplication is disabled if minsize is set. + MPM.add(createLoopRotatePass(PrepareForLTO)); // TODO: Investigate promotion cap for O1. MPM.add(createLICMPass(LicmMssaOptCap, LicmMssaNoAccForPromotionCap)); if (EnableSimpleLoopUnswitch) @@ -921,8 +921,8 @@ // Re-rotate loops in all our loop nests. These may have fallout out of // rotated form due to GVN or other transformations, and the vectorizer relies - // on the rotated form. Disable header duplication at -Oz. - MPM.add(createLoopRotatePass(SizeLevel == 2 ? 0 : -1, PrepareForLTO)); + // on the rotated form. + MPM.add(createLoopRotatePass(PrepareForLTO)); // Distribute loops to allow partial vectorization. I.e. isolate dependences // into separate loop that would otherwise inhibit vectorization. This is diff --git a/llvm/lib/Transforms/Scalar/LoopRotation.cpp b/llvm/lib/Transforms/Scalar/LoopRotation.cpp --- a/llvm/lib/Transforms/Scalar/LoopRotation.cpp +++ b/llvm/lib/Transforms/Scalar/LoopRotation.cpp @@ -40,17 +40,16 @@ cl::desc("Run loop-rotation in the prepare-for-lto stage. This option " "should be used for testing only.")); -LoopRotatePass::LoopRotatePass(bool EnableHeaderDuplication, bool PrepareForLTO) - : EnableHeaderDuplication(EnableHeaderDuplication), - PrepareForLTO(PrepareForLTO) {} +LoopRotatePass::LoopRotatePass(bool PrepareForLTO) + : PrepareForLTO(PrepareForLTO) {} PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &) { // Vectorization requires loop-rotation. Use default threshold for loops the - // user explicitly marked for vectorization, even when header duplication is - // disabled. - int Threshold = EnableHeaderDuplication || + // user explicitly marked for vectorization, even when the minsize attribute + // is set. + int Threshold = !L.getHeader()->getParent()->hasMinSize() || hasVectorizeTransformation(&L) == TM_ForcedByUser ? DefaultRotationThreshold : 0; @@ -80,19 +79,13 @@ namespace { class LoopRotateLegacyPass : public LoopPass { - unsigned MaxHeaderSize; bool PrepareForLTO; public: static char ID; // Pass ID, replacement for typeid - LoopRotateLegacyPass(int SpecifiedMaxHeaderSize = -1, - bool PrepareForLTO = false) + LoopRotateLegacyPass(bool PrepareForLTO = false) : LoopPass(ID), PrepareForLTO(PrepareForLTO) { initializeLoopRotateLegacyPassPass(*PassRegistry::getPassRegistry()); - if (SpecifiedMaxHeaderSize == -1) - MaxHeaderSize = DefaultRotationThreshold; - else - MaxHeaderSize = unsigned(SpecifiedMaxHeaderSize); } // LCSSA form makes instruction renaming easier. @@ -126,11 +119,12 @@ if (MSSAA) MSSAU = MemorySSAUpdater(&MSSAA->getMSSA()); // Vectorization requires loop-rotation. Use default threshold for loops the - // user explicitly marked for vectorization, even when header duplication is - // disabled. - int Threshold = hasVectorizeTransformation(L) == TM_ForcedByUser - ? DefaultRotationThreshold - : MaxHeaderSize; + // user explicitly marked for vectorization, even when the minsize attribute + // is set. + int Threshold = + !F.hasMinSize() || hasVectorizeTransformation(L) == TM_ForcedByUser + ? DefaultRotationThreshold + : 0; return LoopRotation(L, LI, TTI, AC, &DT, &SE, MSSAU.hasValue() ? MSSAU.getPointer() : nullptr, SQ, @@ -150,6 +144,6 @@ INITIALIZE_PASS_END(LoopRotateLegacyPass, "loop-rotate", "Rotate Loops", false, false) -Pass *llvm::createLoopRotatePass(int MaxHeaderSize, bool PrepareForLTO) { - return new LoopRotateLegacyPass(MaxHeaderSize, PrepareForLTO); +Pass *llvm::createLoopRotatePass(bool PrepareForLTO) { + return new LoopRotateLegacyPass(PrepareForLTO); } diff --git a/llvm/test/Transforms/LoopRotate/minsize-disable.ll b/llvm/test/Transforms/LoopRotate/minsize-disable.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LoopRotate/minsize-disable.ll @@ -0,0 +1,33 @@ +; REQUIRES: asserts +; RUN: opt < %s -S -O2 -debug -debug-only=loop-rotate 2>&1 | FileCheck %s +; RUN: opt < %s -S -passes='default' -debug -debug-only=loop-rotate 2>&1 | FileCheck %s + +; Loop should not be rotated for functions with the minsize attribute. +; This is mostly useful for LTO which doesn't (yet) understand -Oz. +; CHECK: LoopRotation: NOT rotating - contains 2 instructions, which is more + +@e = global i32 10 + +declare void @use(i32) + +; Function attrs: minsize optsize +define void @test() #0 { +entry: + %end = load i32, i32* @e + br label %loop + +loop: + %n.phi = phi i32 [ %n, %loop.fin ], [ 0, %entry ] + %cond = icmp eq i32 %n.phi, %end + br i1 %cond, label %exit, label %loop.fin + +loop.fin: + %n = add i32 %n.phi, 1 + call void @use(i32 %n) + br label %loop + +exit: + ret void +} + +attributes #0 = { minsize optsize } diff --git a/llvm/test/Transforms/LoopRotate/oz-disable.ll b/llvm/test/Transforms/LoopRotate/oz-disable.ll deleted file mode 100644 --- a/llvm/test/Transforms/LoopRotate/oz-disable.ll +++ /dev/null @@ -1,32 +0,0 @@ -; REQUIRES: asserts -; RUN: opt < %s -S -Os -debug -debug-only=loop-rotate 2>&1 | FileCheck %s -check-prefix=OS -; RUN: opt < %s -S -Oz -debug -debug-only=loop-rotate 2>&1 | FileCheck %s -check-prefix=OZ -; RUN: opt < %s -S -passes='default' -debug -debug-only=loop-rotate 2>&1 | FileCheck %s -check-prefix=OS -; RUN: opt < %s -S -passes='default' -debug -debug-only=loop-rotate 2>&1 | FileCheck %s -check-prefix=OZ - -; Loop should be rotated for -Os but not for -Oz. -; OS: rotating Loop at depth 1 -; OZ-NOT: rotating Loop at depth 1 - -@e = global i32 10 - -declare void @use(i32) - -define void @test() { -entry: - %end = load i32, i32* @e - br label %loop - -loop: - %n.phi = phi i32 [ %n, %loop.fin ], [ 0, %entry ] - %cond = icmp eq i32 %n.phi, %end - br i1 %cond, label %exit, label %loop.fin - -loop.fin: - %n = add i32 %n.phi, 1 - call void @use(i32 %n) - br label %loop - -exit: - ret void -}