From fa6bc2e94d3a98eda4ddfb05d3190ee221fa6fc6 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Mon, 8 Jun 2015 18:50:43 +0000 Subject: [PATCH] [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 --- include/llvm/CodeGen/Passes.h | 6 ++++- include/llvm/Transforms/Scalar.h | 5 +++- lib/CodeGen/IfConversion.cpp | 13 +++++++++- lib/CodeGen/MachineInstrBundle.cpp | 13 +++++++++- lib/Target/ARM/ARM.h | 5 +++- lib/Target/ARM/ARMTargetMachine.cpp | 29 ++++++++++++----------- lib/Target/ARM/Thumb2SizeReduction.cpp | 15 ++++++++---- lib/Transforms/Scalar/SimplifyCFGPass.cpp | 15 +++++++++--- test/CodeGen/ARM/ifcvt-callback.ll | 22 +++++++++++++++++ 9 files changed, 97 insertions(+), 26 deletions(-) create mode 100644 test/CodeGen/ARM/ifcvt-callback.ll diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 9671459458e..6bcfa0f56bd 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -21,7 +21,6 @@ namespace llvm { -class FunctionPass; class MachineFunctionPass; class PassConfigImpl; class PassInfo; @@ -519,6 +518,8 @@ namespace llvm { /// IfConverter - This pass performs machine code if conversion. extern char &IfConverterID; + FunctionPass *createIfConverter(std::function Ftor); + /// MachineBlockPlacement - This pass places basic blocks based on branch /// probabilities. extern char &MachineBlockPlacementID; @@ -613,6 +614,9 @@ namespace llvm { /// UnpackMachineBundles - This pass unpack machine instruction bundles. extern char &UnpackMachineBundlesID; + FunctionPass * + createUnpackMachineBundles(std::function Ftor); + /// FinalizeMachineBundles - This pass finalize machine instruction /// bundles (created earlier, e.g. during pre-RA scheduling). extern char &FinalizeMachineBundlesID; diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 481d4fc680b..4676c95d7cd 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -16,10 +16,12 @@ #define LLVM_TRANSFORMS_SCALAR_H #include "llvm/ADT/StringRef.h" +#include namespace llvm { class BasicBlockPass; +class Function; class FunctionPass; class ModulePass; class Pass; @@ -245,7 +247,8 @@ FunctionPass *createJumpThreadingPass(int Threshold = -1); // CFGSimplification - Merge basic blocks, eliminate unreachable blocks, // simplify terminator instructions, etc... // -FunctionPass *createCFGSimplificationPass(int Threshold = -1); +FunctionPass *createCFGSimplificationPass( + int Threshold = -1, std::function Ftor = nullptr); //===----------------------------------------------------------------------===// // diff --git a/lib/CodeGen/IfConversion.cpp b/lib/CodeGen/IfConversion.cpp index 0d59c72cb8f..e861ceb2a66 100644 --- a/lib/CodeGen/IfConversion.cpp +++ b/lib/CodeGen/IfConversion.cpp @@ -170,9 +170,12 @@ namespace { bool PreRegAlloc; bool MadeChange; int FnNum; + std::function PredicateFtor; + public: static char ID; - IfConverter() : MachineFunctionPass(ID), FnNum(-1) { + IfConverter(std::function Ftor = nullptr) + : MachineFunctionPass(ID), FnNum(-1), PredicateFtor(Ftor) { initializeIfConverterPass(*PassRegistry::getPassRegistry()); } @@ -270,6 +273,9 @@ INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo) INITIALIZE_PASS_END(IfConverter, "if-converter", "If Converter", false, false) bool IfConverter::runOnMachineFunction(MachineFunction &MF) { + if (PredicateFtor && !PredicateFtor(*MF.getFunction())) + return false; + const TargetSubtargetInfo &ST = MF.getSubtarget(); TLI = ST.getTargetLowering(); TII = ST.getInstrInfo(); @@ -1691,3 +1697,8 @@ void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI, bool AddEdges) { ToBBI.IsAnalyzed = false; FromBBI.IsAnalyzed = false; } + +FunctionPass * +llvm::createIfConverter(std::function Ftor) { + return new IfConverter(Ftor); +} diff --git a/lib/CodeGen/MachineInstrBundle.cpp b/lib/CodeGen/MachineInstrBundle.cpp index 0690f08d495..cd820ee1ac5 100644 --- a/lib/CodeGen/MachineInstrBundle.cpp +++ b/lib/CodeGen/MachineInstrBundle.cpp @@ -23,11 +23,15 @@ namespace { class UnpackMachineBundles : public MachineFunctionPass { public: static char ID; // Pass identification - UnpackMachineBundles() : MachineFunctionPass(ID) { + UnpackMachineBundles(std::function Ftor = nullptr) + : MachineFunctionPass(ID), PredicateFtor(Ftor) { initializeUnpackMachineBundlesPass(*PassRegistry::getPassRegistry()); } bool runOnMachineFunction(MachineFunction &MF) override; + + private: + std::function PredicateFtor; }; } // end anonymous namespace @@ -37,6 +41,9 @@ INITIALIZE_PASS(UnpackMachineBundles, "unpack-mi-bundles", "Unpack machine instruction bundles", false, false) bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) { + if (PredicateFtor && !PredicateFtor(*MF.getFunction())) + return false; + bool Changed = false; for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { MachineBasicBlock *MBB = &*I; @@ -69,6 +76,10 @@ bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) { return Changed; } +FunctionPass * +llvm::createUnpackMachineBundles(std::function Ftor) { + return new UnpackMachineBundles(Ftor); +} namespace { class FinalizeMachineBundles : public MachineFunctionPass { diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h index d3cc068993e..9550a3a3cad 100644 --- a/lib/Target/ARM/ARM.h +++ b/lib/Target/ARM/ARM.h @@ -16,11 +16,13 @@ #define LLVM_LIB_TARGET_ARM_ARM_H #include "llvm/Support/CodeGen.h" +#include namespace llvm { class ARMAsmPrinter; class ARMBaseTargetMachine; +class Function; class FunctionPass; class ImmutablePass; class MachineInstr; @@ -38,7 +40,8 @@ FunctionPass *createARMConstantIslandPass(); FunctionPass *createMLxExpansionPass(); FunctionPass *createThumb2ITBlockPass(); FunctionPass *createARMOptimizeBarriersPass(); -FunctionPass *createThumb2SizeReductionPass(); +FunctionPass *createThumb2SizeReductionPass( + std::function Ftor = nullptr); void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP); diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 0f98d52084f..0aceaed8751 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -304,10 +304,6 @@ public: return getTM(); } - const ARMSubtarget &getARMSubtarget() const { - return *getARMTargetMachine().getSubtargetImpl(); - } - void addIRPasses() override; bool addPreISel() override; bool addInstSelector() override; @@ -330,10 +326,11 @@ void ARMPassConfig::addIRPasses() { // Cmpxchg instructions are often used with a subsequent comparison to // determine whether it succeeded. We can exploit existing control-flow in // ldrex/strex loops to simplify this, but it needs tidying up. - const ARMSubtarget *Subtarget = &getARMSubtarget(); - if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only()) - if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy) - addPass(createCFGSimplificationPass()); + if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy) + addPass(createCFGSimplificationPass(-1, [this](const Function &F) { + const auto &ST = this->TM->getSubtarget(F); + return ST.hasAnyDataBarrier() && !ST.isThumb1Only(); + })); TargetPassConfig::addIRPasses(); } @@ -390,10 +387,13 @@ void ARMPassConfig::addPreSched2() { if (getOptLevel() != CodeGenOpt::None) { // in v8, IfConversion depends on Thumb instruction widths - if (getARMSubtarget().restrictIT()) - addPass(createThumb2SizeReductionPass()); - if (!getARMSubtarget().isThumb1Only()) - addPass(&IfConverterID); + addPass(createThumb2SizeReductionPass([this](const Function &F) { + return this->TM->getSubtarget(F).restrictIT(); + })); + + addPass(createIfConverter([this](const Function &F) { + return !this->TM->getSubtarget(F).isThumb1Only(); + })); } addPass(createThumb2ITBlockPass()); } @@ -402,8 +402,9 @@ void ARMPassConfig::addPreEmitPass() { addPass(createThumb2SizeReductionPass()); // Constant island pass work on unbundled instructions. - if (getARMSubtarget().isThumb2()) - addPass(&UnpackMachineBundlesID); + addPass(createUnpackMachineBundles([this](const Function &F) { + return this->TM->getSubtarget(F).isThumb2(); + })); // Don't optimize barriers at -O0. if (getOptLevel() != CodeGenOpt::None) diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp index 0ab1ff906c9..d9ab824995c 100644 --- a/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -133,7 +133,7 @@ namespace { class Thumb2SizeReduce : public MachineFunctionPass { public: static char ID; - Thumb2SizeReduce(); + Thumb2SizeReduce(std::function Ftor); const Thumb2InstrInfo *TII; const ARMSubtarget *STI; @@ -198,11 +198,14 @@ namespace { }; SmallVector BlockInfo; + + std::function PredicateFtor; }; char Thumb2SizeReduce::ID = 0; } -Thumb2SizeReduce::Thumb2SizeReduce() : MachineFunctionPass(ID) { +Thumb2SizeReduce::Thumb2SizeReduce(std::function Ftor) + : MachineFunctionPass(ID), PredicateFtor(Ftor) { OptimizeSize = MinimizeSize = false; for (unsigned i = 0, e = array_lengthof(ReduceTable); i != e; ++i) { unsigned FromOpc = ReduceTable[i].WideOpc; @@ -1000,6 +1003,9 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) { } bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) { + if (PredicateFtor && !PredicateFtor(*MF.getFunction())) + return false; + STI = &static_cast(MF.getSubtarget()); if (STI->isThumb1Only() || STI->prefers32BitThumb()) return false; @@ -1025,6 +1031,7 @@ bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) { /// createThumb2SizeReductionPass - Returns an instance of the Thumb2 size /// reduction pass. -FunctionPass *llvm::createThumb2SizeReductionPass() { - return new Thumb2SizeReduce(); +FunctionPass *llvm::createThumb2SizeReductionPass( + std::function Ftor) { + return new Thumb2SizeReduce(Ftor); } diff --git a/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/lib/Transforms/Scalar/SimplifyCFGPass.cpp index 8566cd9736d..f0e3ffdb95a 100644 --- a/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -193,11 +193,18 @@ namespace { struct CFGSimplifyPass : public FunctionPass { static char ID; // Pass identification, replacement for typeid unsigned BonusInstThreshold; - CFGSimplifyPass(int T = -1) : FunctionPass(ID) { + std::function PredicateFtor; + + CFGSimplifyPass(int T = -1, + std::function Ftor = nullptr) + : FunctionPass(ID), PredicateFtor(Ftor) { BonusInstThreshold = (T == -1) ? UserBonusInstThreshold : unsigned(T); initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry()); } bool runOnFunction(Function &F) override { + if (PredicateFtor && !PredicateFtor(F)) + return false; + if (skipOptnoneFunction(F)) return false; @@ -224,7 +231,9 @@ INITIALIZE_PASS_END(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false, false) // Public interface to the CFGSimplification pass -FunctionPass *llvm::createCFGSimplificationPass(int Threshold) { - return new CFGSimplifyPass(Threshold); +FunctionPass * +llvm::createCFGSimplificationPass(int Threshold, + std::function Ftor) { + return new CFGSimplifyPass(Threshold, Ftor); } diff --git a/test/CodeGen/ARM/ifcvt-callback.ll b/test/CodeGen/ARM/ifcvt-callback.ll new file mode 100644 index 00000000000..62a66e745b3 --- /dev/null +++ b/test/CodeGen/ARM/ifcvt-callback.ll @@ -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" }