
This commit adds a new pass gate that allows selective disabling of one or more passes via the clang command line using the `-opt-disable` option. Passes to be disabled should be specified as a comma-separated list of their names. The implementation resides in the same file as the bisection tool. The `getGlobalPassGate()` function returns the currently enabled gate. Example: `-opt-disable="PassA,PassB"` Pass names are matched using case-insensitive comparisons. However, note that special characters, including spaces, must be included exactly as they appear in the pass names. Additionally, a `-opt-disable-enable-verbosity` flag has been introduced to enable verbose output when this functionality is in use. When enabled, it prints the status of all passes (either running or NOT running), similar to the default behavior of `-opt-bisect-limit`. This flag is disabled by default, which is the opposite of the `-opt-bisect-verbose` flag (which defaults to enabled). To validate this functionality, a test file has also been provided. It reuses the same infrastructure as the opt-bisect test, but disables three specific passes and checks the output to ensure the expected behavior. --------- Co-authored-by: Nikita Popov <github@npopov.com>
99 lines
3.4 KiB
C++
99 lines
3.4 KiB
C++
//===- llvm/IR/OptBisect/Bisect.cpp - LLVM Bisect support -----------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
/// \file
|
|
/// This file implements support for a bisecting optimizations based on a
|
|
/// command line option.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/IR/OptBisect.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <cassert>
|
|
|
|
using namespace llvm;
|
|
|
|
static OptBisect &getOptBisector() {
|
|
static OptBisect OptBisector;
|
|
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) {
|
|
getOptBisector().setLimit(Limit);
|
|
}),
|
|
cl::desc("Maximum optimization to perform"));
|
|
|
|
static cl::opt<bool> OptBisectVerbose(
|
|
"opt-bisect-verbose",
|
|
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 ";
|
|
errs() << "BISECT: " << Status << "running pass (" << PassNum << ") " << Name
|
|
<< " on " << TargetDesc << '\n';
|
|
}
|
|
|
|
bool OptBisect::shouldRunPass(StringRef PassName,
|
|
StringRef IRDescription) const {
|
|
assert(isEnabled());
|
|
|
|
int CurBisectNum = ++LastBisectNum;
|
|
bool ShouldRun = (BisectLimit == -1 || CurBisectNum <= BisectLimit);
|
|
if (OptBisectVerbose)
|
|
printPassMessage(PassName, CurBisectNum, IRDescription, ShouldRun);
|
|
return ShouldRun;
|
|
}
|
|
|
|
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();
|
|
}
|