Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
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>([](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() << "DISABLE: " << Status << "running pass " << Name << " on "
<< TargetDesc << "\n";
}

void OptDisable::setDisabled(StringRef Pass) {
DisabledPasses.insert(Pass.lower());
}

bool OptDisable::shouldRunPass(StringRef PassName,
StringRef IRDescription) const {
assert(isEnabled());

bool ShouldRun = !DisabledPasses.contains(PassName.lower());
if (OptDisableVerbose)
printDisablePassMessage(PassName, IRDescription, ShouldRun);
return ShouldRun;
}

OptPassGate &llvm::getGlobalPassGate() {
if (getOptDisabler().isEnabled())
return getOptDisabler();
return getOptBisector();
}
91 changes: 91 additions & 0 deletions llvm/test/Other/opt-disable.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
; 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 \
; 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
}

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)
Loading