[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