[llvm] 5ab421f - [LICM] Add allowspeculation pass options.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 18 09:52:19 PDT 2022


Author: Florian Hahn
Date: 2022-03-18T16:51:57Z
New Revision: 5ab421fb4e0e32383af394ef8d861a0bba8e11ee

URL: https://github.com/llvm/llvm-project/commit/5ab421fb4e0e32383af394ef8d861a0bba8e11ee
DIFF: https://github.com/llvm/llvm-project/commit/5ab421fb4e0e32383af394ef8d861a0bba8e11ee.diff

LOG: [LICM] Add allowspeculation pass options.

This adds a new option to control AllowSpeculation added in D119965 when
using `-passes=...`.

This allows reproducing #54023 using opt.

Reviewed By: aeubanks

Differential Revision: https://reviews.llvm.org/D121944

Added: 
    llvm/test/Transforms/LICM/allow-speculation-option.ll

Modified: 
    llvm/include/llvm/Transforms/Scalar/LICM.h
    llvm/lib/Passes/PassBuilder.cpp
    llvm/lib/Passes/PassRegistry.def
    llvm/lib/Transforms/Scalar/LICM.cpp
    llvm/test/Other/new-pm-print-pipeline.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/Scalar/LICM.h b/llvm/include/llvm/Transforms/Scalar/LICM.h
index ba2cdda802ab5..f7dd40be47e58 100644
--- a/llvm/include/llvm/Transforms/Scalar/LICM.h
+++ b/llvm/include/llvm/Transforms/Scalar/LICM.h
@@ -45,44 +45,57 @@ class LoopNest;
 extern cl::opt<unsigned> SetLicmMssaOptCap;
 extern cl::opt<unsigned> SetLicmMssaNoAccForPromotionCap;
 
+struct LICMOptions {
+  unsigned MssaOptCap;
+  unsigned MssaNoAccForPromotionCap;
+  bool AllowSpeculation;
+
+  LICMOptions()
+      : MssaOptCap(SetLicmMssaOptCap),
+        MssaNoAccForPromotionCap(SetLicmMssaNoAccForPromotionCap),
+        AllowSpeculation(true) {}
+
+  LICMOptions(unsigned MssaOptCap, unsigned MssaNoAccForPromotionCap,
+              bool AllowSpeculation)
+      : MssaOptCap(MssaOptCap),
+        MssaNoAccForPromotionCap(MssaNoAccForPromotionCap),
+        AllowSpeculation(AllowSpeculation) {}
+};
+
 /// Performs Loop Invariant Code Motion Pass.
 class LICMPass : public PassInfoMixin<LICMPass> {
-  unsigned LicmMssaOptCap;
-  unsigned LicmMssaNoAccForPromotionCap;
-  bool LicmAllowSpeculation;
+  LICMOptions Opts;
 
 public:
-  LICMPass()
-      : LicmMssaOptCap(SetLicmMssaOptCap),
-        LicmMssaNoAccForPromotionCap(SetLicmMssaNoAccForPromotionCap),
-        LicmAllowSpeculation(true) {}
-  LICMPass(unsigned LicmMssaOptCap, unsigned LicmMssaNoAccForPromotionCap,
-           bool LicmAllowSpeculation)
-      : LicmMssaOptCap(LicmMssaOptCap),
-        LicmMssaNoAccForPromotionCap(LicmMssaNoAccForPromotionCap),
-        LicmAllowSpeculation(LicmAllowSpeculation) {}
+  LICMPass(unsigned MssaOptCap, unsigned MssaNoAccForPromotionCap,
+           bool AllowSpeculation)
+      : LICMPass(LICMOptions(MssaOptCap, MssaNoAccForPromotionCap,
+                             AllowSpeculation)) {}
+  LICMPass(LICMOptions Opts) : Opts(Opts) {}
+
   PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
                         LoopStandardAnalysisResults &AR, LPMUpdater &U);
