4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/MachineScheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ ScheduleDAGInstrs *PostMachineScheduler::createPostMachineScheduler() {
/// design would be to split blocks at scheduling boundaries, but LLVM has a
/// general bias against block splitting purely for implementation simplicity.
bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) {
if (skipOptnoneFunction(*mf.getFunction()))
if (skipFunction(*mf.getFunction()))
return false;

if (EnableMachineSched.getNumOccurrences()) {
Expand Down Expand Up @@ -357,7 +357,7 @@ bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) {
}

bool PostMachineScheduler::runOnMachineFunction(MachineFunction &mf) {
if (skipOptnoneFunction(*mf.getFunction()))
if (skipFunction(*mf.getFunction()))
return false;

if (EnablePostRAMachineSched.getNumOccurrences()) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/MachineSink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ MachineSinking::AllUsesDominatedByBlock(unsigned Reg,
}

bool MachineSinking::runOnMachineFunction(MachineFunction &MF) {
if (skipOptnoneFunction(*MF.getFunction()))
if (skipFunction(*MF.getFunction()))
return false;

DEBUG(dbgs() << "******** Machine Sinking ********\n");
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/OptimizePHIs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ INITIALIZE_PASS(OptimizePHIs, "opt-phis",
"Optimize machine instruction PHIs", false, false)

bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
if (skipOptnoneFunction(*Fn.getFunction()))
if (skipFunction(*Fn.getFunction()))
return false;

MRI = &Fn.getRegInfo();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/PeepholeOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1471,7 +1471,7 @@ bool PeepholeOptimizer::foldRedundantNAPhysCopy(
}

bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
if (skipOptnoneFunction(*MF.getFunction()))
if (skipFunction(*MF.getFunction()))
return false;

DEBUG(dbgs() << "********** PEEPHOLE OPTIMIZER **********\n");
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/PostRASchedulerList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ bool PostRAScheduler::enablePostRAScheduler(
}

bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
if (skipOptnoneFunction(*Fn.getFunction()))
if (skipFunction(*Fn.getFunction()))
return false;

TII = Fn.getSubtarget().getInstrInfo();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/StackColoring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ void StackColoring::expungeSlotMap(DenseMap<int, int> &SlotRemap,
}

bool StackColoring::runOnMachineFunction(MachineFunction &Func) {
if (skipOptnoneFunction(*Func.getFunction()))
if (skipFunction(*Func.getFunction()))
return false;

DEBUG(dbgs() << "********** Stack Coloring **********\n"
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/TailDuplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ INITIALIZE_PASS(TailDuplicatePass, "tailduplication", "Tail Duplication", false,
false)

bool TailDuplicatePass::runOnMachineFunction(MachineFunction &MF) {
if (skipOptnoneFunction(*MF.getFunction()))
if (skipFunction(*MF.getFunction()))
return false;

auto MMI = getAnalysisIfAvailable<MachineModuleInfo>();
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ add_llvm_library(LLVMCore
Module.cpp
ModuleSummaryIndex.cpp
Operator.cpp
OptBisect.cpp
Pass.cpp
PassManager.cpp
PassRegistry.cpp
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/IR/LLVMContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,7 @@ void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); }
void LLVMContext::setDiscardValueNames(bool Discard) {
pImpl->DiscardValueNames = Discard;
}

OptBisect &LLVMContext::getOptBisect() {
return pImpl->getOptBisect();
}
18 changes: 18 additions & 0 deletions llvm/lib/IR/LLVMContextImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "llvm/IR/Attributes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Support/ManagedStatic.h"
#include <algorithm>
using namespace llvm;

Expand Down Expand Up @@ -232,3 +234,19 @@ void GetElementPtrConstantExpr::anchor() { }

void CompareConstantExpr::anchor() { }

/// Singleton instance of the OptBisect class.
///
/// This singleton is accessed via the LLVMContext::getOptBisect() function. It
/// provides a mechanism to disable passes and individual optimizations at
/// compile time based on a command line option (-opt-bisect-limit) in order to
/// perform a bisecting search for optimization-related problems.
///
/// Even if multiple LLVMContext objects are created, they will all return the
/// same instance of OptBisect in order to provide a single bisect count. Any
/// code that uses the OptBisect object should be serialized when bisection is
/// enabled in order to enable a consistent bisect count.
static ManagedStatic<OptBisect> OptBisector;

OptBisect &LLVMContextImpl::getOptBisect() {
return *OptBisector;
}
4 changes: 4 additions & 0 deletions llvm/lib/IR/LLVMContextImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,10 @@ class LLVMContextImpl {

/// Destroy the ConstantArrays if they are not used.
void dropTriviallyDeadConstantArrays();

/// \brief Access the object which manages optimization bisection for failure
/// analysis.
OptBisect &getOptBisect();
};

}
Expand Down
176 changes: 176 additions & 0 deletions llvm/lib/IR/OptBisect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
//===------- llvm/IR/OptBisect/Bisect.cpp - LLVM Bisect support --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements support for a bisecting optimizations based on a
/// command line option.
///
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
cl::init(INT_MAX), cl::Optional,
cl::desc("Maximum optimization to perform"));

OptBisect::OptBisect() {
BisectEnabled = OptBisectLimit != INT_MAX;
}

static void printPassMessage(const StringRef &Name, int PassNum,
StringRef TargetDesc, bool Running) {
StringRef Status = Running ? "" : "NOT ";
errs() << "BISECT: " << Status << "running pass "
<< "(" << PassNum << ") " << Name << " on " << TargetDesc << "\n";
}

static void printCaseMessage(int CaseNum, StringRef Msg, bool Running) {
if (Running)
errs() << "BISECT: running case (";
else
errs() << "BISECT: NOT running case (";
errs() << CaseNum << "): " << Msg << "\n";
}

static std::string getDescription(const Module &M) {
return "module (" + M.getName().str() + ")";
}

static std::string getDescription(const Function &F) {
return "function (" + F.getName().str() + ")";
}

static std::string getDescription(const BasicBlock &BB) {
return "basic block (" + BB.getName().str() + ") in function (" +
BB.getParent()->getName().str() + ")";
}

static std::string getDescription(const Loop &L) {
// FIXME: I'd like to be able to provide a better description here, but
// calling L->getHeader() would introduce a new dependency on the
// LLVMCore library.
return "loop";
}

static std::string getDescription(const CallGraphSCC &SCC) {
std::string Desc = "SCC (";
bool First = true;
for (CallGraphNode *CGN : SCC) {
if (First)
First = false;
else
Desc += ", ";
Function *F = CGN->getFunction();
if (F)
Desc += F->getName();
else
Desc += "<<null function>>";
}
Desc += ")";
return Desc;
}

static std::string getDescription(const LazyCallGraph::SCC &SCC) {
std::string Desc = "SCC (";
bool First = true;
for (LazyCallGraph::Node &CGN : SCC) {
if (First)
First = false;
else
Desc += ", ";
Function &F = CGN.getFunction();
Desc += F.getName();
}
Desc += ")";
return Desc;
}

// Force instantiations.
template bool OptBisect::shouldRunPass(const Pass *, const Module &);
template bool OptBisect::shouldRunPass(const Pass *, const Function &);
template bool OptBisect::shouldRunPass(const Pass *, const BasicBlock &);
template bool OptBisect::shouldRunPass(const Pass *, const Loop &);
template bool OptBisect::shouldRunPass(const Pass *, const CallGraphSCC &);
template bool OptBisect::shouldRunPass(const StringRef PassName,
const Module &);
template bool OptBisect::shouldRunPass(const StringRef PassName,
const Function &);
template bool OptBisect::shouldRunPass(const StringRef PassName,
const BasicBlock &);
template bool OptBisect::shouldRunPass(const StringRef PassName, const Loop &);
template bool OptBisect::shouldRunPass(const StringRef PassName,
const LazyCallGraph::SCC &);

template <class UnitT>
bool OptBisect::shouldRunPass(const Pass *P, const UnitT &U) {
if (!BisectEnabled)
return true;
return checkPass(P->getPassName(), getDescription(U));
}

// Interface function for the new pass manager.
template <class UnitT>
bool OptBisect::shouldRunPass(const StringRef PassName, const UnitT &U) {
if (!BisectEnabled)
return true;
return checkPass(PassName, getDescription(U));
}

bool OptBisect::checkPass(const StringRef PassName,
const StringRef TargetDesc) {
assert(BisectEnabled);

int CurBisectNum = ++LastBisectNum;
bool ShouldRun = (OptBisectLimit == -1 || CurBisectNum <= OptBisectLimit);
printPassMessage(PassName, CurBisectNum, TargetDesc, ShouldRun);
return ShouldRun;
}

bool OptBisect::shouldRunCase(const Twine &Msg) {
if (!BisectEnabled)
return true;
int CurFuelNum = ++LastBisectNum;
bool ShouldRun = (OptBisectLimit == -1 || CurFuelNum <= OptBisectLimit);
printCaseMessage(CurFuelNum, Msg.str(), ShouldRun);
return ShouldRun;
}

bool llvm::skipPassForModule(const StringRef PassName, const Module &M) {
return !M.getContext().getOptBisect().shouldRunPass(PassName, M);
}

bool llvm::skipPassForFunction(const StringRef PassName, const Function &F) {
return !F.getContext().getOptBisect().shouldRunPass(PassName, F);
}
#if 0
bool llvm::skipPassForBasicBlock(const StringRef PassName, const BasicBlock &BB) {
return !BB.getContext().getOptBisect().shouldRunPass(PassName, BB);
}

bool llvm::skipPassForLoop(const StringRef PassName, const Loop &L) {
const Function *F = L.getHeader()->getParent();
if (!F)
return false;
return !F->getContext().getOptBisect().shouldRunPass(PassName, L);
}
#endif
bool llvm::skipPassForSCC(const StringRef PassName, const LazyCallGraph::SCC &SCC) {
LLVMContext &Context = SCC.begin()->getFunction().getContext();
return !Context.getOptBisect().shouldRunPass(PassName, SCC);
}

23 changes: 18 additions & 5 deletions llvm/lib/IR/Pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/PassRegistry.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
Expand Down Expand Up @@ -45,6 +47,10 @@ PassManagerType ModulePass::getPotentialPassManagerType() const {
return PMT_ModulePassManager;
}

bool ModulePass::skipModule(Module &M) const {
return !M.getContext().getOptBisect().shouldRunPass(this, M);
}

bool Pass::mustPreserveAnalysisID(char &AID) const {
return Resolver->getAnalysisIfAvailable(&AID, true) != nullptr;
}
Expand Down Expand Up @@ -140,10 +146,13 @@ PassManagerType FunctionPass::getPotentialPassManagerType() const {
return PMT_FunctionPassManager;
}

bool FunctionPass::skipOptnoneFunction(const Function &F) const {
bool FunctionPass::skipFunction(const Function &F) const {
if (!F.getContext().getOptBisect().shouldRunPass(this, F))
return true;

if (F.hasFnAttribute(Attribute::OptimizeNone)) {
DEBUG(dbgs() << "Skipping pass '" << getPassName()
<< "' on function " << F.getName() << "\n");
DEBUG(dbgs() << "Skipping pass '" << getPassName() << "' on function "
<< F.getName() << "\n");
return true;
}
return false;
Expand All @@ -168,9 +177,13 @@ bool BasicBlockPass::doFinalization(Function &) {
return false;
}

bool BasicBlockPass::skipOptnoneFunction(const BasicBlock &BB) const {
bool BasicBlockPass::skipBasicBlock(const BasicBlock &BB) const {
const Function *F = BB.getParent();
if (F && F->hasFnAttribute(Attribute::OptimizeNone)) {
if (!F)
return false;
if (!F->getContext().getOptBisect().shouldRunPass(this, BB))
return true;
if (F->hasFnAttribute(Attribute::OptimizeNone)) {
// Report this only once per function.
if (&BB == &F->getEntryBlock())
DEBUG(dbgs() << "Skipping pass '" << getPassName()
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ Pass *llvm::createArgumentPromotionPass(unsigned maxElements) {
}

bool ArgPromotion::runOnSCC(CallGraphSCC &SCC) {
if (skipSCC(SCC))
return false;

bool Changed = false, LocalChange;

do { // Iterate until we stop promoting from this SCC.
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Transforms/IPO/ConstantMerge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ unsigned ConstantMerge::getAlignment(GlobalVariable *GV) const {
}

bool ConstantMerge::runOnModule(Module &M) {
if (skipModule(M))
return false;

// Find all the globals that are marked "used". These cannot be merged.
SmallPtrSet<const GlobalValue*, 8> UsedGlobals;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/CrossDSOCFI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ void CrossDSOCFI::buildCFICheck() {
}

bool CrossDSOCFI::runOnModule(Module &M) {
if (skipModule(M))
return false;

if (M.getModuleFlag("Cross-DSO CFI") == nullptr)
return false;
buildCFICheck();
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,9 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
}

bool DAE::runOnModule(Module &M) {
if (skipModule(M))
return false;

bool Changed = false;

// First pass: Do a simple check to see if any functions can have their "..."
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/ElimAvailExtern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ ModulePass *llvm::createEliminateAvailableExternallyPass() {
}

bool EliminateAvailableExternally::runOnModule(Module &M) {
if (skipModule(M))
return false;

bool Changed = false;

// Drop initializers of available externally global variables.
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/ExtractGV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ namespace {
: ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {}

bool runOnModule(Module &M) override {
if (skipModule(M))
return false;

// Visit the global inline asm.
if (!deleteStuff)
M.setModuleInlineAsm("");
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Transforms/IPO/FunctionAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,9 @@ static bool addNoRecurseAttrs(const SCCNodeSet &SCCNodes) {

PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C,
CGSCCAnalysisManager &AM) {
if (skipPassForSCC(name(), C))
return PreservedAnalyses::all();

Module &M = *C.begin()->getFunction().getParent();
const ModuleAnalysisManager &MAM =
AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C).getManager();
Expand Down Expand Up @@ -1081,6 +1084,9 @@ INITIALIZE_PASS_END(PostOrderFunctionAttrsLegacyPass, "functionattrs",
Pass *llvm::createPostOrderFunctionAttrsLegacyPass() { return new PostOrderFunctionAttrsLegacyPass(); }

bool PostOrderFunctionAttrsLegacyPass::runOnSCC(CallGraphSCC &SCC) {
if (skipSCC(SCC))
return false;

TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
bool Changed = false;

Expand Down Expand Up @@ -1195,6 +1201,9 @@ static bool addNoRecurseAttrsTopDown(Function &F) {
}

bool ReversePostOrderFunctionAttrs::runOnModule(Module &M) {
if (skipModule(M))
return false;

// We only have a post-order SCC traversal (because SCCs are inherently
// discovered in post-order), so we accumulate them in a vector and then walk
// it in reverse. This is simpler than using the RPO iterator infrastructure
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/FunctionImport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,9 @@ class FunctionImportPass : public ModulePass {
: ModulePass(ID), Index(Index) {}

bool runOnModule(Module &M) override {
if (skipModule(M))
return false;

if (SummaryFile.empty() && !Index)
report_fatal_error("error: -function-import requires -summary-file or "
"file from frontend\n");
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/GlobalDCE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ INITIALIZE_PASS(GlobalDCE, "globaldce",
ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); }

bool GlobalDCE::runOnModule(Module &M) {
if (skipModule(M))
return false;

bool Changed = false;

// Remove empty functions from the global ctors list.
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/GlobalOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2528,6 +2528,9 @@ bool GlobalOpt::OptimizeEmptyGlobalCXXDtors(Function *CXAAtExitFn) {
}

bool GlobalOpt::runOnModule(Module &M) {
if (skipModule(M))
return false;

bool Changed = false;

auto &DL = M.getDataLayout();
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/IPConstantPropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ INITIALIZE_PASS(IPCP, "ipconstprop",
ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); }

bool IPCP::runOnModule(Module &M) {
if (skipModule(M))
return false;

bool Changed = false;
bool LocalChange = true;

Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Transforms/IPO/InferFunctionAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
Expand Down Expand Up @@ -955,6 +956,9 @@ static bool inferAllPrototypeAttributes(Module &M,

PreservedAnalyses InferFunctionAttrsPass::run(Module &M,
AnalysisManager<Module> &AM) {
if (skipPassForModule(name(), M))
return PreservedAnalyses::all();

auto &TLI = AM.getResult<TargetLibraryAnalysis>(M);

if (!inferAllPrototypeAttributes(M, TLI))
Expand All @@ -979,6 +983,9 @@ struct InferFunctionAttrsLegacyPass : public ModulePass {
}

bool runOnModule(Module &M) override {
if (skipModule(M))
return false;

auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
return inferAllPrototypeAttributes(M, TLI);
}
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/Inliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,9 @@ static bool InlineHistoryIncludes(Function *F, int InlineHistoryID,
}

bool Inliner::runOnSCC(CallGraphSCC &SCC) {
if (skipSCC(SCC))
return false;

CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
ACT = &getAnalysis<AssumptionCacheTracker>();
auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/Internalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ class InternalizePass : public ModulePass {
}

bool runOnModule(Module &M) override {
if (skipModule(M))
return false;

CallGraphWrapperPass *CGPass =
getAnalysisIfAvailable<CallGraphWrapperPass>();
CallGraph *CG = CGPass ? &CGPass->getCallGraph() : nullptr;
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Transforms/IPO/LoopExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ INITIALIZE_PASS(SingleLoopExtractor, "loop-extract-single",
Pass *llvm::createLoopExtractorPass() { return new LoopExtractor(); }

bool LoopExtractor::runOnLoop(Loop *L, LPPassManager &) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

// Only visit top-level loops.
Expand Down Expand Up @@ -249,6 +249,9 @@ void BlockExtractorPass::SplitLandingPadPreds(Function *F) {
}

bool BlockExtractorPass::runOnModule(Module &M) {
if (skipModule(M))
return false;

std::set<BasicBlock*> TranslatedBlocksToNotExtract;
for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) {
BasicBlock *BB = BlocksToNotExtract[i];
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/LowerBitSets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,9 @@ bool LowerBitSets::eraseBitSetMetadata() {
}

bool LowerBitSets::runOnModule(Module &M) {
if (skipModule(M))
return false;

bool Changed = buildBitSets();
Changed |= eraseBitSetMetadata();
return Changed;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/MergeFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,9 @@ bool MergeFunctions::doSanityCheck(std::vector<WeakVH> &Worklist) {
}

bool MergeFunctions::runOnModule(Module &M) {
if (skipModule(M))
return false;

bool Changed = false;

// All functions in the module, ordered by hash. Functions with a unique
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/PartialInlining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ Function* PartialInliner::unswitchFunction(Function* F) {
}

bool PartialInliner::runOnModule(Module& M) {
if (skipModule(M))
return false;

std::vector<Function*> worklist;
worklist.reserve(M.size());
for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/PruneEH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ Pass *llvm::createPruneEHPass() { return new PruneEH(); }


bool PruneEH::runOnSCC(CallGraphSCC &SCC) {
if (skipSCC(SCC))
return false;

SmallPtrSet<CallGraphNode *, 8> SCCNodes;
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
bool MadeChange = false;
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Transforms/IPO/StripDeadPrototypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "llvm/Transforms/IPO/StripDeadPrototypes.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/IPO.h"

Expand Down Expand Up @@ -54,6 +55,9 @@ static bool stripDeadPrototypes(Module &M) {
}

PreservedAnalyses StripDeadPrototypesPass::run(Module &M) {
if (skipPassForModule(name(), M))
return PreservedAnalyses::all();

if (stripDeadPrototypes(M))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
Expand All @@ -69,6 +73,9 @@ class StripDeadPrototypesLegacyPass : public ModulePass {
*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override {
if (skipModule(M))
return false;

return stripDeadPrototypes(M);
}
};
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Transforms/IPO/StripSymbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
}

bool StripSymbols::runOnModule(Module &M) {
if (skipModule(M))
return false;

bool Changed = false;
Changed |= StripDebugInfo(M);
if (!OnlyDebugInfo)
Expand All @@ -237,10 +240,15 @@ bool StripSymbols::runOnModule(Module &M) {
}

bool StripNonDebugSymbols::runOnModule(Module &M) {
if (skipModule(M))
return false;

return StripSymbolNames(M, true);
}

bool StripDebugDeclare::runOnModule(Module &M) {
if (skipModule(M))
return false;

Function *Declare = M.getFunction("llvm.dbg.declare");
std::vector<Constant*> DeadConstants;
Expand Down Expand Up @@ -286,6 +294,9 @@ bool StripDebugDeclare::runOnModule(Module &M) {
/// optimized away by the optimizer. This special pass removes debug info for
/// such symbols.
bool StripDeadDebugInfo::runOnModule(Module &M) {
if (skipModule(M))
return false;

bool Changed = false;

LLVMContext &C = M.getContext();
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,12 @@ struct WholeProgramDevirt : public ModulePass {
WholeProgramDevirt() : ModulePass(ID) {
initializeWholeProgramDevirtPass(*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) { return DevirtModule(M).run(); }
bool runOnModule(Module &M) {
if (skipModule(M))
return false;

return DevirtModule(M).run();
}
};

} // anonymous namespace
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include "llvm/IR/Dominators.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/CommandLine.h"
Expand Down Expand Up @@ -3088,6 +3089,9 @@ combineInstructionsOverFunction(Function &F, InstCombineWorklist &Worklist,

PreservedAnalyses InstCombinePass::run(Function &F,
AnalysisManager<Function> &AM) {
if (skipPassForFunction(name(), F))
return PreservedAnalyses::all();

auto &AC = AM.getResult<AssumptionAnalysis>(F);
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
Expand Down Expand Up @@ -3120,7 +3124,7 @@ void InstructionCombiningPass::getAnalysisUsage(AnalysisUsage &AU) const {
}

bool InstructionCombiningPass::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

// Required analyses.
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,9 @@ static void createIRLevelProfileFlagVariable(Module &M) {
}

bool PGOInstrumentationGen::runOnModule(Module &M) {
if (skipModule(M))
return false;

createIRLevelProfileFlagVariable(M);
for (auto &F : M) {
if (F.isDeclaration())
Expand All @@ -801,6 +804,9 @@ static void setPGOCountOnFunc(PGOUseFunc &Func,
}

bool PGOInstrumentationUse::runOnModule(Module &M) {
if (skipModule(M))
return false;

DEBUG(dbgs() << "Read in profile counters: ");
auto &Ctx = M.getContext();
// Read the counter array from file.
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ bool ObjCARCAPElim::runOnModule(Module &M) {
if (!ModuleHasARC(M))
return false;

if (skipModule(M))
return false;

// Find the llvm.global_ctors variable, as the first step in
// identifying the global constructors. In theory, unnecessary autorelease
// pools could occur anywhere, but in practice it's pretty rare. Global
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Transforms/Scalar/ADCE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Pass.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Transforms/Scalar.h"
Expand Down Expand Up @@ -146,6 +147,9 @@ static bool aggressiveDCE(Function& F) {
}

PreservedAnalyses ADCEPass::run(Function &F) {
if (skipPassForFunction(name(), F))
return PreservedAnalyses::all();

if (aggressiveDCE(F))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
Expand All @@ -159,7 +163,7 @@ struct ADCELegacyPass : public FunctionPass {
}

bool runOnFunction(Function& F) override {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;
return aggressiveDCE(F);
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/BDCE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ INITIALIZE_PASS_END(BDCE, "bdce", "Bit-Tracking Dead Code Elimination",
false, false)

bool BDCE::runOnFunction(Function& F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;
auto &DB = getAnalysis<DemandedBitsWrapperPass>().getDemandedBits();

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ FunctionPass *llvm::createConstantHoistingPass() {

/// \brief Perform the constant hoisting optimization for the given function.
bool ConstantHoisting::runOnFunction(Function &Fn) {
if (skipOptnoneFunction(Fn))
if (skipFunction(Fn))
return false;

DEBUG(dbgs() << "********** Begin Constant Hoisting **********\n");
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ Constant *CorrelatedValuePropagation::getConstantAt(Value *V, Instruction *At) {
}

bool CorrelatedValuePropagation::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

LVI = &getAnalysis<LazyValueInfo>();
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Transforms/Scalar/DCE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace {
initializeDeadInstEliminationPass(*PassRegistry::getPassRegistry());
}
bool runOnBasicBlock(BasicBlock &BB) override {
if (skipOptnoneFunction(BB))
if (skipBasicBlock(BB))
return false;
auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI() : nullptr;
Expand Down Expand Up @@ -122,7 +122,7 @@ static bool DCEInstruction(Instruction *I,
}

bool DCE::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace {
}

bool runOnFunction(Function &F) override {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Transforms/Scalar/EarlyCSE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
Expand Down Expand Up @@ -819,6 +820,9 @@ bool EarlyCSE::run() {

PreservedAnalyses EarlyCSEPass::run(Function &F,
AnalysisManager<Function> &AM) {
if (skipPassForFunction(name(), F))
return PreservedAnalyses::all();

auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
auto &TTI = AM.getResult<TargetIRAnalysis>(F);
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
Expand Down Expand Up @@ -853,7 +857,7 @@ class EarlyCSELegacyPass : public FunctionPass {
}

bool runOnFunction(Function &F) override {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/Float2Int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ void Float2Int::cleanup() {
}

bool Float2Int::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

DEBUG(dbgs() << "F2I: Looking at function " << F.getName() << "\n");
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Transforms/Scalar/GVN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
Expand Down Expand Up @@ -584,6 +585,9 @@ void GVN::ValueTable::verifyRemoved(const Value *V) const {
//===----------------------------------------------------------------------===//

PreservedAnalyses GVN::run(Function &F, AnalysisManager<Function> &AM) {
if (skipPassForFunction(name(), F))
return PreservedAnalyses::all();

// FIXME: The order of evaluation of these 'getResult' calls is very
// significant! Re-ordering these variables will cause GVN when run alone to
// be less effective! We should fix memdep and basic-aa to not exhibit this
Expand Down Expand Up @@ -2675,7 +2679,7 @@ class llvm::gvn::GVNLegacyPass : public FunctionPass {
}

bool runOnFunction(Function &F) override {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

return Impl.runImpl(
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2122,7 +2122,7 @@ void IndVarSimplify::sinkUnusedInvariants(Loop *L) {
//===----------------------------------------------------------------------===//

bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

// If LoopSimplify form is not available, stay out of trouble. Some notes:
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/JumpThreading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ FunctionPass *llvm::createJumpThreadingPass(int Threshold) { return new JumpThre
/// runOnFunction - Top level algorithm.
///
bool JumpThreading::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

DEBUG(dbgs() << "Jump threading on function '" << F.getName() << "'\n");
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LICM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ Pass *llvm::createLICMPass() { return new LICM(); }
/// times on one loop.
///
bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

Changed = false;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoadCombine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ bool LoadCombine::combineLoads(SmallVectorImpl<LoadPOPPair> &Loads) {
}

bool LoadCombine::runOnBasicBlock(BasicBlock &BB) {
if (skipOptnoneFunction(BB))
if (skipBasicBlock(BB))
return false;

AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopDeletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ bool LoopDeletion::isLoopDead(Loop *L,
/// NOTE: This entire process relies pretty heavily on LoopSimplify and LCSSA
/// in order to make various safety checks work.
bool LoopDeletion::runOnLoop(Loop *L, LPPassManager &) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ static void deleteDeadInstruction(Instruction *I,
//===----------------------------------------------------------------------===//

bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

CurLoop = L;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopInstSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Pass *llvm::createLoopInstSimplifyPass() {
}

bool LoopInstSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

DominatorTreeWrapperPass *DTWP =
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,9 @@ class LoopLoadElimination : public FunctionPass {
}

bool runOnFunction(Function &F) override {
if (skipFunction(F))
return false;

auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
auto *LAA = &getAnalysis<LoopAccessAnalysis>();
auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopRerollPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1536,7 +1536,7 @@ bool LoopReroll::reroll(Instruction *IV, Loop *L, BasicBlock *Header,
}

bool LoopReroll::runOnLoop(Loop *L, LPPassManager &LPM) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopRotation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ class LoopRotate : public LoopPass {
}

bool runOnLoop(Loop *L, LPPassManager &LPM) override {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;
Function &F = *L->getHeader()->getParent();

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ static bool simplifyLoopCFG(Loop *L, DominatorTree *DT, LoopInfo *LI) {
/// runOnLoop - Perform basic CFG simplifications to assist other loop passes.
/// For now, this only attempts to merge blocks in the trivial case.
bool LoopSimplifyCFG::runOnLoop(Loop *L, LPPassManager &) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5002,7 +5002,7 @@ void LoopStrengthReduce::getAnalysisUsage(AnalysisUsage &AU) const {
}

bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager & /*LPM*/) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

auto &IU = getAnalysis<IVUsers>();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,7 @@ class LoopUnroll : public LoopPass {
Optional<bool> ProvidedRuntime;

bool runOnLoop(Loop *L, LPPassManager &) override {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

Function &F = *L->getHeader()->getParent();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopUnswitch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ static Value *FindLIVLoopCondition(Value *Cond, Loop *L, bool &Changed) {
}

bool LoopUnswitch::runOnLoop(Loop *L, LPPassManager &LPM_Ref) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;

AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ void LoopVersioningLICM::setNoAliasToLoop(Loop *VerLoop) {
}

bool LoopVersioningLICM::runOnLoop(Loop *L, LPPassManager &LPM) {
if (skipOptnoneFunction(L))
if (skipLoop(L))
return false;
Changed = false;
// Get Analysis information.
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/LowerAtomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ namespace {
initializeLowerAtomicPass(*PassRegistry::getPassRegistry());
}
bool runOnBasicBlock(BasicBlock &BB) override {
if (skipOptnoneFunction(BB))
if (skipBasicBlock(BB))
return false;
bool Changed = false;
for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1361,7 +1361,7 @@ bool MemCpyOpt::iterateOnFunction(Function &F) {

/// This is the main transformation entry point for a function.
bool MemCpyOpt::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

bool MadeChange = false;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,9 @@ bool MergedLoadStoreMotion::mergeStores(BasicBlock *T) {
/// \brief Run the transformation for each function
///
bool MergedLoadStoreMotion::runOnFunction(Function &F) {
if (skipFunction(F))
return false;

auto *MDWP = getAnalysisIfAvailable<MemoryDependenceWrapperPass>();
MD = MDWP ? &MDWP->getMemDep() : nullptr;
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/NaryReassociate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ FunctionPass *llvm::createNaryReassociatePass() {
}

bool NaryReassociate::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/Reassociate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2257,7 +2257,7 @@ void Reassociate::ReassociateExpression(BinaryOperator *I) {
}

bool Reassociate::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

// Reassociate needs for each instruction to have its operands already
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Transforms/Scalar/SCCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1568,7 +1568,7 @@ FunctionPass *llvm::createSCCPPass() {
// and return true if the function was modified.
//
bool SCCP::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n");
Expand Down Expand Up @@ -1705,6 +1705,9 @@ static bool AddressIsTaken(const GlobalValue *GV) {
}

bool IPSCCP::runOnModule(Module &M) {
if (skipModule(M))
return false;

const DataLayout &DL = M.getDataLayout();
const TargetLibraryInfo *TLI =
&getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Transforms/Scalar/SROA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
Expand Down Expand Up @@ -4229,6 +4230,9 @@ PreservedAnalyses SROA::runImpl(Function &F, DominatorTree &RunDT,
}

PreservedAnalyses SROA::run(Function &F, AnalysisManager<Function> &AM) {
if (skipPassForFunction(name(), F))
return PreservedAnalyses::all();

return runImpl(F, AM.getResult<DominatorTreeAnalysis>(F),
AM.getResult<AssumptionAnalysis>(F));
}
Expand All @@ -4246,7 +4250,7 @@ class llvm::sroa::SROALegacyPass : public FunctionPass {
initializeSROALegacyPassPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

auto PA = Impl.runImpl(
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ ConvertScalar_InsertValue(Value *SV, Value *Old,


bool SROA::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

bool Changed = performPromotion(F);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,7 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
}

bool SeparateConstOffsetFromGEP::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

if (DisableSeparateConstOffsetFromGEP)
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Utils/Local.h"
Expand Down Expand Up @@ -187,6 +188,9 @@ SimplifyCFGPass::SimplifyCFGPass(int BonusInstThreshold)

PreservedAnalyses SimplifyCFGPass::run(Function &F,
AnalysisManager<Function> &AM) {
if (skipPassForFunction(name(), F))
return PreservedAnalyses::all();

auto &TTI = AM.getResult<TargetIRAnalysis>(F);
auto &AC = AM.getResult<AssumptionAnalysis>(F);

Expand All @@ -212,7 +216,7 @@ struct CFGSimplifyPass : public FunctionPass {
if (PredicateFtor && !PredicateFtor(F))
return false;

if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

AssumptionCache *AC =
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void SpeculativeExecution::getAnalysisUsage(AnalysisUsage &AU) const {
}

bool SpeculativeExecution::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ void StraightLineStrengthReduce::rewriteCandidateWithBasis(
}

bool StraightLineStrengthReduce::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ static bool CanTRE(Function &F) {
}

bool TailCallElim::runOnFunction(Function &F) {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

if (F.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Transforms/Utils/Mem2Reg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ INITIALIZE_PASS_END(PromotePass, "mem2reg", "Promote Memory to Register",
false, false)

bool PromotePass::runOnFunction(Function &F) {
if (skipFunction(F))
return false;

std::vector<AllocaInst*> Allocas;

BasicBlock &BB = F.getEntryBlock(); // Get the entry node for the function

if (F.hasFnAttribute(Attribute::OptimizeNone))
return false;

bool Changed = false;

DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Vectorize/BBVectorize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ namespace {
Instruction *I, Instruction *J);

bool vectorizeBB(BasicBlock &BB) {
if (skipOptnoneFunction(BB))
if (skipBasicBlock(BB))
return false;
if (!DT->isReachableFromEntry(&BB)) {
DEBUG(dbgs() << "BBV: skipping unreachable " << BB.getName() <<
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,9 @@ struct LoopVectorize : public FunctionPass {
BlockFrequency ColdEntryFreq;

bool runOnFunction(Function &F) override {
if (skipFunction(F))
return false;

SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3396,7 +3396,7 @@ struct SLPVectorizer : public FunctionPass {
}

bool runOnFunction(Function &F) override {
if (skipOptnoneFunction(F))
if (skipFunction(F))
return false;

SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
Expand Down
39 changes: 39 additions & 0 deletions llvm/test/Other/opt-bisect-helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env python

import os
import sys
import argparse
import subprocess

parser = argparse.ArgumentParser()

parser.add_argument('--start', type=int, default=0)
parser.add_argument('--end', type=int, default=(1 << 32))
parser.add_argument('--optcmd', default=("opt"))
parser.add_argument('--filecheckcmd', default=("FileCheck"))
parser.add_argument('--prefix', default=("CHECK-BISECT"))
parser.add_argument('--test', default=(""))

args = parser.parse_args()

start = args.start
end = args.end

opt_command = [args.optcmd, "-O2", "-opt-bisect-limit=%(count)s", "-S", args.test]
check_command = [args.filecheckcmd, args.test, "--check-prefix=%s" % args.prefix]
last = None
while start != end and start != end-1:
count = int(round(start + (end - start)/2))
cmd = [x % {'count':count} for x in opt_command]
print("opt: " + str(cmd))
opt_result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
filecheck_result = subprocess.Popen(check_command, stdin=opt_result.stdout)
opt_result.stdout.close()
opt_result.stderr.close()
filecheck_result.wait()
if filecheck_result.returncode == 0:
start = count
else:
end = count

print("Last good count: %d" % start)
148 changes: 148 additions & 0 deletions llvm/test/Other/opt-bisect-legacy-pass-manager.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
; This file verifies the behavior of the OptBisect class, which is used to
; diagnose optimization related failures. The tests check various
; invocations that result in different sets of optimization passes that
; are run in different ways.
;
; This set of tests exercises the legacy pass manager interface to the OptBisect
; class. Because the exact set of optimizations that will be run may
; change over time, these tests are written in a more general manner than the
; corresponding tests for the new pass manager.
;
; Don't use NEXT checks or hard-code pass numbering so that this won't fail if
; new passes are inserted.


; Verify that the file can be compiled to an object file at -O3 with all
; skippable passes skipped.

; RUN: opt -O3 -opt-bisect-limit=0 < %s | llc -O3 -opt-bisect-limit=0


; Verify that no skippable passes are run with -opt-bisect-limit=0.

; RUN: opt -disable-output -disable-verify -O3 -opt-bisect-limit=0 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-SKIP-ALL
; CHECK-SKIP-ALL: BISECT: NOT running pass ({{[0-9]+}})
; CHECK-SKIP-ALL-NOT: BISECT: running pass ({{[0-9]+}})


; Verify that we can use the opt-bisect-helper.py script (derived from
; utils/bisect) to locate the optimization that inlines the call to
; f2() in f3().

; RUN: %python %S/opt-bisect-helper.py --start=0 --end=256 --optcmd=opt \
; RUN: --filecheckcmd=FileCheck --test=%s \
; RUN: --prefix=CHECK-BISECT-INLINE-HELPER \
; RUN: | FileCheck %s --check-prefix=CHECK-BISECT-INLINE-RESULT
; The helper script uses this to find the optimization that inlines the call.
; CHECK-BISECT-INLINE-HELPER: call i32 @f2()
; These checks verifies that the optimization was found.
; CHECK-BISECT-INLINE-RESULT-NOT: Last good count: 0
; CHECK-BISECT-INLINE-RESULT: Last good count: {{[0-9]+}}


; Test a module pass.

; RUN: opt -disable-output -disable-verify -deadargelim -opt-bisect-limit=-1 %s \
; RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-DEADARG
; CHECK-DEADARG: BISECT: running pass ({{[0-9]+}}) Dead Argument Elimination on module

; RUN: opt -disable-output -disable-verify -deadargelim -opt-bisect-limit=0 %s \
; RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-NOT-DEADARG
; CHECK-NOT-DEADARG: BISECT: NOT running pass ({{[0-9]+}}) Dead Argument Elimination on module


; Test an SCC pass.

; RUN: opt -disable-output -disable-verify -inline -opt-bisect-limit=-1 %s \
; RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-INLINE
; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (<<null function>>)
; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (g)
; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f1)
; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f2)
; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f3)
; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (<<null function>>)

; RUN: opt -disable-output -disable-verify -inline -opt-bisect-limit=0 %s \
; RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-NOT-INLINE
; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (<<null function>>)
; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (g)
; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f1)
; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f2)
; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f3)
; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (<<null function>>)


; Test a function pass.

; RUN: opt -disable-output -disable-verify -early-cse -opt-bisect-limit=-1 \
; RUN: %s 2>&1 | FileCheck %s --check-prefix=CHECK-EARLY-CSE
; CHECK-EARLY-CSE: BISECT: running pass ({{[0-9]+}}) Early CSE on function (f1)
; CHECK-EARLY-CSE: BISECT: running pass ({{[0-9]+}}) Early CSE on function (f2)
; CHECK-EARLY-CSE: BISECT: running pass ({{[0-9]+}}) Early CSE on function (f3)

; RUN: opt -disable-output -disable-verify -early-cse -opt-bisect-limit=0 %s \
; RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-NOT-EARLY-CSE
; CHECK-NOT-EARLY-CSE: BISECT: NOT running pass ({{[0-9]+}}) Early CSE on function (f1)
; CHECK-NOT-EARLY-CSE: BISECT: NOT running pass ({{[0-9]+}}) Early CSE on function (f2)
; CHECK-NOT-EARLY-CSE: BISECT: NOT running pass ({{[0-9]+}}) Early CSE on function (f3)


; Test a loop pass.

; RUN: opt -disable-output -disable-verify -loop-reduce -opt-bisect-limit=-1 \
; RUN: %s 2>&1 | FileCheck %s --check-prefix=CHECK-LOOP-REDUCE
; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop
; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop
; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop
; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop
; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop

; RUN: opt -disable-output -disable-verify -loop-reduce -opt-bisect-limit=0 \
; RUN: %s 2>&1 | FileCheck %s --check-prefix=CHECK-NOT-LOOP-REDUCE
; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop
; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop
; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop
; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop
; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop


declare i32 @g()

define void @f1() {
entry:
br label %loop.0
loop.0:
br i1 undef, label %loop.0.0, label %loop.1
loop.0.0:
br i1 undef, label %loop.0.0, label %loop.0.1
loop.0.1:
br i1 undef, label %loop.0.1, label %loop.0
loop.1:
br i1 undef, label %loop.1, label %loop.1.bb1
loop.1.bb1:
br i1 undef, label %loop.1, label %loop.1.bb2
loop.1.bb2:
br i1 undef, label %end, label %loop.1.0
loop.1.0:
br i1 undef, 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
}
109 changes: 109 additions & 0 deletions llvm/test/Other/opt-bisect-new-pass-manager.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
; This file verifies the behavior of the OptBisect class, which is used to
; diagnose optimization related failures. The tests check various
; invocations that result in different sets of optimization passes that
; are run in different ways.
;
; Because the exact set of optimizations that will be run is expected to
; change over time, the checks for disabling passes are written in a
; conservative way that avoids assumptions about which specific passes
; will be disabled.

; 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

; 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

; 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 function (f1)
; CHECK-FUNCTION-PASS: BISECT: running pass (2) EarlyCSEPass on function (f2)
; CHECK-FUNCTION-PASS: BISECT: running pass (3) EarlyCSEPass on function (f3)

; 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 function (f1)
; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (2) EarlyCSEPass on function (f2)
; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (3) EarlyCSEPass on function (f3)

; 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 SCC (f2)
; CHECK-CGSCC-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on SCC (f3)
; CHECK-CGSCC-PASS: BISECT: running pass (3) PostOrderFunctionAttrsPass on SCC (f1)

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

; 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 SCC (f2)
; CHECK-MULTI-PASS: BISECT: running pass (3) EarlyCSEPass on function (f2)
; CHECK-MULTI-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on SCC (f3)
; CHECK-MULTI-PASS: BISECT: running pass (5) EarlyCSEPass on function (f3)
; CHECK-MULTI-PASS: BISECT: running pass (6) PostOrderFunctionAttrsPass on SCC (f1)
; CHECK-MULTI-PASS: BISECT: running pass (7) EarlyCSEPass on function (f1)

; RUN: opt -disable-output -disable-verify -opt-bisect-limit=5 \
; 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 SCC (f2)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (3) EarlyCSEPass on function (f2)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on SCC (f3)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (5) EarlyCSEPass on function (f3)
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (6) PostOrderFunctionAttrsPass on SCC (f1)
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (7) EarlyCSEPass on function (f1)

declare i32 @g()

define void @f1() {
entry:
br label %loop.0
loop.0:
br i1 undef, label %loop.0.0, label %loop.1
loop.0.0:
br i1 undef, label %loop.0.0, label %loop.0.1
loop.0.1:
br i1 undef, label %loop.0.1, label %loop.0
loop.1:
br i1 undef, label %loop.1, label %loop.1.bb1
loop.1.bb1:
br i1 undef, label %loop.1, label %loop.1.bb2
loop.1.bb2:
br i1 undef, label %end, label %loop.1.0
loop.1.0:
br i1 undef, 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
}