[llvm] [OptBisect] Merge shouldRun logic of -opt-bisect and -opt-disable (PR #177122)

Cristian Assaiante via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 21 01:15:00 PST 2026


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

>From 76ff44a2aa3cf3398a62775f20541432f097bd8a Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Fri, 16 Jan 2026 18:31:21 +0100
Subject: [PATCH 1/2] [OptBisect] Merge opt-disable and opt-bisect logic

---
 llvm/include/llvm/IR/OptBisect.h          | 45 ++++---------
 llvm/lib/IR/OptBisect.cpp                 | 42 +++----------
 llvm/test/Other/opt-disable-and-bisect.ll | 77 +++++++++++++++++++++++
 llvm/test/Other/opt-disable.ll            | 32 +++++-----
 4 files changed, 112 insertions(+), 84 deletions(-)
 create mode 100644 llvm/test/Other/opt-disable-and-bisect.ll

diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index 77c866ab76d21..3089fc5922c26 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -39,9 +39,10 @@ class OptPassGate {
 };
 
 /// This class implements a mechanism to disable passes and individual
-/// optimizations at compile time based on a command line option
-/// (-opt-bisect) in order to perform a bisecting search for
-/// optimization-related problems.
+/// optimizations at compile time based on two command line options
+/// (-opt-bisect and -opt-disable) in order to perform a bisecting 
+/// search for optimization-related problems, and/or disable individual
+/// passes or combinations thereof.
 class LLVM_ABI OptBisect : public OptPassGate {
 public:
   /// Default constructor. Initializes the state to "disabled". The bisection
@@ -67,7 +68,9 @@ class LLVM_ABI OptBisect : public OptPassGate {
                      StringRef IRDescription) const override;
 
   /// isEnabled() should return true before calling shouldRunPass().
-  bool isEnabled() const override { return !BisectIntervals.empty(); }
+  bool isEnabled() const override { 
+    return !BisectIntervals.empty() || !DisabledPasses.empty();
+  }
 
   /// Set intervals directly from an IntervalList.
   void setIntervals(IntegerInclusiveIntervalUtils::IntervalList Intervals) {
@@ -80,38 +83,16 @@ class LLVM_ABI OptBisect : public OptPassGate {
     LastBisectNum = 0;
   }
 
-private:
-  mutable int LastBisectNum = 0;
-  IntegerInclusiveIntervalUtils::IntervalList BisectIntervals;
-};
-
-/// 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:
-  /// Checks the pass name to determine if the specified pass should run.
-  ///
-  /// It returns true if the pass should run, i.e. if its name is was
-  /// not provided via command line.
-  /// If -opt-disable-enable-verbosity is given, the method prints the
-  /// name of the pass, and whether or not the pass will be executed.
-  ///
-  /// 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(StringRef PassName,
-                     StringRef IRDescription) const 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 Pass);
-
-  /// isEnabled() should return true before calling shouldRunPass().
-  bool isEnabled() const override { return !DisabledPasses.empty(); }
+  void setDisabled(StringRef Pass) {
+    DisabledPasses.insert(Pass);
+  }
 
 private:
+  mutable int LastBisectNum = 0;
+  IntegerInclusiveIntervalUtils::IntervalList BisectIntervals;
+
   StringSet<> DisabledPasses = {};
 };
 
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index bb9fba66ddf95..2dce82374e640 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -28,11 +28,6 @@ static OptBisect &getOptBisector() {
   return OptBisector;
 }
 