+
+  void printPipeline(raw_ostream &OS,
+                     function_ref<StringRef(StringRef)> MapClassName2PassName);
 };
 
 /// Performs LoopNest Invariant Code Motion Pass.
 class LNICMPass : public PassInfoMixin<LNICMPass> {
-  unsigned LicmMssaOptCap;
-  unsigned LicmMssaNoAccForPromotionCap;
-  bool LicmAllowSpeculation;
+  LICMOptions Opts;
 
 public:
-  LNICMPass()
-      : LicmMssaOptCap(SetLicmMssaOptCap),
-        LicmMssaNoAccForPromotionCap(SetLicmMssaNoAccForPromotionCap),
-        LicmAllowSpeculation(true) {}
-  LNICMPass(unsigned LicmMssaOptCap, unsigned LicmMssaNoAccForPromotionCap,
-            bool LicmAllowSpeculation)
-      : LicmMssaOptCap(LicmMssaOptCap),
-        LicmMssaNoAccForPromotionCap(LicmMssaNoAccForPromotionCap),
-        LicmAllowSpeculation(LicmAllowSpeculation) {}
+  LNICMPass(unsigned MssaOptCap, unsigned MssaNoAccForPromotionCap,
+            bool AllowSpeculation)
+      : LNICMPass(LICMOptions(MssaOptCap, MssaNoAccForPromotionCap,
+                              AllowSpeculation)) {}
+  LNICMPass(LICMOptions Opts) : Opts(Opts) {}
+
   PreservedAnalyses run(LoopNest &L, LoopAnalysisManager &AM,
                         LoopStandardAnalysisResults &AR, LPMUpdater &U);
+
+  void printPipeline(raw_ostream &OS,
+                     function_ref<StringRef(StringRef)> MapClassName2PassName);
 };
 } // end namespace llvm
 

diff  --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 05efe90846d13..1f407a6fcfca6 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -752,6 +752,24 @@ Expected<std::pair<bool, bool>> parseLoopUnswitchOptions(StringRef Params) {
   return Result;
 }
 
+Expected<LICMOptions> parseLICMOptions(StringRef Params) {
+  LICMOptions Result;
+  while (!Params.empty()) {
+    StringRef ParamName;
+    std::tie(ParamName, Params) = Params.split(';');
+
+    bool Enable = !ParamName.consume_front("no-");
+    if (ParamName == "allowspeculation") {
+      Result.AllowSpeculation = Enable;
+    } else {
+      return make_error<StringError>(
+          formatv("invalid LICM pass parameter '{0}' ", ParamName).str(),
+          inconvertibleErrorCode());
+    }
+  }
+  return Result;
+}
+
 Expected<bool> parseMergedLoadStoreMotionOptions(StringRef Params) {
   bool Result = false;
   while (!Params.empty()) {

diff  --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index e0780f5ee845f..8009a308bdf5e 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -463,7 +463,6 @@ FUNCTION_PASS_WITH_PARAMS("print<stack-lifetime>",
 #ifndef LOOPNEST_PASS
 #define LOOPNEST_PASS(NAME, CREATE_PASS)
 #endif
-LOOPNEST_PASS("lnicm", LNICMPass())
 LOOPNEST_PASS("loop-flatten", LoopFlattenPass())
 LOOPNEST_PASS("loop-interchange", LoopInterchangePass())
 LOOPNEST_PASS("loop-unroll-and-jam", LoopUnrollAndJamPass())
@@ -486,7 +485,6 @@ LOOP_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC))
 LOOP_PASS("canon-freeze", CanonicalizeFreezeInLoopsPass())
 LOOP_PASS("dot-ddg", DDGDotPrinterPass())
 LOOP_PASS("invalidate<all>", InvalidateAllAnalysesPass())
-LOOP_PASS("licm", LICMPass())
 LOOP_PASS("loop-idiom", LoopIdiomRecognizePass())
 LOOP_PASS("loop-instsimplify", LoopInstSimplifyPass())
 LOOP_PASS("loop-rotate", LoopRotatePass())
@@ -519,4 +517,18 @@ LOOP_PASS_WITH_PARAMS("simple-loop-unswitch",
                       },
                       parseLoopUnswitchOptions,
                       "nontrivial;no-nontrivial;trivial;no-trivial")
