[ARM] Pass a callback to FunctionPass constructors to enable skipping execution

on a per-function basis.

Previously some of the passes were conditionally added to ARM's pass pipeline
based on the target machine's subtarget. This patch makes changes to add those
passes unconditionally and execute them conditonally based on the predicate
functor passed to the pass constructors. This enables running different sets of
passes for different functions in the module.

rdar://problem/20542263

Differential Revision: http://reviews.llvm.org/D8717


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239325 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Akira Hatanaka 2015-06-08 18:50:43 +00:00
parent d354befbbb
commit fa6bc2e94d
9 changed files with 97 additions and 26 deletions

View File

@ -21,7 +21,6 @@
namespace llvm { namespace llvm {
class FunctionPass;
class MachineFunctionPass; class MachineFunctionPass;
class PassConfigImpl; class PassConfigImpl;
class PassInfo; class PassInfo;
@ -519,6 +518,8 @@ namespace llvm {
/// IfConverter - This pass performs machine code if conversion. /// IfConverter - This pass performs machine code if conversion.
extern char &IfConverterID; extern char &IfConverterID;
FunctionPass *createIfConverter(std::function<bool(const Function &)> Ftor);
/// MachineBlockPlacement - This pass places basic blocks based on branch /// MachineBlockPlacement - This pass places basic blocks based on branch
/// probabilities. /// probabilities.
extern char &MachineBlockPlacementID; extern char &MachineBlockPlacementID;
@ -613,6 +614,9 @@ namespace llvm {
/// UnpackMachineBundles - This pass unpack machine instruction bundles. /// UnpackMachineBundles - This pass unpack machine instruction bundles.
extern char &UnpackMachineBundlesID; extern char &UnpackMachineBundlesID;
FunctionPass *
createUnpackMachineBundles(std::function<bool(const Function &)> Ftor);
/// FinalizeMachineBundles - This pass finalize machine instruction /// FinalizeMachineBundles - This pass finalize machine instruction
/// bundles (created earlier, e.g. during pre-RA scheduling). /// bundles (created earlier, e.g. during pre-RA scheduling).
extern char &FinalizeMachineBundlesID; extern char &FinalizeMachineBundlesID;

View File

@ -16,10 +16,12 @@
#define LLVM_TRANSFORMS_SCALAR_H #define LLVM_TRANSFORMS_SCALAR_H
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include <functional>
namespace llvm { namespace llvm {
class BasicBlockPass; class BasicBlockPass;
class Function;
class FunctionPass; class FunctionPass;
class ModulePass; class ModulePass;
class Pass; class Pass;
@ -245,7 +247,8 @@ FunctionPass *createJumpThreadingPass(int Threshold = -1);
// CFGSimplification - Merge basic blocks, eliminate unreachable blocks, // CFGSimplification - Merge basic blocks, eliminate unreachable blocks,
// simplify terminator instructions, etc... // simplify terminator instructions, etc...
// //
FunctionPass *createCFGSimplificationPass(int Threshold = -1); FunctionPass *createCFGSimplificationPass(
int Threshold = -1, std::function<bool(const Function &)> Ftor = nullptr);
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //

View File

@ -170,9 +170,12 @@ namespace {
bool PreRegAlloc; bool PreRegAlloc;
bool MadeChange; bool MadeChange;
int FnNum; int FnNum;
std::function<bool(const Function &)> PredicateFtor;
public: public:
static char ID; static char ID;
IfConverter() : MachineFunctionPass(ID), FnNum(-1) { IfConverter(std::function<bool(const Function &)> Ftor = nullptr)
: MachineFunctionPass(ID), FnNum(-1), PredicateFtor(Ftor) {
initializeIfConverterPass(*PassRegistry::getPassRegistry()); initializeIfConverterPass(*PassRegistry::getPassRegistry());
} }
@ -270,6 +273,9 @@ INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
INITIALIZE_PASS_END(IfConverter, "if-converter", "If Converter", false, false) INITIALIZE_PASS_END(IfConverter, "if-converter", "If Converter", false, false)
bool IfConverter::runOnMachineFunction(MachineFunction &MF) { bool IfConverter::runOnMachineFunction(MachineFunction &MF) {
if (PredicateFtor && !PredicateFtor(*MF.getFunction()))
return false;
const TargetSubtargetInfo &ST = MF.getSubtarget(); const TargetSubtargetInfo &ST = MF.getSubtarget();
TLI = ST.getTargetLowering(); TLI = ST.getTargetLowering();
TII = ST.getInstrInfo(); TII = ST.getInstrInfo();
@ -1691,3 +1697,8 @@ void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI, bool AddEdges) {
ToBBI.IsAnalyzed = false; ToBBI.IsAnalyzed = false;
FromBBI.IsAnalyzed = false; FromBBI.IsAnalyzed = false;
} }
FunctionPass *
llvm::createIfConverter(std::function<bool(const Function &)> Ftor) {
return new IfConverter(Ftor);
}

View File

@ -23,11 +23,15 @@ namespace {
class UnpackMachineBundles : public MachineFunctionPass { class UnpackMachineBundles : public MachineFunctionPass {
public: public:
static char ID; // Pass identification static char ID; // Pass identification
UnpackMachineBundles() : MachineFunctionPass(ID) { UnpackMachineBundles(std::function<bool(const Function &)> Ftor = nullptr)
: MachineFunctionPass(ID), PredicateFtor(Ftor) {
initializeUnpackMachineBundlesPass(*PassRegistry::getPassRegistry()); initializeUnpackMachineBundlesPass(*PassRegistry::getPassRegistry());
} }
bool runOnMachineFunction(MachineFunction &MF) override; bool runOnMachineFunction(MachineFunction &MF) override;
private:
std::function<bool(const Function &)> PredicateFtor;
}; };
} // end anonymous namespace } // end anonymous namespace
@ -37,6 +41,9 @@ INITIALIZE_PASS(UnpackMachineBundles, "unpack-mi-bundles",
"Unpack machine instruction bundles", false, false) "Unpack machine instruction bundles", false, false)
bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) { bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) {
if (PredicateFtor && !PredicateFtor(*MF.getFunction()))
return false;
bool Changed = false; bool Changed = false;
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
MachineBasicBlock *MBB = &*I; MachineBasicBlock *MBB = &*I;
@ -69,6 +76,10 @@ bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) {
return Changed; return Changed;
} }
FunctionPass *
llvm::createUnpackMachineBundles(std::function<bool(const Function &)> Ftor) {
return new UnpackMachineBundles(Ftor);
}
namespace { namespace {
class FinalizeMachineBundles : public MachineFunctionPass { class FinalizeMachineBundles : public MachineFunctionPass {

View File

@ -16,11 +16,13 @@
#define LLVM_LIB_TARGET_ARM_ARM_H #define LLVM_LIB_TARGET_ARM_ARM_H
#include "llvm/Support/CodeGen.h" #include "llvm/Support/CodeGen.h"
#include <functional>
namespace llvm { namespace llvm {
class ARMAsmPrinter; class ARMAsmPrinter;
class ARMBaseTargetMachine; class ARMBaseTargetMachine;
class Function;
class FunctionPass; class FunctionPass;
class ImmutablePass; class ImmutablePass;
class MachineInstr; class MachineInstr;
@ -38,7 +40,8 @@ FunctionPass *createARMConstantIslandPass();
FunctionPass *createMLxExpansionPass(); FunctionPass *createMLxExpansionPass();
FunctionPass *createThumb2ITBlockPass(); FunctionPass *createThumb2ITBlockPass();
FunctionPass *createARMOptimizeBarriersPass(); FunctionPass *createARMOptimizeBarriersPass();
FunctionPass *createThumb2SizeReductionPass(); FunctionPass *createThumb2SizeReductionPass(
std::function<bool(const Function &)> Ftor = nullptr);
void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
ARMAsmPrinter &AP); ARMAsmPrinter &AP);

View File

@ -304,10 +304,6 @@ public:
return getTM<ARMBaseTargetMachine>(); return getTM<ARMBaseTargetMachine>();
} }
const ARMSubtarget &getARMSubtarget() const {
return *getARMTargetMachine().getSubtargetImpl();
}
void addIRPasses() override; void addIRPasses() override;
bool addPreISel() override; bool addPreISel() override;
bool addInstSelector() override; bool addInstSelector() override;
@ -330,10 +326,11 @@ void ARMPassConfig::addIRPasses() {
// Cmpxchg instructions are often used with a subsequent comparison to // Cmpxchg instructions are often used with a subsequent comparison to
// determine whether it succeeded. We can exploit existing control-flow in // determine whether it succeeded. We can exploit existing control-flow in
// ldrex/strex loops to simplify this, but it needs tidying up. // ldrex/strex loops to simplify this, but it needs tidying up.
const ARMSubtarget *Subtarget = &getARMSubtarget(); if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only()) addPass(createCFGSimplificationPass(-1, [this](const Function &F) {
if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy) const auto &ST = this->TM->getSubtarget<ARMSubtarget>(F);
addPass(createCFGSimplificationPass()); return ST.hasAnyDataBarrier() && !ST.isThumb1Only();
}));
TargetPassConfig::addIRPasses(); TargetPassConfig::addIRPasses();
} }
@ -390,10 +387,13 @@ void ARMPassConfig::addPreSched2() {
if (getOptLevel() != CodeGenOpt::None) { if (getOptLevel() != CodeGenOpt::None) {
// in v8, IfConversion depends on Thumb instruction widths // in v8, IfConversion depends on Thumb instruction widths
if (getARMSubtarget().restrictIT()) addPass(createThumb2SizeReductionPass([this](const Function &F) {
addPass(createThumb2SizeReductionPass()); return this->TM->getSubtarget<ARMSubtarget>(F).restrictIT();
if (!getARMSubtarget().isThumb1Only()) }));
addPass(&IfConverterID);
addPass(createIfConverter([this](const Function &F) {
return !this->TM->getSubtarget<ARMSubtarget>(F).isThumb1Only();
}));
} }
addPass(createThumb2ITBlockPass()); addPass(createThumb2ITBlockPass());
} }
@ -402,8 +402,9 @@ void ARMPassConfig::addPreEmitPass() {
addPass(createThumb2SizeReductionPass()); addPass(createThumb2SizeReductionPass());
// Constant island pass work on unbundled instructions. // Constant island pass work on unbundled instructions.
if (getARMSubtarget().isThumb2()) addPass(createUnpackMachineBundles([this](const Function &F) {
addPass(&UnpackMachineBundlesID); return this->TM->getSubtarget<ARMSubtarget>(F).isThumb2();
}));
// Don't optimize barriers at -O0. // Don't optimize barriers at -O0.
if (getOptLevel() != CodeGenOpt::None) if (getOptLevel() != CodeGenOpt::None)

View File

@ -133,7 +133,7 @@ namespace {
class Thumb2SizeReduce : public MachineFunctionPass { class Thumb2SizeReduce : public MachineFunctionPass {
public: public:
static char ID; static char ID;
Thumb2SizeReduce(); Thumb2SizeReduce(std::function<bool(const Function &)> Ftor);
const Thumb2InstrInfo *TII; const Thumb2InstrInfo *TII;
const ARMSubtarget *STI; const ARMSubtarget *STI;
@ -198,11 +198,14 @@ namespace {
}; };
SmallVector<MBBInfo, 8> BlockInfo; SmallVector<MBBInfo, 8> BlockInfo;
std::function<bool(const Function &)> PredicateFtor;
}; };
char Thumb2SizeReduce::ID = 0; char Thumb2SizeReduce::ID = 0;
} }
Thumb2SizeReduce::Thumb2SizeReduce() : MachineFunctionPass(ID) { Thumb2SizeReduce::Thumb2SizeReduce(std::function<bool(const Function &)> Ftor)
: MachineFunctionPass(ID), PredicateFtor(Ftor) {
OptimizeSize = MinimizeSize = false; OptimizeSize = MinimizeSize = false;
for (unsigned i = 0, e = array_lengthof(ReduceTable); i != e; ++i) { for (unsigned i = 0, e = array_lengthof(ReduceTable); i != e; ++i) {
unsigned FromOpc = ReduceTable[i].WideOpc; unsigned FromOpc = ReduceTable[i].WideOpc;
@ -1000,6 +1003,9 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) {
} }
bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) { bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) {
if (PredicateFtor && !PredicateFtor(*MF.getFunction()))
return false;
STI = &static_cast<const ARMSubtarget &>(MF.getSubtarget()); STI = &static_cast<const ARMSubtarget &>(MF.getSubtarget());
if (STI->isThumb1Only() || STI->prefers32BitThumb()) if (STI->isThumb1Only() || STI->prefers32BitThumb())
return false; return false;
@ -1025,6 +1031,7 @@ bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) {
/// createThumb2SizeReductionPass - Returns an instance of the Thumb2 size /// createThumb2SizeReductionPass - Returns an instance of the Thumb2 size
/// reduction pass. /// reduction pass.
FunctionPass *llvm::createThumb2SizeReductionPass() { FunctionPass *llvm::createThumb2SizeReductionPass(
return new Thumb2SizeReduce(); std::function<bool(const Function &)> Ftor) {
return new Thumb2SizeReduce(Ftor);
} }

View File

@ -193,11 +193,18 @@ namespace {
struct CFGSimplifyPass : public FunctionPass { struct CFGSimplifyPass : public FunctionPass {
static char ID; // Pass identification, replacement for typeid static char ID; // Pass identification, replacement for typeid
unsigned BonusInstThreshold; unsigned BonusInstThreshold;
CFGSimplifyPass(int T = -1) : FunctionPass(ID) { std::function<bool(const Function &)> PredicateFtor;
CFGSimplifyPass(int T = -1,
std::function<bool(const Function &)> Ftor = nullptr)
: FunctionPass(ID), PredicateFtor(Ftor) {
BonusInstThreshold = (T == -1) ? UserBonusInstThreshold : unsigned(T); BonusInstThreshold = (T == -1) ? UserBonusInstThreshold : unsigned(T);
initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry()); initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry());
} }
bool runOnFunction(Function &F) override { bool runOnFunction(Function &F) override {
if (PredicateFtor && !PredicateFtor(F))
return false;
if (skipOptnoneFunction(F)) if (skipOptnoneFunction(F))
return false; return false;
@ -224,7 +231,9 @@ INITIALIZE_PASS_END(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false,
false) false)
// Public interface to the CFGSimplification pass // Public interface to the CFGSimplification pass
FunctionPass *llvm::createCFGSimplificationPass(int Threshold) { FunctionPass *
return new CFGSimplifyPass(Threshold); llvm::createCFGSimplificationPass(int Threshold,
std::function<bool(const Function &)> Ftor) {
return new CFGSimplifyPass(Threshold, Ftor);
} }

View File

@ -0,0 +1,22 @@
; RUN: llc -march thumb %s -o - | FileCheck %s
; This test checks that if-conversion pass is unconditionally added to the pass
; pipeline and is conditionally executed based on the per-function targert-cpu
; attribute.
; CHECK: ite eq
define i32 @test_ifcvt(i32 %a, i32 %b) #0 {
%tmp2 = icmp eq i32 %a, 0
br i1 %tmp2, label %cond_false, label %cond_true
cond_true:
%tmp5 = add i32 %b, 1
ret i32 %tmp5
cond_false:
%tmp7 = add i32 %b, -1
ret i32 %tmp7
}
attributes #0 = { "target-cpu"="cortex-a8" }