Index: include/llvm/CodeGen/Passes.h =================================================================== --- include/llvm/CodeGen/Passes.h +++ include/llvm/CodeGen/Passes.h @@ -316,20 +316,30 @@ /// Add a CodeGen pass at this point in the pipeline after checking overrides. /// Return the pass that was added, or zero if no pass was added. + /// @p SkipFPFtor a call-back function that decides if FunctionPass PassID + /// should be skipped. /// @p printAfter if true and adding a machine function pass add an extra /// machine printer pass afterwards /// @p verifyAfter if true and adding a machine function pass add an extra /// machine verification pass afterwards. - AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true, - bool printAfter = true); + AnalysisID + addPass(AnalysisID PassID, + FunctionPass::SkipPassFtorTy SkipFPFtor = + FunctionPass::SkipPassFtorTy(), + bool verifyAfter = true, bool printAfter = true); /// Add a pass to the PassManager if that pass is supposed to be run, as /// determined by the StartAfter and StopAfter options. Takes ownership of the /// pass. + /// @p SkipFPFtor a call-back function that decides if FunctionPass P should + /// be skipped. /// @p printAfter if true and adding a machine function pass add an extra /// machine printer pass afterwards /// @p verifyAfter if true and adding a machine function pass add an extra /// machine verification pass afterwards. + void addPass(Pass *P, FunctionPass::SkipPassFtorTy SkipFPFtor, + bool verifyAfter = true, bool printAfter = true); + void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true); /// addMachinePasses helper to create the target-selected or overriden Index: include/llvm/Pass.h =================================================================== --- include/llvm/Pass.h +++ include/llvm/Pass.h @@ -31,6 +31,7 @@ #include "llvm/Support/Compiler.h" #include +#include namespace llvm { @@ -309,10 +310,22 @@ /// Return what kind of Pass Manager can manage this pass. PassManagerType getPotentialPassManagerType() const override; + typedef std::function SkipPassFtorTy; + + void setSkipPassFtor(SkipPassFtorTy Ftor); + protected: /// skipOptnoneFunction - This function has Attribute::OptimizeNone /// and most transformation passes should skip it. bool skipOptnoneFunction(const Function &F) const; + + bool skipPass(const Function &F) const { + return SkipPassFtor && SkipPassFtor(F); + } + +private: + /// A call-back function that decides if this pass should be skipped. + SkipPassFtorTy SkipPassFtor; }; Index: lib/CodeGen/IfConversion.cpp =================================================================== --- lib/CodeGen/IfConversion.cpp +++ lib/CodeGen/IfConversion.cpp @@ -271,6 +271,9 @@ INITIALIZE_PASS_END(IfConverter, "if-converter", "If Converter", false, false) bool IfConverter::runOnMachineFunction(MachineFunction &MF) { + if (skipPass(*MF.getFunction())) + return false; + const TargetSubtargetInfo &ST = MF.getSubtarget(); TLI = ST.getTargetLowering(); TII = ST.getInstrInfo(); Index: lib/CodeGen/MachineInstrBundle.cpp =================================================================== --- lib/CodeGen/MachineInstrBundle.cpp +++ lib/CodeGen/MachineInstrBundle.cpp @@ -37,6 +37,9 @@ "Unpack machine instruction bundles", false, false) bool UnpackMachineBundles::runOnMachineFunction(MachineFunction &MF) { + if (skipPass(*MF.getFunction())) + return false; + bool Changed = false; for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { MachineBasicBlock *MBB = &*I; Index: lib/CodeGen/Passes.cpp =================================================================== --- lib/CodeGen/Passes.cpp +++ lib/CodeGen/Passes.cpp @@ -271,6 +271,15 @@ /// a later pass or that it should stop after an earlier pass, then do not add /// the pass. Finally, compare the current pass against the StartAfter /// and StopAfter options and change the Started/Stopped flags accordingly. +void TargetPassConfig::addPass(Pass *P, + FunctionPass::SkipPassFtorTy SkipFPFtor, + bool verifyAfter, bool printAfter) { + if (P->getPassKind() == llvm::PT_Function) + static_cast(P)->setSkipPassFtor(SkipFPFtor); + + addPass(P, verifyAfter, printAfter); +} + void TargetPassConfig::addPass(Pass *P, bool verifyAfter, bool printAfter) { assert(!Initialized && "PassConfig is immutable"); @@ -308,8 +317,10 @@ /// /// addPass cannot return a pointer to the pass instance because is internal the /// PassManager and the instance we create here may already be freed. -AnalysisID TargetPassConfig::addPass(AnalysisID PassID, bool verifyAfter, - bool printAfter) { +AnalysisID +TargetPassConfig::addPass(AnalysisID PassID, + FunctionPass::SkipPassFtorTy SkipFPFtor, + bool verifyAfter, bool printAfter) { IdentifyingPassPtr TargetID = getPassSubstitution(PassID); IdentifyingPassPtr FinalPtr = overridePass(PassID, TargetID); if (!FinalPtr.isValid()) @@ -324,7 +335,8 @@ llvm_unreachable("Pass ID not registered"); } AnalysisID FinalID = P->getPassID(); - addPass(P, verifyAfter, printAfter); // Ends the lifetime of P. + addPass(P, SkipFPFtor, verifyAfter, + printAfter); // Ends the lifetime of P. // Add the passes after the pass P if there is any. for (SmallVectorImpl >::iterator @@ -507,7 +519,7 @@ } else { // If the target requests it, assign local variables to stack slots relative // to one another and simplify frame index references where possible. - addPass(&LocalStackSlotAllocationID, false); + addPass(&LocalStackSlotAllocationID, FunctionPass::SkipPassFtorTy(), false); } // Run pre-ra passes. @@ -556,7 +568,7 @@ addPreEmitPass(); - addPass(&StackMapLivenessID, false); + addPass(&StackMapLivenessID, FunctionPass::SkipPassFtorTy(), false); AddingMachinePasses = false; } @@ -568,15 +580,15 @@ // Optimize PHIs before DCE: removing dead PHI cycles may make more // instructions dead. - addPass(&OptimizePHIsID, false); + addPass(&OptimizePHIsID, FunctionPass::SkipPassFtorTy(), false); // This pass merges large allocas. StackSlotColoring is a different pass // which merges spill slots. - addPass(&StackColoringID, false); + addPass(&StackColoringID, FunctionPass::SkipPassFtorTy(), false); // If the target requests it, assign local variables to stack slots relative // to one another and simplify frame index references where possible. - addPass(&LocalStackSlotAllocationID, false); + addPass(&LocalStackSlotAllocationID, FunctionPass::SkipPassFtorTy(), false); // With optimization, dead code should already be eliminated. However // there is one known exception: lowered code for arguments that are only @@ -589,11 +601,11 @@ // loop info, just like LICM and CSE below. addILPOpts(); - addPass(&MachineLICMID, false); - addPass(&MachineCSEID, false); + addPass(&MachineLICMID, FunctionPass::SkipPassFtorTy(), false); + addPass(&MachineCSEID, FunctionPass::SkipPassFtorTy(), false); addPass(&MachineSinkingID); - addPass(&PeepholeOptimizerID, false); + addPass(&PeepholeOptimizerID, FunctionPass::SkipPassFtorTy(), false); // Clean-up the dead code that may have been generated by peephole // rewriting. addPass(&DeadMachineInstructionElimID); @@ -679,8 +691,8 @@ /// Add the minimum set of target-independent passes that are required for /// register allocation. No coalescing or scheduling. void TargetPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) { - addPass(&PHIEliminationID, false); - addPass(&TwoAddressInstructionPassID, false); + addPass(&PHIEliminationID, FunctionPass::SkipPassFtorTy(), false); + addPass(&TwoAddressInstructionPassID, FunctionPass::SkipPassFtorTy(), false); addPass(RegAllocPass); } @@ -689,7 +701,7 @@ /// optimized register allocation, including coalescing, machine instruction /// scheduling, and register allocation itself. void TargetPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) { - addPass(&ProcessImplicitDefsID, false); + addPass(&ProcessImplicitDefsID, FunctionPass::SkipPassFtorTy(), false); // LiveVariables currently requires pure SSA form. // @@ -697,17 +709,17 @@ // LiveVariables can be removed completely, and LiveIntervals can be directly // computed. (We still either need to regenerate kill flags after regalloc, or // preferably fix the scavenger to not depend on them). - addPass(&LiveVariablesID, false); + addPass(&LiveVariablesID, FunctionPass::SkipPassFtorTy(), false); // Edge splitting is smarter with machine loop info. - addPass(&MachineLoopInfoID, false); - addPass(&PHIEliminationID, false); + addPass(&MachineLoopInfoID, FunctionPass::SkipPassFtorTy(), false); + addPass(&PHIEliminationID, FunctionPass::SkipPassFtorTy(), false); // Eventually, we want to run LiveIntervals before PHI elimination. if (EarlyLiveIntervals) - addPass(&LiveIntervalsID, false); + addPass(&LiveIntervalsID, FunctionPass::SkipPassFtorTy(), false); - addPass(&TwoAddressInstructionPassID, false); + addPass(&TwoAddressInstructionPassID, FunctionPass::SkipPassFtorTy(), false); addPass(&RegisterCoalescerID); // PreRA instruction scheduling. @@ -756,13 +768,14 @@ /// Add standard GC passes. bool TargetPassConfig::addGCPasses() { - addPass(&GCMachineCodeAnalysisID, false); + addPass(&GCMachineCodeAnalysisID, FunctionPass::SkipPassFtorTy(), false); return true; } /// Add standard basic block placement passes. void TargetPassConfig::addBlockPlacement() { - if (addPass(&MachineBlockPlacementID, false)) { + if (addPass(&MachineBlockPlacementID, FunctionPass::SkipPassFtorTy(), + false)) { // Run a separate pass to collect block placement statistics. if (EnableBlockPlacementStats) addPass(&MachineBlockPlacementStatsID); Index: lib/IR/Pass.cpp =================================================================== --- lib/IR/Pass.cpp +++ lib/IR/Pass.cpp @@ -140,6 +140,10 @@ return PMT_FunctionPassManager; } +void FunctionPass::setSkipPassFtor(SkipPassFtorTy Ftor) { + SkipPassFtor = Ftor; +} + bool FunctionPass::skipOptnoneFunction(const Function &F) const { if (F.hasFnAttribute(Attribute::OptimizeNone)) { DEBUG(dbgs() << "Skipping pass '" << getPassName() Index: lib/Target/ARM/ARMTargetMachine.cpp =================================================================== --- lib/Target/ARM/ARMTargetMachine.cpp +++ lib/Target/ARM/ARMTargetMachine.cpp @@ -297,10 +297,6 @@ return getTM(); } - const ARMSubtarget &getARMSubtarget() const { - return *getARMTargetMachine().getSubtargetImpl(); - } - void addIRPasses() override; bool addPreISel() override; bool addInstSelector() override; @@ -323,10 +319,11 @@ // 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(), [this](const Function &F) { + const auto &ST = this->TM->getSubtarget(F); + return !ST.hasAnyDataBarrier() || ST.isThumb1Only(); + }); TargetPassConfig::addIRPasses(); } @@ -378,10 +375,14 @@ 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) { + const auto &ST = this->TM->getSubtarget(F); + return !ST.restrictIT(); + }); + addPass(&IfConverterID, [this](const Function &F) { + const auto &ST = this->TM->getSubtarget(F); + return ST.isThumb1Only(); + }); } addPass(createThumb2ITBlockPass()); } @@ -390,8 +391,10 @@ addPass(createThumb2SizeReductionPass()); // Constant island pass work on unbundled instructions. - if (getARMSubtarget().isThumb2()) - addPass(&UnpackMachineBundlesID); + addPass(&UnpackMachineBundlesID, [this](const Function &F) { + const auto &ST = this->TM->getSubtarget(F); + return !ST.isThumb2(); + }); addPass(createARMOptimizeBarriersPass()); addPass(createARMConstantIslandPass()); Index: lib/Target/ARM/Thumb2SizeReduction.cpp =================================================================== --- lib/Target/ARM/Thumb2SizeReduction.cpp +++ lib/Target/ARM/Thumb2SizeReduction.cpp @@ -1002,6 +1002,9 @@ } bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) { + if (skipPass(*MF.getFunction())) + return false; + STI = &static_cast(MF.getSubtarget()); if (STI->isThumb1Only() || STI->prefers32BitThumb()) return false; Index: lib/Target/Hexagon/HexagonTargetMachine.cpp =================================================================== --- lib/Target/Hexagon/HexagonTargetMachine.cpp +++ lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -134,7 +134,7 @@ void HexagonPassConfig::addPreSched2() { addPass(createHexagonCopyToCombine(), false); if (getOptLevel() != CodeGenOpt::None) - addPass(&IfConverterID, false); + addPass(&IfConverterID, FunctionPass::SkipPassFtorTy(), false); addPass(createHexagonSplitConst32AndConst64()); } Index: lib/Target/R600/AMDGPUTargetMachine.cpp =================================================================== --- lib/Target/R600/AMDGPUTargetMachine.cpp +++ lib/Target/R600/AMDGPUTargetMachine.cpp @@ -214,14 +214,14 @@ const AMDGPUSubtarget &ST = *getAMDGPUTargetMachine().getSubtargetImpl(); addPass(createR600EmitClauseMarkers(), false); if (ST.isIfCvtEnabled()) - addPass(&IfConverterID, false); + addPass(&IfConverterID, FunctionPass::SkipPassFtorTy(), false); addPass(createR600ClauseMergePass(*TM), false); } void R600PassConfig::addPreEmitPass() { addPass(createAMDGPUCFGStructurizerPass(), false); addPass(createR600ExpandSpecialInstrsPass(*TM), false); - addPass(&FinalizeMachineBundlesID, false); + addPass(&FinalizeMachineBundlesID, FunctionPass::SkipPassFtorTy(), false); addPass(createR600Packetizer(*TM), false); addPass(createR600ControlFlowFinalizer(*TM), false); } Index: lib/Transforms/Scalar/SimplifyCFGPass.cpp =================================================================== --- lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -198,7 +198,7 @@ initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry()); } bool runOnFunction(Function &F) override { - if (skipOptnoneFunction(F)) + if (skipOptnoneFunction(F) || skipPass(F)) return false; AssumptionCache *AC =