+
+LOOP_PASS_WITH_PARAMS("licm", "LICMPass",
+                      [](LICMOptions Params) {
+                        return LICMPass(Params);
+                      },
+                      parseLICMOptions,
+                      "allowspeculation");
+
+LOOP_PASS_WITH_PARAMS("lnicm", "LNICMPass",
+                      [](LICMOptions Params) {
+                        return LNICMPass(Params);
+                      },
+                      parseLICMOptions,
+                      "allowspeculation");
 #undef LOOP_PASS_WITH_PARAMS

diff  --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 458d4cfbd4823..88d9eed187654 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -270,8 +270,8 @@ PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM,
   // but ORE cannot be preserved (see comment before the pass definition).
   OptimizationRemarkEmitter ORE(L.getHeader()->getParent());
 
-  LoopInvariantCodeMotion LICM(LicmMssaOptCap, LicmMssaNoAccForPromotionCap,
-                               LicmAllowSpeculation);
+  LoopInvariantCodeMotion LICM(Opts.MssaOptCap, Opts.MssaNoAccForPromotionCap,
+                               Opts.AllowSpeculation);
   if (!LICM.runOnLoop(&L, &AR.AA, &AR.LI, &AR.DT, AR.BFI, &AR.TLI, &AR.TTI,
                       &AR.SE, AR.MSSA, &ORE))
     return PreservedAnalyses::all();
@@ -285,6 +285,16 @@ PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM,
   return PA;
 }
 
