Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ab60634
Adding -opt-disable and a test for it
cristianassaiante Jun 20, 2025
aea7b99
Merge branch 'llvm:main' into opt-disable
cristianassaiante Jun 20, 2025
5e79702
Partial solve of review comments
cristianassaiante Jun 23, 2025
8862507
Fix vector usage
cristianassaiante Jun 23, 2025
9f95327
Remove leftovers
cristianassaiante Jun 23, 2025
56405f2
Converted to cl::list, renamed verbose flag, cleanup
cristianassaiante Jun 27, 2025
ed3dd9f
Merge branch 'main' into opt-disable
cristianassaiante Jul 1, 2025
731bcdf
Fixes, new test using opt in llvm/test
cristianassaiante Jul 2, 2025
12bb09c
Added test description
cristianassaiante Jul 2, 2025
6cc429b
Removing leftovers, solving nits
cristianassaiante Jul 3, 2025
825b711
Update llvm/lib/IR/OptBisect.cpp
cristianassaiante Jul 9, 2025
284a13f
Short names with both NPM and Legacy, updated test, solved nits
cristianassaiante Jul 10, 2025
39b85f1
Update failing opt-bisect test
cristianassaiante Jul 10, 2025
3b766f2
Apply suggestions from code review
cristianassaiante Jul 10, 2025
2cb80ea
Removing virtual, cleaning format
cristianassaiante Jul 10, 2025
0f13dab
Format check fail leftover
cristianassaiante Jul 10, 2025
9b696eb
Full case sensitivity, leftover this
cristianassaiante Jul 11, 2025
8282416
Merge branch 'main' into opt-disable
cristianassaiante Jul 11, 2025
098431a
Update llvm/include/llvm/Pass.h
cristianassaiante Jul 16, 2025
3774261
Merge branch 'main' into opt-disable
cristianassaiante Jul 16, 2025
08341fd
Format check fix
cristianassaiante Jul 16, 2025
82ffe52
Update clang bisect test with new output format
cristianassaiante Jul 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions llvm/include/llvm/IR/OptBisect.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define LLVM_IR_OPTBISECT_H

#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Compiler.h"
#include <limits>

Expand Down Expand Up @@ -82,8 +83,38 @@ class LLVM_ABI OptBisect : public OptPassGate {
mutable int LastBisectNum = 0;
};

/// Singleton instance of the OptBisect class, so multiple pass managers don't
/// need to coordinate their uses of OptBisect.
/// 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(); }

private:
StringSet<> DisabledPasses = {};
};

