Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
13 changes: 13 additions & 0 deletions clang/test/CodeGen/opt-disable.c
Original file line number Diff line number Diff line change
@@ -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; }
39 changes: 39 additions & 0 deletions llvm/include/llvm/IR/OptBisect.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include <limits>
#include <set>

namespace llvm {

Expand Down Expand Up @@ -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();
Expand Down
63 changes: 59 additions & 4 deletions llvm/lib/IR/OptBisect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <sstream>

using namespace llvm;

Expand All @@ -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";
Expand All @@ -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();
}