+void LICMPass::printPipeline(
+    raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
+  static_cast<PassInfoMixin<LICMPass> *>(this)->printPipeline(
+      OS, MapClassName2PassName);
+
+  OS << "<";
+  OS << (Opts.AllowSpeculation ? "" : "no-") << "allowspeculation";
+  OS << ">";
+}
+
 PreservedAnalyses LNICMPass::run(LoopNest &LN, LoopAnalysisManager &AM,
                                  LoopStandardAnalysisResults &AR,
                                  LPMUpdater &) {
@@ -296,8 +306,8 @@ PreservedAnalyses LNICMPass::run(LoopNest &LN, LoopAnalysisManager &AM,
   // but ORE cannot be preserved (see comment before the pass definition).
   OptimizationRemarkEmitter ORE(LN.getParent());
 
-  LoopInvariantCodeMotion LICM(LicmMssaOptCap, LicmMssaNoAccForPromotionCap,
-                               LicmAllowSpeculation);
+  LoopInvariantCodeMotion LICM(Opts.MssaOptCap, Opts.MssaNoAccForPromotionCap,
+                               Opts.AllowSpeculation);
 
   Loop &OutermostLoop = LN.getOutermostLoop();
   bool Changed = LICM.runOnLoop(&OutermostLoop, &AR.AA, &AR.LI, &AR.DT, AR.BFI,
@@ -315,6 +325,16 @@ PreservedAnalyses LNICMPass::run(LoopNest &LN, LoopAnalysisManager &AM,
   return PA;
 }
 
+void LNICMPass::printPipeline(
+    raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
+  static_cast<PassInfoMixin<LNICMPass> *>(this)->printPipeline(
+      OS, MapClassName2PassName);
+
+  OS << "<";
+  OS << (Opts.AllowSpeculation ? "" : "no-") << "allowspeculation";
+  OS << ">";
+}
+
 char LegacyLICMPass::ID = 0;
 INITIALIZE_PASS_BEGIN(LegacyLICMPass, "licm", "Loop Invariant Code Motion",
                       false, false)

diff  --git a/llvm/test/Other/new-pm-print-pipeline.ll b/llvm/test/Other/new-pm-print-pipeline.ll
index a30bcc5881496..5841702b63341 100644
--- a/llvm/test/Other/new-pm-print-pipeline.ll
+++ b/llvm/test/Other/new-pm-print-pipeline.ll
@@ -69,9 +69,13 @@
 
 ;; Test that the loop-nest-pass lnicm is printed with the other loop-passes in the pipeline.
 ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(loop-mssa(licm,loop-rotate,loop-deletion,lnicm,loop-rotate))' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-23
-; CHECK-23: function(loop-mssa(licm,loop-rotate,loop-deletion,lnicm,loop-rotate))
+; CHECK-23: function(loop-mssa(licm<allowspeculation>,loop-rotate,loop-deletion,lnicm<allowspeculation>,loop-rotate))
 
 ;; Test that -debugify and -check-debugify is printed correctly.
 ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='debugify,no-op-function,check-debugify' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-24
 ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -enable-debugify -passes='no-op-function' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-24
 ; CHECK-24: debugify,function(no-op-function),check-debugify
+
+;; Test that LICM & LNICM with options.
+; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(loop-mssa(licm<allowspeculation>,licm<no-allowspeculation>,lnicm<allowspeculation>,lnicm<no-allowspeculation>))' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-25
+; CHECK-25: function(loop-mssa(licm<allowspeculation>,licm<no-allowspeculation>,lnicm<allowspeculation>,lnicm<no-allowspeculation>))

diff  --git a/llvm/test/Transforms/LICM/allow-speculation-option.ll b/llvm/test/Transforms/LICM/allow-speculation-option.ll
new file mode 100644
index 0000000000000..572ce2d8a33d4
--- /dev/null
+++ b/llvm/test/Transforms/LICM/allow-speculation-option.ll
@@ -0,0 +1,41 @@
+; RUN: opt -passes='loop-mssa(licm<allowspeculation>)' -S %s | FileCheck --check-prefixes=COMMON,SPEC_ON %s
+; RUN: opt -passes='loop-mssa(licm<no-allowspeculation>)' -S %s | FileCheck --check-prefixes=COMMON,SPEC_OFF %s
+; RUN: opt -passes='loop-mssa(lnicm<allowspeculation>)' -S %s | FileCheck --check-prefixes=COMMON,SPEC_ON %s
+; RUN: opt -passes='loop-mssa(lnicm<no-allowspeculation>)' -S %s | FileCheck --check-prefixes=COMMON,SPEC_OFF %s
+
+define void @test([10 x i32]* %ptr, i32 %N) {
+; COMMON-LABEL: @test(
+; COMMON-NEXT:  entry:
+; SPEC_ON-NEXT:   [[GEP:%.*]] = getelementptr [10 x i32], [10 x i32]* [[PTR:%.*]], i32 0, i32 0
+; COMMON-NEXT:    br label [[LOOP_HEADER:%.*]]
+; COMMON:       loop.header:
+; COMMON-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; COMMON-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
+; COMMON-NEXT:    br i1 [[CMP]], label [[LOOP_LATCH]], label [[EXIT:%.*]]
+; COMMON:       loop.latch:
+; SPEC_OFF-NEXT:  [[GEP:%.*]] = getelementptr [10 x i32], [10 x i32]* [[PTR:%.*]], i32 0, i32 0
+; COMMON-NEXT:    [[GEP_IV:%.*]] = getelementptr i32, i32* [[GEP]], i32 [[IV]]
+; COMMON-NEXT:    store i32 9999, i32* [[GEP_IV]], align 4
+; COMMON-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; COMMON-NEXT:    br label [[LOOP_HEADER]]
+; COMMON:       exit:
+; COMMON-NEXT:    ret void
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
+  %cmp = icmp ult i32 %iv, %N
+  br i1 %cmp, label %loop.latch, label %exit
+
+loop.latch:
+  %gep = getelementptr [10 x i32], [10 x i32]* %ptr, i32 0, i32 0
+  %gep.iv = getelementptr i32, i32* %gep, i32 %iv
+  store i32 9999, i32* %gep.iv
+  %iv.next = add i32 %iv, 1
+  br label %loop.header
+
+exit:
+  ret void
+}


        


More information about the llvm-commits mailing list