[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
Thu Jul 3 01:28:24 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 1/8] 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();
+}
>From 5e79702e3bcee337ced764967d95cb3c684b7fa8 Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Mon, 23 Jun 2025 11:08:02 +0200
Subject: [PATCH 2/8] Partial solve of review comments
---
llvm/include/llvm/IR/OptBisect.h | 4 ++--
llvm/lib/IR/OptBisect.cpp | 21 +++++++--------------
2 files changed, 9 insertions(+), 16 deletions(-)
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index 51c3a8040da9b..20d332d78a8e5 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -15,9 +15,9 @@
#define LLVM_IR_OPTBISECT_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Compiler.h"
#include <limits>
-#include <set>
namespace llvm {
@@ -118,7 +118,7 @@ class LLVM_ABI OptDisable : public OptPassGate {
bool isEnabled() const override { return !DisabledPasses.empty(); }
private:
- std::set<std::string> DisabledPasses = {};
+ StringSet<> DisabledPasses = {};
};
/// Singleton instance of the OptBisect class, so multiple pass managers don't
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index aa1dbdfdbebd4..5adad939deab6 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -17,7 +17,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
-#include <sstream>
using namespace llvm;
@@ -83,14 +82,12 @@ static void printDisablePassMessage(const StringRef &Name, StringRef TargetDesc,
}
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);
- }
+ llvm::SmallVector<llvm::StringRef, 8> Tokens;
+
+ Passes.split(Tokens, ',', -1, false);
+
+ for (auto Token : Tokens) {
+ DisabledPasses.insert(Token.lower());
}
}
@@ -98,11 +95,7 @@ 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();
+ bool ShouldRun = !DisabledPasses.contains(PassName.lower());
if (OptDisableVerbose)
printDisablePassMessage(PassName, IRDescription, ShouldRun);
return ShouldRun;
>From 88625075b9854ad7fabe0007b0bc0b44f8d91f58 Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Mon, 23 Jun 2025 12:33:05 +0200
Subject: [PATCH 3/8] Fix vector usage
---
llvm/lib/IR/OptBisect.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index 5adad939deab6..a2591e07f0a00 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -65,6 +65,7 @@ static OptDisable &getOptDisabler() {
static cl::opt<std::string> OptDisablePass(
"opt-disable", cl::Hidden, cl::init(""), cl::Optional,
cl::cb<void, std::string>([](std::string Passes) {
+ getOptDisabler().initMap();
getOptDisabler().setDisabled(Passes);
}),
cl::desc("Optimization pass(es) to disable (comma separated)"));
@@ -82,7 +83,7 @@ static void printDisablePassMessage(const StringRef &Name, StringRef TargetDesc,
}
void OptDisable::setDisabled(StringRef Passes) {
- llvm::SmallVector<llvm::StringRef, 8> Tokens;
+ llvm::SmallVector<llvm::StringRef, 4> Tokens;
Passes.split(Tokens, ',', -1, false);
>From 9f95327b2b772d24b73f32164e8dad2e889d8847 Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Mon, 23 Jun 2025 19:23:15 +0200
Subject: [PATCH 4/8] Remove leftovers
---
llvm/lib/IR/OptBisect.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index a2591e07f0a00..db068633454b5 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -65,7 +65,6 @@ static OptDisable &getOptDisabler() {
static cl::opt<std::string> OptDisablePass(
"opt-disable", cl::Hidden, cl::init(""), cl::Optional,
cl::cb<void, std::string>([](std::string Passes) {
- getOptDisabler().initMap();
getOptDisabler().setDisabled(Passes);
}),
cl::desc("Optimization pass(es) to disable (comma separated)"));
>From 56405f21193edb70d4c55b14bc8fa54e7fb96b3e Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Fri, 27 Jun 2025 19:07:03 +0200
Subject: [PATCH 5/8] Converted to cl::list, renamed verbose flag, cleanup
---
llvm/include/llvm/IR/OptBisect.h | 15 ++++++++-------
llvm/lib/IR/OptBisect.cpp | 28 +++++++++++-----------------
2 files changed, 19 insertions(+), 24 deletions(-)
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index 20d332d78a8e5..83d3579225b1a 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -90,7 +90,7 @@ class LLVM_ABI OptBisect : public OptPassGate {
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
+ /// will be enabled by the cl::list call-back when the command line option
/// is processed.
/// Clients should not instantiate this class directly. All access should go
/// through LLVMContext.
@@ -100,9 +100,10 @@ class LLVM_ABI OptDisable : public OptPassGate {
/// 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.
+ /// 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
@@ -112,7 +113,7 @@ class LLVM_ABI OptDisable : 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 Passes);
+ void setDisabled(StringRef Pass);
/// isEnabled() should return true before calling shouldRunPass().
bool isEnabled() const override { return !DisabledPasses.empty(); }
@@ -121,8 +122,8 @@ class LLVM_ABI OptDisable : public OptPassGate {
StringSet<> DisabledPasses = {};
};
-/// Singleton instance of the OptBisect class, so multiple pass managers don't
-/// need to coordinate their uses of OptBisect.
+/// Singleton instance of the OptPassGate class, so multiple pass managers don't
+/// need to coordinate their uses of OptBisect and OptDisable.
LLVM_ABI OptPassGate &getGlobalPassGate();
} // end namespace llvm
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index db068633454b5..dc5637a31c08b 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -37,8 +37,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 printBisectPassMessage(const StringRef &Name, int PassNum,
- StringRef TargetDesc, bool Running) {
+static void printPassMessage(const StringRef &Name, int PassNum,
+ StringRef TargetDesc, bool Running) {
StringRef Status = Running ? "" : "NOT ";
errs() << "BISECT: " << Status << "running pass "
<< "(" << PassNum << ") " << Name << " on " << TargetDesc << "\n";
@@ -51,7 +51,7 @@ bool OptBisect::shouldRunPass(const StringRef PassName,
int CurBisectNum = ++LastBisectNum;
bool ShouldRun = (BisectLimit == -1 || CurBisectNum <= BisectLimit);
if (OptBisectVerbose)
- printBisectPassMessage(PassName, CurBisectNum, IRDescription, ShouldRun);
+ printPassMessage(PassName, CurBisectNum, IRDescription, ShouldRun);
return ShouldRun;
}
@@ -62,15 +62,15 @@ static OptDisable &getOptDisabler() {
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);
+static cl::list<std::string> OptDisablePasses(
+ "opt-disable", cl::Hidden, cl::CommaSeparated, cl::Optional,
+ cl::cb<void, std::string>([](std::string Pass) {
+ getOptDisabler().setDisabled(Pass);
}),
- cl::desc("Optimization pass(es) to disable (comma separated)"));
+ cl::desc("Optimization pass(es) to disable (comma-separated list)"));
static cl::opt<bool>
- OptDisableVerbose("opt-disable-verbose",
+ OptDisableVerbose("opt-disable-enable-verbosity",
cl::desc("Show verbose output when opt-disable is set"),
cl::Hidden, cl::init(false), cl::Optional);
@@ -81,14 +81,8 @@ static void printDisablePassMessage(const StringRef &Name, StringRef TargetDesc,
<< TargetDesc << "\n";
}
-void OptDisable::setDisabled(StringRef Passes) {
- llvm::SmallVector<llvm::StringRef, 4> Tokens;
-
- Passes.split(Tokens, ',', -1, false);
-
- for (auto Token : Tokens) {
- DisabledPasses.insert(Token.lower());
- }
+void OptDisable::setDisabled(StringRef Pass) {
+ DisabledPasses.insert(Pass.lower());
}
bool OptDisable::shouldRunPass(const StringRef PassName,
>From 731bcdf9b93eea1345a269257fe3ef6ee9cc37a0 Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Thu, 3 Jul 2025 01:41:22 +0200
Subject: [PATCH 6/8] Fixes, new test using opt in llvm/test
---
clang/test/CodeGen/opt-disable.c | 13 -----
llvm/include/llvm/IR/OptBisect.h | 15 ++----
llvm/lib/IR/OptBisect.cpp | 2 +-
llvm/test/Other/opt-disable.ll | 89 ++++++++++++++++++++++++++++++++
4 files changed, 93 insertions(+), 26 deletions(-)
delete mode 100644 clang/test/CodeGen/opt-disable.c
create mode 100644 llvm/test/Other/opt-disable.ll
diff --git a/clang/test/CodeGen/opt-disable.c b/clang/test/CodeGen/opt-disable.c
deleted file mode 100644
index ee90fc5620d65..0000000000000
--- a/clang/test/CodeGen/opt-disable.c
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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 a0a6d2532748f..d5b2ece1f84bb 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -89,27 +89,18 @@ class LLVM_ABI OptBisect : public OptPassGate {
/// 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::list 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.
///
- /// It returns true if the pass should run, i.e. if its name is was
+ /// 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
+ /// 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(const StringRef PassName,
- StringRef IRDescription) override;
+ 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.
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index f83241f9903e7..471a9cfdc1491 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -86,7 +86,7 @@ void OptDisable::setDisabled(StringRef Pass) {
}
bool OptDisable::shouldRunPass(const StringRef PassName,
- StringRef IRDescription) {
+ StringRef IRDescription) const {
assert(isEnabled());
bool ShouldRun = !DisabledPasses.contains(PassName.lower());
diff --git a/llvm/test/Other/opt-disable.ll b/llvm/test/Other/opt-disable.ll
new file mode 100644
index 0000000000000..0b1a0b08a5a8b
--- /dev/null
+++ b/llvm/test/Other/opt-disable.ll
@@ -0,0 +1,89 @@
+; RUN: opt -disable-output -disable-verify \
+; RUN: -opt-disable-enable-verbosity \
+; RUN: -passes=inferattrs -opt-disable=inferfunctionattrspass %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-MODULE-PASS
+; CHECK-MODULE-PASS: DISABLE: NOT running pass InferFunctionAttrsPass on [module]
+
+; RUN: opt -disable-output -disable-verify \
+; RUN: -opt-disable-enable-verbosity \
+; RUN: -passes=sroa -opt-disable=sroapass %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS
+; CHECK-FUNCTION-PASS: DISABLE: NOT running pass SROAPass on f1
+; CHECK-FUNCTION-PASS: DISABLE: NOT running pass SROAPass on f2
+; CHECK-FUNCTION-PASS: DISABLE: NOT running pass SROAPass on f3
+; CHECK-FUNCTION-PASS: DISABLE: NOT running pass SROAPass on f4
+
+; RUN: opt -disable-output -disable-verify \
+; RUN: -opt-disable=inferfunctionattrspass,PostOrderFunctionAttrsPass \
+; 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: DISABLE: NOT running pass InferFunctionAttrsPass on [module]
+; CHECK-MULTI-PASS: DISABLE: NOT running pass PostOrderFunctionAttrsPass on (f1)
+; CHECK-MULTI-PASS: DISABLE: running pass EarlyCSEPass on f1
+; CHECK-MULTI-PASS: DISABLE: NOT running pass PostOrderFunctionAttrsPass on (f2)
+; CHECK-MULTI-PASS: DISABLE: running pass EarlyCSEPass on f2
+; CHECK-MULTI-PASS: DISABLE: NOT running pass PostOrderFunctionAttrsPass on (f3)
+; CHECK-MULTI-PASS: DISABLE: running pass EarlyCSEPass on f3
+; CHECK-MULTI-PASS: DISABLE: NOT running pass PostOrderFunctionAttrsPass on (f4)
+; CHECK-MULTI-PASS: DISABLE: running pass EarlyCSEPass 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
+}
+
+; This function is here to verify that opt-bisect can skip all passes for
+; functions that contain lifetime intrinsics.
+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)
\ No newline at end of file
>From 12bb09c24b4ac487a48b59f8a3ee5ba3e7a61d50 Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Thu, 3 Jul 2025 01:53:33 +0200
Subject: [PATCH 7/8] Added test description
---
llvm/test/Other/opt-disable.ll | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/llvm/test/Other/opt-disable.ll b/llvm/test/Other/opt-disable.ll
index 0b1a0b08a5a8b..63d59c5792d3f 100644
--- a/llvm/test/Other/opt-disable.ll
+++ b/llvm/test/Other/opt-disable.ll
@@ -1,3 +1,7 @@
+; 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=inferfunctionattrspass %s 2>&1 \
@@ -68,8 +72,6 @@ bb.false:
ret i32 0
}
-; This function is here to verify that opt-bisect can skip all passes for
-; functions that contain lifetime intrinsics.
define void @f4(i1 %arg) {
entry:
%i = alloca i32, align 4
@@ -86,4 +88,4 @@ for.end:
ret void
}
-declare void @llvm.lifetime.start(i64, ptr nocapture)
\ No newline at end of file
+declare void @llvm.lifetime.start(i64, ptr nocapture)
>From 6cc429b97977b06208548b8cc839f46312b75178 Mon Sep 17 00:00:00 2001
From: Cristian Assaiante <cristianassaiante at outlook.com>
Date: Thu, 3 Jul 2025 10:28:05 +0200
Subject: [PATCH 8/8] Removing leftovers, solving nits
---
llvm/include/llvm/IR/OptBisect.h | 2 +-
llvm/lib/IR/OptBisect.cpp | 40 +++++++++++++++-----------------
2 files changed, 20 insertions(+), 22 deletions(-)
diff --git a/llvm/include/llvm/IR/OptBisect.h b/llvm/include/llvm/IR/OptBisect.h
index d5b2ece1f84bb..d813ae933d65e 100644
--- a/llvm/include/llvm/IR/OptBisect.h
+++ b/llvm/include/llvm/IR/OptBisect.h
@@ -99,7 +99,7 @@ class LLVM_ABI OptDisable : public OptPassGate {
/// 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,
+ bool shouldRunPass(StringRef PassName,
StringRef IRDescription) const override;
/// Parses the command line argument to extract the names of the passes
diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp
index 471a9cfdc1491..9f2a844f13762 100644
--- a/llvm/lib/IR/OptBisect.cpp
+++ b/llvm/lib/IR/OptBisect.cpp
@@ -25,6 +25,11 @@ 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(OptBisect::Disabled), cl::Optional,
cl::cb<void, int>([](int Limit) {
@@ -37,6 +42,18 @@ static cl::opt<bool> OptBisectVerbose(
cl::desc("Show verbose output when opt-bisect-limit is 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>([](std::string Pass) {
+ getOptDisabler().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 ";
@@ -55,29 +72,10 @@ bool OptBisect::shouldRunPass(StringRef PassName,
return ShouldRun;
}
-const int OptBisect::Disabled;
-
-static OptDisable &getOptDisabler() {
- static OptDisable OptDisabler;
- return OptDisabler;
-}
-
-static cl::list<std::string> OptDisablePasses(
- "opt-disable", cl::Hidden, cl::CommaSeparated, cl::Optional,
- cl::cb<void, std::string>([](std::string Pass) {
- getOptDisabler().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 printDisablePassMessage(const StringRef &Name, StringRef TargetDesc,
bool Running) {
StringRef Status = Running ? "" : "NOT ";
- errs() << "DISABLE: " << Status << "running pass " << Name << " on "
+ dbgs() << "DISABLE: " << Status << "running pass " << Name << " on "
<< TargetDesc << "\n";
}
@@ -85,7 +83,7 @@ void OptDisable::setDisabled(StringRef Pass) {
DisabledPasses.insert(Pass.lower());
}
-bool OptDisable::shouldRunPass(const StringRef PassName,
+bool OptDisable::shouldRunPass(StringRef PassName,
StringRef IRDescription) const {
assert(isEnabled());
More information about the llvm-commits
mailing list