[PassBuilder] Add textual representation for function simplification pipeline
authorArthur Eubanks <aeubanks@google.com>
Mon, 26 Jun 2023 16:51:22 +0000 (09:51 -0700)
committerArthur Eubanks <aeubanks@google.com>
Thu, 29 Jun 2023 16:39:04 +0000 (09:39 -0700)
Reviewed By: nikic

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

llvm/lib/Passes/PassBuilder.cpp
llvm/lib/Passes/PassRegistry.def
llvm/test/Other/function-simplification.ll [new file with mode: 0644]

index 25a9e7d..bbab55c 100644 (file)
@@ -80,6 +80,7 @@
 #include "llvm/IR/SafepointIRVerifier.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/IRPrinter/IRPrintingPasses.h"
+#include "llvm/Passes/OptimizationLevel.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -527,6 +528,17 @@ static bool checkParametrizedPassName(StringRef Name, StringRef PassName) {
   return Name.startswith("<") && Name.endswith(">");
 }
 
+static std::optional<OptimizationLevel> parseOptLevel(StringRef S) {
+  return StringSwitch<std::optional<OptimizationLevel>>(S)
+      .Case("O0", OptimizationLevel::O0)
+      .Case("O1", OptimizationLevel::O1)
+      .Case("O2", OptimizationLevel::O2)
+      .Case("O3", OptimizationLevel::O3)
+      .Case("Os", OptimizationLevel::Os)
+      .Case("Oz", OptimizationLevel::Oz)
+      .Default(std::nullopt);
+}
+
 namespace {
 
 /// This performs customized parsing of pass name with parameters.
@@ -613,14 +625,10 @@ Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {
   while (!Params.empty()) {
     StringRef ParamName;
     std::tie(ParamName, Params) = Params.split(';');
-    int OptLevel = StringSwitch<int>(ParamName)
-                       .Case("O0", 0)
-                       .Case("O1", 1)
-                       .Case("O2", 2)
-                       .Case("O3", 3)
-                       .Default(-1);
-    if (OptLevel >= 0) {
-      UnrollOpts.setOptLevel(OptLevel);
+    std::optional<OptimizationLevel> OptLevel = parseOptLevel(ParamName);
+    // Don't accept -Os/-Oz.
+    if (OptLevel && !OptLevel->isOptimizingForSize()) {
+      UnrollOpts.setOptLevel(OptLevel->getSpeedupLevel());
       continue;
     }
     if (ParamName.consume_front("full-unroll-max=")) {
@@ -1046,6 +1054,18 @@ Expected<bool> parseSeparateConstOffsetFromGEPPassOptions(StringRef Params) {
                                "SeparateConstOffsetFromGEP");
 }
 
+Expected<OptimizationLevel>
+parseFunctionSimplificationPipelineOptions(StringRef Params) {
+  std::optional<OptimizationLevel> L = parseOptLevel(Params);
+  if (!L || *L == OptimizationLevel::O0) {
+    return make_error<StringError>(
+        formatv("invalid function-simplification parameter '{0}' ", Params)
+            .str(),
+        inconvertibleErrorCode());
+  };
+  return *L;
+}
+
 } // namespace
 
 /// Tests whether a pass name starts with a valid prefix for a default pipeline
@@ -1342,13 +1362,7 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM,
 
     assert(Matches.size() == 3 && "Must capture two matched strings!");
 
-    OptimizationLevel L = StringSwitch<OptimizationLevel>(Matches[2])
-                              .Case("O0", OptimizationLevel::O0)
-                              .Case("O1", OptimizationLevel::O1)
-                              .Case("O2", OptimizationLevel::O2)
-                              .Case("O3", OptimizationLevel::O3)
-                              .Case("Os", OptimizationLevel::Os)
-                              .Case("Oz", OptimizationLevel::Oz);
+    OptimizationLevel L = *parseOptLevel(Matches[2]);
 
     // This is consistent with old pass manager invoked via opt, but
     // inconsistent with clang. Clang doesn't enable loop vectorization
index 956e1d9..800feb2 100644 (file)
@@ -550,6 +550,13 @@ FUNCTION_PASS_WITH_PARAMS("separate-const-offset-from-gep",
                            },
                           parseSeparateConstOffsetFromGEPPassOptions,
                           "lower-gep")
+FUNCTION_PASS_WITH_PARAMS("function-simplification",
+                          "",
+                           [this](OptimizationLevel OL) {
+                             return buildFunctionSimplificationPipeline(OL, ThinOrFullLTOPhase::None);
+                           },
+                          parseFunctionSimplificationPipelineOptions,
+                          "O1;O2;O3;Os;Oz")
 #undef FUNCTION_PASS_WITH_PARAMS
 
 #ifndef LOOPNEST_PASS
diff --git a/llvm/test/Other/function-simplification.ll b/llvm/test/Other/function-simplification.ll
new file mode 100644 (file)
index 0000000..e782aa4
--- /dev/null
@@ -0,0 +1,18 @@
+; RUN: opt -passes='function-simplification<O1>' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O1
+; RUN: opt -passes='function-simplification<O2>' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O23SZ
+; RUN: opt -passes='function-simplification<O3>' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O23SZ
+; RUN: opt -passes='function-simplification<Os>' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O23SZ
+; RUN: opt -passes='function-simplification<Oz>' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O23SZ
+; RUN: not opt -passes='function-simplification<O0>' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O0
+
+; O1: Running pass: EarlyCSEPass
+; O1-NOT: Running pass: GVNPass
+
+; O23SZ: Running pass: EarlyCSEPass
+; O23SZ: Running pass: GVNPass
+
+; O0: invalid function-simplification parameter 'O0'
+
+define void @f() {
+  ret void
+}
\ No newline at end of file