[clang] [llvm] [OptBisect][IR] Adding a new OptPassGate for disabling passes via name (PR #145059)

Cristian Assaiante via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 20 08:54:00 PDT 2025


https://github.com/cristianassaiante updated https://github.com/llvm/llvm-project/pull/145059

>From ab6063493744ef5a1ee92fd249bf8d86b7299fad Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Fri, 20 Jun 2025 16:56:23 +0200
Subject: [PATCH] Adding -opt-disable and a test for it

---
 clang/test/CodeGen/opt-disable.c | 13 +++++++
 llvm/include/llvm/IR/OptBisect.h | 39 ++++++++++++++++++++
 llvm/lib/IR/OptBisect.cpp        | 63 ++++++++++++++++++++++++++++++--
 3 files changed, 111 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CodeGen/opt-disable.c

diff --git a/clang/test/CodeGen/opt-disable.c b/clang/test/CodeGen/opt-disable.c
new file mode 100644
index 0000000000000..ee90fc5620d65
--- /dev/null
+++ b/clang/test/CodeGen/opt-disable.c
@@ -0,0 +1,13 @@
+// REQUIRES: x86-registered-target
+
+// Make sure opt-bisect works through both pass managers
+//
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -O1 %s -mllvm -opt-disable="inlinerpass,SROAPass,machine code sinking" -mllvm -opt-disable-verbose -emit-obj -o /dev/null 2>&1 | FileCheck %s
+
+// CHECK-NOT: DISABLE: running pass InlinerPass
+// CHECK-NOT: DISABLE: running pass SROAPass
+// CHECK-NOT: DISABLE: running pass Machine code sinking
+// Make sure that legacy pass manager is running
+// CHECK: Instruction Selection
+
+int func(int a) { return a; }
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index be6aef3298b23..51c3a8040da9b 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include <limits>
+#include <set>
 
 namespace llvm {
 
@@ -82,6 +83,44 @@ class LLVM_ABI OptBisect : public OptPassGate {
   int LastBisectNum = 0;
 };
 
+/// This class implements a mechanism to disable passes and individual
+/// optimizations at compile time based on a command line option
+/// (-opt-disable) in order to study how single transformations, or
+/// combinations thereof, affect the IR.
+class LLVM_ABI OptDisable : public OptPassGate {
+public:
+  /// Default constructor. Initializes the state to empty set. The disabling
+  /// will be enabled by the cl::opt call-back when the command line option
+  /// is processed.
+  /// Clients should not instantiate this class directly.  All access should go
+  /// through LLVMContext.
+  OptDisable() = default;
+
+  virtual ~OptDisable() = default;
+
+  /// Checks the pass name to determine if the specified pass should run.
+  ///
+  /// The method prints the name of the pass, and whether or not the pass
+  /// will be executed. It returns true if the pass should run, i.e. if
+  /// its name is was not provided via command line.
+  ///
+  /// Most passes should not call this routine directly. Instead, it is called
+  /// through helper routines provided by the base classes of the pass. For
+  /// instance, function passes should call FunctionPass::skipFunction().
+  bool shouldRunPass(const StringRef PassName,
+                     StringRef IRDescription) override;
+
+  /// Parses the command line argument to extract the names of the passes
+  /// to be disabled. Multiple pass names can be provided with comma separation.
+  void setDisabled(StringRef Passes);
+
+  /// isEnabled() should return true before calling shouldRunPass().
+  bool isEnabled() const override { return !DisabledPasses.empty(); }
+
+private:
+  std::set<std::string> DisabledPasses = {};
+};
+
 /// Singleton instance of the OptBisect class, so multiple pass managers don't
 /// need to coordinate their uses of OptBisect.
 LLVM_ABI OptPassGate &getGlobalPassGate();
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index 559b199445366..aa1dbdfdbebd4 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -17,6 +17,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
+#include <sstream>
 
 using namespace llvm;
 
@@ -37,8 +38,8 @@ static cl::opt<bool> OptBisectVerbose(
     cl::desc("Show verbose output when opt-bisect-limit is set"), cl::Hidden,
     cl::init(true), cl::Optional);
 
-static void printPassMessage(const StringRef &Name, int PassNum,
-                             StringRef TargetDesc, bool Running) {
+static void printBisectPassMessage(const StringRef &Name, int PassNum,
+                                   StringRef TargetDesc, bool Running) {
   StringRef Status = Running ? "" : "NOT ";
   errs() << "BISECT: " << Status << "running pass "
          << "(" << PassNum << ") " << Name << " on " << TargetDesc << "\n";
@@ -51,10 +52,64 @@ bool OptBisect::shouldRunPass(const StringRef PassName,
   int CurBisectNum = ++LastBisectNum;
   bool ShouldRun = (BisectLimit == -1 || CurBisectNum <= BisectLimit);
   if (OptBisectVerbose)
-    printPassMessage(PassName, CurBisectNum, IRDescription, ShouldRun);
+    printBisectPassMessage(PassName, CurBisectNum, IRDescription, ShouldRun);
   return ShouldRun;
 }
 
 const int OptBisect::Disabled;
 
-OptPassGate &llvm::getGlobalPassGate() { return getOptBisector(); }
+static OptDisable &getOptDisabler() {
+  static OptDisable OptDisabler;
+  return OptDisabler;
+}
+
+static cl::opt<std::string> OptDisablePass(
+    "opt-disable", cl::Hidden, cl::init(""), cl::Optional,
+    cl::cb<void, std::string>([](std::string Passes) {
+      getOptDisabler().setDisabled(Passes);
+    }),
+    cl::desc("Optimization pass(es) to disable (comma separated)"));
+
+static cl::opt<bool>
+    OptDisableVerbose("opt-disable-verbose",
+                      cl::desc("Show verbose output when opt-disable is set"),
+                      cl::Hidden, cl::init(false), cl::Optional);
+
+static void printDisablePassMessage(const StringRef &Name, StringRef TargetDesc,
+                                    bool Running) {
+  StringRef Status = Running ? "" : "NOT ";
+  errs() << "DISABLE: " << Status << "running pass " << Name << " on "
+         << TargetDesc << "\n";
+}
+
+void OptDisable::setDisabled(StringRef Passes) {
+  std::stringstream StrStream(Passes.str());
+  std::string Token;
+
+  while (std::getline(StrStream, Token, ',')) {
+    if (!Token.empty()) {
+      std::transform(Token.begin(), Token.end(), Token.begin(), ::tolower);
+      DisabledPasses.insert(Token);
+    }
+  }
+}
+
+bool OptDisable::shouldRunPass(const StringRef PassName,
+                               StringRef IRDescription) {
+  assert(isEnabled());
+
+  std::string LowerName = PassName.str();
+  std::transform(LowerName.begin(), LowerName.end(), LowerName.begin(),
+                 ::tolower);
+
+  bool ShouldRun = DisabledPasses.find(LowerName) == DisabledPasses.end();
+  if (OptDisableVerbose)
+    printDisablePassMessage(PassName, IRDescription, ShouldRun);
+  return ShouldRun;
+}
+
+OptPassGate &llvm::getGlobalPassGate() {
+  if (getOptDisabler().isEnabled())
+    return getOptDisabler();
+  return getOptBisector();
+}



More information about the llvm-commits mailing list