[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