-static OptDisable &getOptDisabler() {
-  static OptDisable OptDisabler;
-  return OptDisabler;
-}
-
 static cl::opt<int> OptBisectLimit(
     "opt-bisect-limit", cl::Hidden, cl::init(-1), cl::Optional,
     cl::cb<void, int>([](int Limit) {
@@ -80,21 +75,16 @@ static cl::opt<std::string> OptBisectIntervals(
 
 static cl::opt<bool> OptBisectVerbose(
     "opt-bisect-verbose",
-    cl::desc("Show verbose output when opt-bisect-limit is set"), cl::Hidden,
+    cl::desc("Show verbose output when opt-bisect-limit and/or opt-disable are set"), cl::Hidden,
     cl::init(true), cl::Optional);
 
 static cl::list<std::string> OptDisablePasses(
     "opt-disable", cl::Hidden, cl::CommaSeparated, cl::Optional,
     cl::cb<void, std::string>([](const std::string &Pass) {
-      getOptDisabler().setDisabled(Pass);
+      getOptBisector().setDisabled(Pass);
     }),
     cl::desc("Optimization pass(es) to disable (comma-separated list)"));
 
-static cl::opt<bool>
-    OptDisableVerbose("opt-disable-enable-verbosity",
-                      cl::desc("Show verbose output when opt-disable is set"),
-                      cl::Hidden, cl::init(false), cl::Optional);
-
 static void printPassMessage(StringRef Name, int PassNum, StringRef TargetDesc,
                              bool Running) {
   StringRef Status = Running ? "" : "NOT ";
@@ -109,35 +99,19 @@ bool OptBisect::shouldRunPass(StringRef PassName,
   int CurBisectNum = ++LastBisectNum;
 
   // Check if current pass number falls within any of the specified intervals.
-  bool ShouldRun =
+  // Since the bisector may be enabled by opt-disable, we also need to check if the
+  // BisectIntervals are empty.
+  bool ShouldRun = BisectIntervals.empty() ||
       IntegerInclusiveIntervalUtils::contains(BisectIntervals, CurBisectNum);
+    
+  // Also check if the pass is disabled via -opt-disable.
+  ShouldRun = ShouldRun && !DisabledPasses.contains(PassName);
 
   if (OptBisectVerbose)
     printPassMessage(PassName, CurBisectNum, IRDescription, ShouldRun);
   return ShouldRun;
 }
 
-static void printDisablePassMessage(const StringRef &Name, StringRef TargetDesc,
-                                    bool Running) {
-  StringRef Status = Running ? "" : "NOT ";
-  dbgs() << "OptDisable: " << Status << "running pass " << Name << " on "
-         << TargetDesc << "\n";
-}
-
-void OptDisable::setDisabled(StringRef Pass) { DisabledPasses.insert(Pass); }
-
-bool OptDisable::shouldRunPass(StringRef PassName,
-                               StringRef IRDescription) const {
-  assert(isEnabled());
-
-  const bool ShouldRun = !DisabledPasses.contains(PassName);
-  if (OptDisableVerbose)
-    printDisablePassMessage(PassName, IRDescription, ShouldRun);
-  return ShouldRun;
-}
-
 OptPassGate &llvm::getGlobalPassGate() {
-  if (getOptDisabler().isEnabled())
-    return getOptDisabler();
   return getOptBisector();
 }
diff --git a/llvm/test/Other/opt-disable-and-bisect.ll b/llvm/test/Other/opt-disable-and-bisect.ll
new file mode 100644
index 0000000000000..f14712f072b61
--- /dev/null
+++ b/llvm/test/Other/opt-disable-and-bisect.ll
@@ -0,0 +1,77 @@
+; This test uses the same IR functions of the opt-bisect test
+; and it checks if it correctly cohexists with the opt-disable flag.
+; Passes before opt-bisect-limit should be ran unless disabled 
+; by opt-disable. Later passes NOT run.
+
+; RUN: opt -disable-output -disable-verify \
+; RUN:     -opt-disable=inferattrs,function-attrs  \
+; RUN:     -opt-bisect-limit=6 \
+; RUN:     -passes='inferattrs,cgscc(function-attrs,function(early-cse))' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-MULTI-PASS
+; CHECK-MULTI-PASS: BISECT: NOT running pass (1) inferattrs on [module]
+; CHECK-MULTI-PASS: BISECT: NOT running pass (2) function-attrs on (f1)
+; CHECK-MULTI-PASS: BISECT: running pass (3) early-cse on f1
+; CHECK-MULTI-PASS: BISECT: NOT running pass (4) function-attrs on (f2)
+; CHECK-MULTI-PASS: BISECT: running pass (5) early-cse on f2
+; CHECK-MULTI-PASS: BISECT: NOT running pass (6) function-attrs on (f3)
+; CHECK-MULTI-PASS: BISECT: NOT running pass (7) early-cse on f3
+; CHECK-MULTI-PASS: BISECT: NOT running pass (8) function-attrs on (f4)
+; CHECK-MULTI-PASS: BISECT: NOT running pass (9) early-cse on f4
+
+declare i32 @g()
+
+define void @f1(i1 %arg) {
+entry:
+  br label %loop.0
+loop.0:
+  br i1 %arg, label %loop.0.0, label %loop.1
+loop.0.0:
+  br i1 %arg, label %loop.0.0, label %loop.0.1
+loop.0.1:
+  br i1 %arg, label %loop.0.1, label %loop.0
+loop.1:
+  br i1 %arg, label %loop.1, label %loop.1.bb1
+loop.1.bb1:
+  br i1 %arg, label %loop.1, label %loop.1.bb2
+loop.1.bb2:
+  br i1 %arg, label %end, label %loop.1.0
+loop.1.0:
+  br i1 %arg, label %loop.1.0, label %loop.1
+end:
+  ret void
+}
+
+define i32 @f2() {
+entry:
+  ret i32 0
+}
+
+define i32 @f3() {
+entry:
+  %temp = call i32 @g()
+  %icmp = icmp ugt i32 %temp, 2
+  br i1 %icmp, label %bb.true, label %bb.false
+bb.true:
+  %temp2 = call i32 @f2()
+  ret i32 %temp2
+bb.false:
+  ret i32 0
+}
+
+define void @f4(i1 %arg) {
+entry:
+  %i = alloca i32, align 4
+  call void @llvm.lifetime.start(i64 4, ptr %i)
+  br label %for.cond
+
+for.cond:
+  br i1 %arg, label %for.body, label %for.end
+
+for.body:
+  br label %for.cond
+
+for.end:
+  ret void
+}
+
+declare void @llvm.lifetime.start(i64, ptr nocapture)
diff --git a/llvm/test/Other/opt-disable.ll b/llvm/test/Other/opt-disable.ll
index 4506042215cbf..c54d2bb2f2019 100644
--- a/llvm/test/Other/opt-disable.ll
+++ b/llvm/test/Other/opt-disable.ll
@@ -1,36 +1,32 @@
 ; This test uses the same IR functions of the opt-bisect test
 ; but it checks the correctness of the -opt-disable flag.
-; -opt-disable-enable-verbosity is required to have output.
 
 ; RUN: opt -disable-output -disable-verify \
-; RUN:     -opt-disable-enable-verbosity \
 ; RUN:     -passes=inferattrs -opt-disable=inferattrs %s 2>&1 \
 ; RUN:     | FileCheck %s --check-prefix=CHECK-MODULE-PASS
-; CHECK-MODULE-PASS: OptDisable: NOT running pass inferattrs on [module]
+; CHECK-MODULE-PASS: BISECT: NOT running pass (1) inferattrs on [module]
 
 ; RUN: opt -disable-output -disable-verify \
-; RUN:     -opt-disable-enable-verbosity \
 ; RUN:     -passes=sroa -opt-disable=sroa %s 2>&1 \
 ; RUN:     | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS
-; CHECK-FUNCTION-PASS: OptDisable: NOT running pass sroa on f1
-; CHECK-FUNCTION-PASS: OptDisable: NOT running pass sroa on f2
-; CHECK-FUNCTION-PASS: OptDisable: NOT running pass sroa on f3
-; CHECK-FUNCTION-PASS: OptDisable: NOT running pass sroa on f4
+; CHECK-FUNCTION-PASS: BISECT: NOT running pass (1) sroa on f1
+; CHECK-FUNCTION-PASS: BISECT: NOT running pass (2) sroa on f2
+; CHECK-FUNCTION-PASS: BISECT: NOT running pass (3) sroa on f3
+; CHECK-FUNCTION-PASS: BISECT: NOT running pass (4) sroa on f4
 
 ; RUN: opt -disable-output -disable-verify \
 ; RUN:     -opt-disable=inferattrs,function-attrs  \
-; RUN:     -opt-disable-enable-verbosity \
 ; RUN:     -passes='inferattrs,cgscc(function-attrs,function(early-cse))' %s 2>&1 \
 ; RUN:     | FileCheck %s --check-prefix=CHECK-MULTI-PASS
-; CHECK-MULTI-PASS: OptDisable: NOT running pass inferattrs on [module]
-; CHECK-MULTI-PASS: OptDisable: NOT running pass function-attrs on (f1)
-; CHECK-MULTI-PASS: OptDisable: running pass early-cse on f1
-; CHECK-MULTI-PASS: OptDisable: NOT running pass function-attrs on (f2)
-; CHECK-MULTI-PASS: OptDisable: running pass early-cse on f2
-; CHECK-MULTI-PASS: OptDisable: NOT running pass function-attrs on (f3)
-; CHECK-MULTI-PASS: OptDisable: running pass early-cse on f3
-; CHECK-MULTI-PASS: OptDisable: NOT running pass function-attrs on (f4)
-; CHECK-MULTI-PASS: OptDisable: running pass early-cse on f4
+; CHECK-MULTI-PASS: BISECT: NOT running pass (1) inferattrs on [module]
+; CHECK-MULTI-PASS: BISECT: NOT running pass (2) function-attrs on (f1)
+; CHECK-MULTI-PASS: BISECT: running pass (3) early-cse on f1
+; CHECK-MULTI-PASS: BISECT: NOT running pass (4) function-attrs on (f2)
+; CHECK-MULTI-PASS: BISECT: running pass (5) early-cse on f2
+; CHECK-MULTI-PASS: BISECT: NOT running pass (6) function-attrs on (f3)
+; CHECK-MULTI-PASS: BISECT: running pass (7) early-cse on f3
+; CHECK-MULTI-PASS: BISECT: NOT running pass (8) function-attrs on (f4)
+; CHECK-MULTI-PASS: BISECT: running pass (9) early-cse on f4
 
 declare i32 @g()
 

>From 9e25c2281fdfd139e4e1d9d108777839150bf68c Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Wed, 21 Jan 2026 10:14:44 +0100
Subject: [PATCH 2/2] Fix clang-format errors

---
 llvm/include/llvm/IR/OptBisect.h |  8 +++-----
 llvm/lib/IR/OptBisect.cpp        | 14 +++++++-------
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index 3089fc5922c26..7c056ceb35ca5 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -40,7 +40,7 @@ class OptPassGate {
 
 /// This class implements a mechanism to disable passes and individual
 /// optimizations at compile time based on two command line options
-/// (-opt-bisect and -opt-disable) in order to perform a bisecting 
+/// (-opt-bisect and -opt-disable) in order to perform a bisecting
 /// search for optimization-related problems, and/or disable individual
 /// passes or combinations thereof.
 class LLVM_ABI OptBisect : public OptPassGate {
@@ -68,7 +68,7 @@ class LLVM_ABI OptBisect : public OptPassGate {
                      StringRef IRDescription) const override;
 
   /// isEnabled() should return true before calling shouldRunPass().
-  bool isEnabled() const override { 
+  bool isEnabled() const override {
     return !BisectIntervals.empty() || !DisabledPasses.empty();
   }
 
@@ -85,9 +85,7 @@ class LLVM_ABI OptBisect : public OptPassGate {
 
   /// 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 Pass) {
-    DisabledPasses.insert(Pass);
-  }
+  void setDisabled(StringRef Pass) { DisabledPasses.insert(Pass); }
 
 private:
   mutable int LastBisectNum = 0;
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index 2dce82374e640..926bab2154ee0 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -75,8 +75,9 @@ static cl::opt<std::string> OptBisectIntervals(
 
 static cl::opt<bool> OptBisectVerbose(
     "opt-bisect-verbose",
-    cl::desc("Show verbose output when opt-bisect-limit and/or opt-disable are set"), cl::Hidden,
-    cl::init(true), cl::Optional);
+    cl::desc(
+        "Show verbose output when opt-bisect-limit and/or opt-disable are set"),
+    cl::Hidden, cl::init(true), cl::Optional);
 
 static cl::list<std::string> OptDisablePasses(
     "opt-disable", cl::Hidden, cl::CommaSeparated, cl::Optional,
@@ -101,9 +102,10 @@ bool OptBisect::shouldRunPass(StringRef PassName,
   // Check if current pass number falls within any of the specified intervals.
   // Since the bisector may be enabled by opt-disable, we also need to check if the
   // BisectIntervals are empty.
-  bool ShouldRun = BisectIntervals.empty() ||
+  bool ShouldRun =
+      BisectIntervals.empty() ||
       IntegerInclusiveIntervalUtils::contains(BisectIntervals, CurBisectNum);
-    
+
   // Also check if the pass is disabled via -opt-disable.
   ShouldRun = ShouldRun && !DisabledPasses.contains(PassName);
 
@@ -112,6 +114,4 @@ bool OptBisect::shouldRunPass(StringRef PassName,
   return ShouldRun;
 }
 
-OptPassGate &llvm::getGlobalPassGate() {
-  return getOptBisector();
-}
+OptPassGate &llvm::getGlobalPassGate() { return getOptBisector(); }



More information about the llvm-commits mailing list