/// 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
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/Pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ class LLVM_ABI Pass {
/// Registration templates, but can be overloaded directly.
virtual StringRef getPassName() const;

/// Return a nice clean name for a pass
/// corresponding to that used to enable the pass in opt
StringRef getPassArgument() const;

/// getPassID - Return the PassID number that corresponds to this pass.
AnalysisID getPassID() const {
return PassID;
Expand Down
44 changes: 43 additions & 1 deletion llvm/lib/IR/OptBisect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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>([](const 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 ";
Expand All @@ -55,4 +72,29 @@ bool OptBisect::shouldRunPass(StringRef PassName,
return ShouldRun;
}

OptPassGate &llvm::getGlobalPassGate() { return getOptBisector(); }
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();
}
26 changes: 22 additions & 4 deletions llvm/lib/IR/Pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,12 @@ static std::string getDescription(const Module &M) {

bool ModulePass::skipModule(const Module &M) const {
const OptPassGate &Gate = M.getContext().getOptPassGate();
return Gate.isEnabled() &&
!Gate.shouldRunPass(this->getPassName(), getDescription(M));

StringRef PassName = getPassArgument();
if (PassName.empty())
PassName = this->getPassName();

return Gate.isEnabled() && !Gate.shouldRunPass(PassName, getDescription(M));
}

bool Pass::mustPreserveAnalysisID(char &AID) const {
Expand All @@ -86,6 +90,16 @@ StringRef Pass::getPassName() const {
return "Unnamed pass: implement Pass::getPassName()";
}

/// getPassArgument - Return a nice clean name for a pass
/// corresponding to that used to enable the pass in opt
StringRef Pass::getPassArgument() const {
AnalysisID AID = getPassID();
const PassInfo *PI = Pass::lookupPassInfo(AID);
if (PI)
return PI->getPassArgument();
return "";
}

void Pass::preparePassManager(PMStack &) {
// By default, don't do anything.
}
Expand Down Expand Up @@ -173,8 +187,12 @@ static std::string getDescription(const Function &F) {

bool FunctionPass::skipFunction(const Function &F) const {
OptPassGate &Gate = F.getContext().getOptPassGate();
if (Gate.isEnabled() &&
!Gate.shouldRunPass(this->getPassName(), getDescription(F)))

StringRef PassName = getPassArgument();
if (PassName.empty())
PassName = this->getPassName();

if (Gate.isEnabled() && !Gate.shouldRunPass(PassName, getDescription(F)))
return true;

if (F.hasOptNone()) {
Expand Down
10 changes: 7 additions & 3 deletions llvm/lib/Passes/StandardInstrumentations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1078,9 +1078,13 @@ void OptPassGateInstrumentation::registerCallbacks(
if (!PassGate.isEnabled())
return;

PIC.registerShouldRunOptionalPassCallback([this](StringRef PassName, Any IR) {
return this->shouldRun(PassName, IR);
});
PIC.registerShouldRunOptionalPassCallback(
[this, &PIC](StringRef ClassName, Any IR) {
StringRef PassName = PIC.getPassNameForClassName(ClassName);
if (PassName.empty())
return this->shouldRun(ClassName, IR);
return this->shouldRun(PassName, IR);
});
}

raw_ostream &PrintPassInstrumentation::print() {
Expand Down
76 changes: 38 additions & 38 deletions llvm/test/Other/opt-bisect-new-pass-manager.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,84 +11,84 @@
; RUN: opt -disable-output -disable-verify \
; RUN: -passes=inferattrs -opt-bisect-limit=-1 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-MODULE-PASS
; CHECK-MODULE-PASS: BISECT: running pass (1) InferFunctionAttrsPass on [module]
; CHECK-MODULE-PASS: BISECT: running pass (1) inferattrs on [module]

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=inferattrs -opt-bisect-limit=0 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-MODULE-PASS
; CHECK-LIMIT-MODULE-PASS: BISECT: NOT running pass (1) InferFunctionAttrsPass on [module]
; CHECK-LIMIT-MODULE-PASS: BISECT: NOT running pass (1) inferattrs on [module]

; RUN: opt -disable-output -debug-pass-manager \
; RUN: -passes=inferattrs -opt-bisect-limit=-1 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-REQUIRED-PASS
; CHECK-REQUIRED-PASS: BISECT: running pass (1) InferFunctionAttrsPass on [module]
; CHECK-REQUIRED-PASS: BISECT: running pass (1) inferattrs on [module]
; CHECK-REQUIRED-PASS-NOT: BISECT: {{.*}}VerifierPass
; CHECK-REQUIRED-PASS: Running pass: VerifierPass

; RUN: opt -disable-output -debug-pass-manager \
; RUN: -passes=inferattrs -opt-bisect-limit=0 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-REQUIRED-PASS
; CHECK-LIMIT-REQUIRED-PASS: BISECT: NOT running pass (1) InferFunctionAttrsPass on [module]
; CHECK-LIMIT-REQUIRED-PASS: BISECT: NOT running pass (1) inferattrs on [module]
; CHECK-LIMIT-REQUIRED-PASS-NOT: BISECT: {{.*}}VerifierPass
; CHECK-LIMIT-REQUIRED-PASS: Running pass: VerifierPass

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=early-cse -opt-bisect-limit=-1 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS
; CHECK-FUNCTION-PASS: BISECT: running pass (1) EarlyCSEPass on f1
; CHECK-FUNCTION-PASS: BISECT: running pass (2) EarlyCSEPass on f2
; CHECK-FUNCTION-PASS: BISECT: running pass (3) EarlyCSEPass on f3
; CHECK-FUNCTION-PASS: BISECT: running pass (4) EarlyCSEPass on f4
; CHECK-FUNCTION-PASS: BISECT: running pass (1) early-cse on f1
; CHECK-FUNCTION-PASS: BISECT: running pass (2) early-cse on f2
; CHECK-FUNCTION-PASS: BISECT: running pass (3) early-cse on f3
; CHECK-FUNCTION-PASS: BISECT: running pass (4) early-cse on f4

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=early-cse -opt-bisect-limit=2 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-FUNCTION-PASS
; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (1) EarlyCSEPass on f1
; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (2) EarlyCSEPass on f2
; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (3) EarlyCSEPass on f3
; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (4) EarlyCSEPass on f4
; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (1) early-cse on f1
; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (2) early-cse on f2
; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (3) early-cse on f3
; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (4) early-cse on f4

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=function-attrs -opt-bisect-limit=-1 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-CGSCC-PASS
; CHECK-CGSCC-PASS: BISECT: running pass (1) PostOrderFunctionAttrsPass on (f1)
; CHECK-CGSCC-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on (f2)
; CHECK-CGSCC-PASS: BISECT: running pass (3) PostOrderFunctionAttrsPass on (f3)
; CHECK-CGSCC-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on (f4)
; CHECK-CGSCC-PASS: BISECT: running pass (1) function-attrs on (f1)
; CHECK-CGSCC-PASS: BISECT: running pass (2) function-attrs on (f2)
; CHECK-CGSCC-PASS: BISECT: running pass (3) function-attrs on (f3)
; CHECK-CGSCC-PASS: BISECT: running pass (4) function-attrs on (f4)

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=function-attrs -opt-bisect-limit=3 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-CGSCC-PASS
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (1) PostOrderFunctionAttrsPass on (f1)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on (f2)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (3) PostOrderFunctionAttrsPass on (f3)
; CHECK-LIMIT-CGSCC-PASS: BISECT: NOT running pass (4) PostOrderFunctionAttrsPass on (f4)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (1) function-attrs on (f1)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (2) function-attrs on (f2)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (3) function-attrs on (f3)
; CHECK-LIMIT-CGSCC-PASS: BISECT: NOT running pass (4) function-attrs on (f4)

; RUN: opt -disable-output -disable-verify -opt-bisect-limit=-1 \
; RUN: -passes='inferattrs,cgscc(function-attrs,function(early-cse))' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-MULTI-PASS
; CHECK-MULTI-PASS: BISECT: running pass (1) InferFunctionAttrsPass on [module]
; CHECK-MULTI-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on (f1)
; CHECK-MULTI-PASS: BISECT: running pass (3) EarlyCSEPass on f1
; CHECK-MULTI-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on (f2)
; CHECK-MULTI-PASS: BISECT: running pass (5) EarlyCSEPass on f2
; CHECK-MULTI-PASS: BISECT: running pass (6) PostOrderFunctionAttrsPass on (f3)
; CHECK-MULTI-PASS: BISECT: running pass (7) EarlyCSEPass on f3
; CHECK-MULTI-PASS: BISECT: running pass (8) PostOrderFunctionAttrsPass on (f4)
; CHECK-MULTI-PASS: BISECT: running pass (9) EarlyCSEPass on f4
; CHECK-MULTI-PASS: BISECT: running pass (1) inferattrs on [module]
; CHECK-MULTI-PASS: BISECT: running pass (2) function-attrs on (f1)
; CHECK-MULTI-PASS: BISECT: running pass (3) early-cse on f1
; CHECK-MULTI-PASS: BISECT: running pass (4) function-attrs on (f2)
; CHECK-MULTI-PASS: BISECT: running pass (5) early-cse on f2
; CHECK-MULTI-PASS: BISECT: running pass (6) function-attrs on (f3)
; CHECK-MULTI-PASS: BISECT: running pass (7) early-cse on f3
; CHECK-MULTI-PASS: BISECT: running pass (8) function-attrs on (f4)
; CHECK-MULTI-PASS: BISECT: running pass (9) early-cse on f4

; RUN: opt -disable-output -disable-verify -opt-bisect-limit=7 \
; RUN: -passes='inferattrs,cgscc(function-attrs,function(early-cse))' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-MULTI-PASS
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (1) InferFunctionAttrsPass on [module]
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on (f1)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (3) EarlyCSEPass on f1
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on (f2)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (5) EarlyCSEPass on f2
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (6) PostOrderFunctionAttrsPass on (f3)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (7) EarlyCSEPass on f3
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (8) PostOrderFunctionAttrsPass on (f4)
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (9) EarlyCSEPass on f4
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (1) inferattrs on [module]
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (2) function-attrs on (f1)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (3) early-cse on f1
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (4) function-attrs on (f2)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (5) early-cse on f2
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (6) function-attrs on (f3)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (7) early-cse on f3
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (8) function-attrs on (f4)
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (9) early-cse on f4

; Make sure we don't skip writing the output to stdout.
; RUN: opt %s -opt-bisect-limit=0 -passes=early-cse | opt -S | FileCheck %s -check-prefix=CHECK-OUTPUT
Expand Down
Loading