diff options
34 files changed, 214 insertions, 0 deletions
diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index 5926610d1a..9ca55053f5 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -81,6 +81,11 @@ public: /// deleteAnalysisValue - Delete analysis info associated with value V. virtual void deleteAnalysisValue(Value *V, Loop *L) {} + +protected: + /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone + /// and most transformation passes should skip it. + bool skipOptnoneFunction(Loop *L) const; }; class LPPassManager : public FunctionPass, public PMDataManager { diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index 35ec022516..e16144397c 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -307,6 +307,11 @@ public: /// Return what kind of Pass Manager can manage this pass. virtual PassManagerType getPotentialPassManagerType() const; + +protected: + /// skipOptnoneFunction - This function has Attribute::OptimizeNone + /// and most transformation passes should skip it. + bool skipOptnoneFunction(Function &F) const; }; @@ -351,6 +356,11 @@ public: /// Return what kind of Pass Manager can manage this pass. virtual PassManagerType getPotentialPassManagerType() const; + +protected: + /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone + /// and most transformation passes should skip it. + bool skipOptnoneFunction(BasicBlock &BB) const; }; /// If the user specifies the -time-passes argument on an LLVM tool command line diff --git a/lib/Analysis/LoopPass.cpp b/lib/Analysis/LoopPass.cpp index 4775359c50..db69e1325a 100644 --- a/lib/Analysis/LoopPass.cpp +++ b/lib/Analysis/LoopPass.cpp @@ -365,3 +365,17 @@ void LoopPass::assignPassManager(PMStack &PMS, LPPM->add(this); } + +// Containing function has Attribute::OptimizeNone and transformation +// passes should skip it. +bool LoopPass::skipOptnoneFunction(Loop *L) const { + Function *F = L->getHeader()->getParent(); + if (F && F->hasFnAttribute(Attribute::OptimizeNone)) { + // FIXME: Report this to dbgs() only once per function. + DEBUG(dbgs() << "Skipping pass '" << getPassName() + << "' in function " << F->getName() << "\n"); + // FIXME: Delete loop from pass manager's queue? + return true; + } + return false; +} diff --git a/lib/IR/Pass.cpp b/lib/IR/Pass.cpp index 3782e2d7be..84b0b04d69 100644 --- a/lib/IR/Pass.cpp +++ b/lib/IR/Pass.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Pass.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/PassRegistry.h" #include "llvm/Support/Debug.h" @@ -137,6 +138,15 @@ PassManagerType FunctionPass::getPotentialPassManagerType() const { return PMT_FunctionPassManager; } +bool FunctionPass::skipOptnoneFunction(Function &F) const { + if (F.hasFnAttribute(Attribute::OptimizeNone)) { + DEBUG(dbgs() << "Skipping pass '" << getPassName() + << "' on function " << F.getName() << "\n"); + return true; + } + return false; +} + //===----------------------------------------------------------------------===// // BasicBlockPass Implementation // @@ -156,6 +166,18 @@ bool BasicBlockPass::doFinalization(Function &) { return false; } +bool BasicBlockPass::skipOptnoneFunction(BasicBlock &BB) const { + Function *F = BB.getParent(); + if (F && F->hasFnAttribute(Attribute::OptimizeNone)) { + // Report this only once per function. + if (&BB == &F->getEntryBlock()) + DEBUG(dbgs() << "Skipping pass '" << getPassName() + << "' on function " << F->getName() << "\n"); + return true; + } + return false; +} + PassManagerType BasicBlockPass::getPotentialPassManagerType() const { return PMT_BasicBlockPassManager; } diff --git a/lib/Transforms/IPO/LoopExtractor.cpp b/lib/Transforms/IPO/LoopExtractor.cpp index 714e0786f6..f6dda62fa4 100644 --- a/lib/Transforms/IPO/LoopExtractor.cpp +++ b/lib/Transforms/IPO/LoopExtractor.cpp @@ -79,6 +79,9 @@ INITIALIZE_PASS(SingleLoopExtractor, "loop-extract-single", Pass *llvm::createLoopExtractorPass() { return new LoopExtractor(); } bool LoopExtractor::runOnLoop(Loop *L, LPPassManager &LPM) { + if (skipOptnoneFunction(L)) + return false; + // Only visit top-level loops. if (L->getParentLoop()) return false; diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index b453f81de9..04c1499220 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2509,6 +2509,9 @@ public: } bool InstCombiner::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + TD = getAnalysisIfAvailable<DataLayout>(); TLI = &getAnalysis<TargetLibraryInfo>(); // Minimizing size? diff --git a/lib/Transforms/Scalar/ADCE.cpp b/lib/Transforms/Scalar/ADCE.cpp index a3eb07a9f6..a53b23ec44 100644 --- a/lib/Transforms/Scalar/ADCE.cpp +++ b/lib/Transforms/Scalar/ADCE.cpp @@ -50,6 +50,9 @@ char ADCE::ID = 0; INITIALIZE_PASS(ADCE, "adce", "Aggressive Dead Code Elimination", false, false) bool ADCE::runOnFunction(Function& F) { + if (skipOptnoneFunction(F)) + return false; + SmallPtrSet<Instruction*, 128> alive; SmallVector<Instruction*, 128> worklist; diff --git a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index 995782e1bc..7615e8f17b 100644 --- a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -281,6 +281,9 @@ bool CorrelatedValuePropagation::processSwitch(SwitchInst *SI) { } bool CorrelatedValuePropagation::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + LVI = &getAnalysis<LazyValueInfo>(); bool FnChanged = false; diff --git a/lib/Transforms/Scalar/DCE.cpp b/lib/Transforms/Scalar/DCE.cpp index e8a090af40..a4f24df384 100644 --- a/lib/Transforms/Scalar/DCE.cpp +++ b/lib/Transforms/Scalar/DCE.cpp @@ -39,6 +39,8 @@ namespace { initializeDeadInstEliminationPass(*PassRegistry::getPassRegistry()); } virtual bool runOnBasicBlock(BasicBlock &BB) { + if (skipOptnoneFunction(BB)) + return false; TargetLibraryInfo *TLI = getAnalysisIfAvailable<TargetLibraryInfo>(); bool Changed = false; for (BasicBlock::iterator DI = BB.begin(); DI != BB.end(); ) { @@ -89,6 +91,9 @@ char DCE::ID = 0; INITIALIZE_PASS(DCE, "dce", "Dead Code Elimination", false, false) bool DCE::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + TargetLibraryInfo *TLI = getAnalysisIfAvailable<TargetLibraryInfo>(); // Start out with all of the instructions in the worklist... diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index 453dca303d..216f65509e 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -54,6 +54,9 @@ namespace { } virtual bool runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + AA = &getAnalysis<AliasAnalysis>(); MD = &getAnalysis<MemoryDependenceAnalysis>(); DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); diff --git a/lib/Transforms/Scalar/EarlyCSE.cpp b/lib/Transforms/Scalar/EarlyCSE.cpp index d049dd5a99..24baee72dc 100644 --- a/lib/Transforms/Scalar/EarlyCSE.cpp +++ b/lib/Transforms/Scalar/EarlyCSE.cpp @@ -552,6 +552,9 @@ bool EarlyCSE::processNode(DomTreeNode *Node) { bool EarlyCSE::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + std::vector<StackNode *> nodesToProcess; TD = getAnalysisIfAvailable<DataLayout>(); diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 1041dc9af6..955ea1b7fe 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -2313,6 +2313,9 @@ bool GVN::processInstruction(Instruction *I) { /// runOnFunction - This is the main transformation entry point for a function. bool GVN::runOnFunction(Function& F) { + if (skipOptnoneFunction(F)) + return false; + if (!NoLoads) MD = &getAnalysis<MemoryDependenceAnalysis>(); DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index dfcd11fb4c..723af0f02c 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1801,6 +1801,9 @@ void IndVarSimplify::SinkUnusedInvariants(Loop *L) { //===----------------------------------------------------------------------===// bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { + if (skipOptnoneFunction(L)) + return false; + // If LoopSimplify form is not available, stay out of trouble. Some notes: // - LSR currently only supports LoopSimplify-form loops. Indvars' // canonicalization can be a pessimization without LSR to "clean up" diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index b3ec2fc84c..087944a2be 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -148,6 +148,9 @@ FunctionPass *llvm::createJumpThreadingPass() { return new JumpThreading(); } /// runOnFunction - Top level algorithm. /// bool JumpThreading::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + DEBUG(dbgs() << "Jump threading on function '" << F.getName() << "'\n"); TD = getAnalysisIfAvailable<DataLayout>(); TLI = &getAnalysis<TargetLibraryInfo>(); diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp index 1ce0cbc1c4..24ef172794 100644 --- a/lib/Transforms/Scalar/LICM.cpp +++ b/lib/Transforms/Scalar/LICM.cpp @@ -209,6 +209,9 @@ Pass *llvm::createLICMPass() { return new LICM(); } /// times on one loop. /// bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) { + if (skipOptnoneFunction(L)) + return false; + Changed = false; // Get our Loop and Alias Analysis information... diff --git a/lib/Transforms/Scalar/LoopDeletion.cpp b/lib/Transforms/Scalar/LoopDeletion.cpp index cae1253a95..b0155458a4 100644 --- a/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/lib/Transforms/Scalar/LoopDeletion.cpp @@ -130,6 +130,9 @@ 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 &LPM) { + if (skipOptnoneFunction(L)) + return false; + // We can only remove the loop if there is a preheader that we can // branch from after removing it. BasicBlock *preheader = L->getLoopPreheader(); diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index c89cd74c6e..b9c4046c0c 100644 --- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -707,6 +707,9 @@ bool LoopIdiomRecognize::runOnNoncountableLoop() { } bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) { + if (skipOptnoneFunction(L)) + return false; + CurLoop = L; // If the loop could not be converted to canonical form, it must have an diff --git a/lib/Transforms/Scalar/LoopInstSimplify.cpp b/lib/Transforms/Scalar/LoopInstSimplify.cpp index d6ed9d3330..362b8ab63b 100644 --- a/lib/Transforms/Scalar/LoopInstSimplify.cpp +++ b/lib/Transforms/Scalar/LoopInstSimplify.cpp @@ -65,6 +65,9 @@ Pass *llvm::createLoopInstSimplifyPass() { } bool LoopInstSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { + if (skipOptnoneFunction(L)) + return false; + DominatorTreeWrapperPass *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>(); DominatorTree *DT = DTWP ? &DTWP->getDomTree() : 0; diff --git a/lib/Transforms/Scalar/LoopRerollPass.cpp b/lib/Transforms/Scalar/LoopRerollPass.cpp index 144aa7e5c5..7245e0a5c5 100644 --- a/lib/Transforms/Scalar/LoopRerollPass.cpp +++ b/lib/Transforms/Scalar/LoopRerollPass.cpp @@ -1134,6 +1134,9 @@ bool LoopReroll::reroll(Instruction *IV, Loop *L, BasicBlock *Header, } bool LoopReroll::runOnLoop(Loop *L, LPPassManager &LPM) { + if (skipOptnoneFunction(L)) + return false; + AA = &getAnalysis<AliasAnalysis>(); LI = &getAnalysis<LoopInfo>(); SE = &getAnalysis<ScalarEvolution>(); diff --git a/lib/Transforms/Scalar/LoopRotation.cpp b/lib/Transforms/Scalar/LoopRotation.cpp index 9af053b682..04c3b9877b 100644 --- a/lib/Transforms/Scalar/LoopRotation.cpp +++ b/lib/Transforms/Scalar/LoopRotation.cpp @@ -79,6 +79,9 @@ Pass *llvm::createLoopRotatePass() { return new LoopRotate(); } /// Rotate Loop L as many times as possible. Return true if /// the loop is rotated at least once. bool LoopRotate::runOnLoop(Loop *L, LPPassManager &LPM) { + if (skipOptnoneFunction(L)) + return false; + LI = &getAnalysis<LoopInfo>(); TTI = &getAnalysis<TargetTransformInfo>(); diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp index 734d8451fb..b25943011f 100644 --- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -4912,6 +4912,9 @@ void LoopStrengthReduce::getAnalysisUsage(AnalysisUsage &AU) const { } bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager & /*LPM*/) { + if (skipOptnoneFunction(L)) + return false; + bool Changed = false; // Run the main LSR transformation. diff --git a/lib/Transforms/Scalar/LoopUnrollPass.cpp b/lib/Transforms/Scalar/LoopUnrollPass.cpp index 658413497a..450614684e 100644 --- a/lib/Transforms/Scalar/LoopUnrollPass.cpp +++ b/lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -147,6 +147,9 @@ static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls, } bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) { + if (skipOptnoneFunction(L)) + return false; + LoopInfo *LI = &getAnalysis<LoopInfo>(); ScalarEvolution *SE = &getAnalysis<ScalarEvolution>(); const TargetTransformInfo &TTI = getAnalysis<TargetTransformInfo>(); diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp index 32c6412ef7..cfadf9a9d4 100644 --- a/lib/Transforms/Scalar/LoopUnswitch.cpp +++ b/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -382,6 +382,9 @@ static Value *FindLIVLoopCondition(Value *Cond, Loop *L, bool &Changed) { } bool LoopUnswitch::runOnLoop(Loop *L, LPPassManager &LPM_Ref) { + if (skipOptnoneFunction(L)) + return false; + LI = &getAnalysis<LoopInfo>(); LPM = &LPM_Ref; DominatorTreeWrapperPass *DTWP = diff --git a/lib/Transforms/Scalar/LowerAtomic.cpp b/lib/Transforms/Scalar/LowerAtomic.cpp index 8ced4946c8..b28c29f40d 100644 --- a/lib/Transforms/Scalar/LowerAtomic.cpp +++ b/lib/Transforms/Scalar/LowerAtomic.cpp @@ -112,6 +112,8 @@ namespace { initializeLowerAtomicPass(*PassRegistry::getPassRegistry()); } bool runOnBasicBlock(BasicBlock &BB) { + if (skipOptnoneFunction(BB)) + return false; bool Changed = false; for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) { Instruction *Inst = DI++; diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp index d46b1ddcdd..3c24e6d364 100644 --- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -1010,6 +1010,9 @@ bool MemCpyOpt::iterateOnFunction(Function &F) { // function. // bool MemCpyOpt::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + bool MadeChange = false; MD = &getAnalysis<MemoryDependenceAnalysis>(); TD = getAnalysisIfAvailable<DataLayout>(); diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp index 7d31de4d74..1a387f60e1 100644 --- a/lib/Transforms/Scalar/Reassociate.cpp +++ b/lib/Transforms/Scalar/Reassociate.cpp @@ -1971,6 +1971,9 @@ void Reassociate::ReassociateExpression(BinaryOperator *I) { } bool Reassociate::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + // Calculate the rank map for F BuildRankMap(F); diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index 43647207c2..02c64d9ea8 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -1553,6 +1553,9 @@ static void DeleteInstructionInBlock(BasicBlock *BB) { // and return true if the function was modified. // bool SCCP::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n"); const DataLayout *TD = getAnalysisIfAvailable<DataLayout>(); const TargetLibraryInfo *TLI = &getAnalysis<TargetLibraryInfo>(); diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index 08a9bc0926..bed53b832a 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -3572,6 +3572,9 @@ namespace { } bool SROA::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + DEBUG(dbgs() << "SROA function: " << F.getName() << "\n"); C = &F.getContext(); DL = getAnalysisIfAvailable<DataLayout>(); diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index a3c74cd43e..a8186ae342 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -1020,6 +1020,9 @@ ConvertScalar_InsertValue(Value *SV, Value *Old, bool SROA::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + TD = getAnalysisIfAvailable<DataLayout>(); bool Changed = performPromotion(F); diff --git a/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/lib/Transforms/Scalar/SimplifyCFGPass.cpp index 8371f6d352..f1e3ac573e 100644 --- a/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -168,6 +168,9 @@ static bool iterativelySimplifyCFG(Function &F, const TargetTransformInfo &TTI, // simplify the CFG. // bool CFGSimplifyPass::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + const TargetTransformInfo &TTI = getAnalysis<TargetTransformInfo>(); const DataLayout *TD = getAnalysisIfAvailable<DataLayout>(); bool EverChanged = removeUnreachableBlocks(F); diff --git a/lib/Transforms/Scalar/TailRecursionElimination.cpp b/lib/Transforms/Scalar/TailRecursionElimination.cpp index 9fb8ddc3d2..351aee058b 100644 --- a/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -171,6 +171,9 @@ struct AllocaCaptureTracker : public CaptureTracker { } // end anonymous namespace bool TailCallElim::runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + // If this function is a varargs function, we won't be able to PHI the args // right, so don't even try to convert it... if (F.getFunctionType()->isVarArg()) return false; diff --git a/lib/Transforms/Vectorize/BBVectorize.cpp b/lib/Transforms/Vectorize/BBVectorize.cpp index ffbf81b942..0cc1f3962a 100644 --- a/lib/Transforms/Vectorize/BBVectorize.cpp +++ b/lib/Transforms/Vectorize/BBVectorize.cpp @@ -388,6 +388,8 @@ namespace { void combineMetadata(Instruction *K, const Instruction *J); bool vectorizeBB(BasicBlock &BB) { + if (skipOptnoneFunction(BB)) + return false; if (!DT->isReachableFromEntry(&BB)) { DEBUG(dbgs() << "BBV: skipping unreachable " << BB.getName() << " in " << BB.getParent()->getName() << "\n"); @@ -429,6 +431,8 @@ namespace { } virtual bool runOnBasicBlock(BasicBlock &BB) { + // OptimizeNone check deferred to vectorizeBB(). + AA = &getAnalysis<AliasAnalysis>(); DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); SE = &getAnalysis<ScalarEvolution>(); diff --git a/lib/Transforms/Vectorize/SLPVectorizer.cpp b/lib/Transforms/Vectorize/SLPVectorizer.cpp index 80d9ffccaf..9eadfb58be 100644 --- a/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -1771,6 +1771,9 @@ struct SLPVectorizer : public FunctionPass { DominatorTree *DT; virtual bool runOnFunction(Function &F) { + if (skipOptnoneFunction(F)) + return false; + SE = &getAnalysis<ScalarEvolution>(); DL = getAnalysisIfAvailable<DataLayout>(); TTI = &getAnalysis<TargetTransformInfo>(); diff --git a/test/Feature/optnone-opt.ll b/test/Feature/optnone-opt.ll new file mode 100644 index 0000000000..f83e68ccfe --- /dev/null +++ b/test/Feature/optnone-opt.ll @@ -0,0 +1,74 @@ +; RUN: opt -S -debug %s 2>&1 | FileCheck %s --check-prefix=OPT-O0 +; RUN: opt -O1 -S -debug %s 2>&1 | FileCheck %s --check-prefix=OPT-O1 +; RUN: opt -O2 -S -debug %s 2>&1 | FileCheck %s --check-prefix=OPT-O1 --check-prefix=OPT-O2O3 +; RUN: opt -O3 -S -debug %s 2>&1 | FileCheck %s --check-prefix=OPT-O1 --check-prefix=OPT-O2O3 +; RUN: opt -bb-vectorize -dce -die -loweratomic -S -debug %s 2>&1 | FileCheck %s --check-prefix=OPT-MORE +; RUN: opt -indvars -licm -loop-deletion -loop-extract -loop-idiom -loop-instsimplify -loop-reduce -loop-reroll -loop-rotate -loop-unroll -loop-unswitch -S -debug %s 2>&1 | FileCheck %s --check-prefix=OPT-LOOP + +; REQUIRES: asserts + +; This test verifies that we don't run target independent IR-level +; optimizations on optnone functions. + +; Function Attrs: noinline optnone +define i32 @_Z3fooi(i32 %x) #0 { +entry: + %x.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + br label %while.cond + +while.cond: ; preds = %while.body, %entry + %0 = load i32* %x.addr, align 4 + %dec = add nsw i32 %0, -1 + store i32 %dec, i32* %x.addr, align 4 + %tobool = icmp ne i32 %0, 0 + br i1 %tobool, label %while.body, label %while.end + +while.body: ; preds = %while.cond + br label %while.cond + +while.end: ; preds = %while.cond + ret i32 0 +} + +attributes #0 = { optnone noinline } + +; Nothing that runs at -O0 gets skipped. +; OPT-O0-NOT: Skipping pass + +; IR passes run at -O1 and higher. +; OPT-O1-DAG: Skipping pass 'Aggressive Dead Code Elimination' +; OPT-O1-DAG: Skipping pass 'Combine redundant instructions' +; OPT-O1-DAG: Skipping pass 'Dead Store Elimination' +; OPT-O1-DAG: Skipping pass 'Early CSE' +; OPT-O1-DAG: Skipping pass 'Jump Threading' +; OPT-O1-DAG: Skipping pass 'MemCpy Optimization' +; OPT-O1-DAG: Skipping pass 'Reassociate expressions' +; OPT-O1-DAG: Skipping pass 'Simplify the CFG' +; OPT-O1-DAG: Skipping pass 'Sparse Conditional Constant Propagation' +; OPT-O1-DAG: Skipping pass 'SROA' +; OPT-O1-DAG: Skipping pass 'Tail Call Elimination' +; OPT-O1-DAG: Skipping pass 'Value Propagation' + +; Additional IR passes run at -O2 and higher. +; OPT-O2O3-DAG: Skipping pass 'Global Value Numbering' +; OPT-O2O3-DAG: Skipping pass 'SLP Vectorizer' + +; Additional IR passes that opt doesn't turn on by default. +; OPT-MORE-DAG: Skipping pass 'Basic-Block Vectorization' +; OPT-MORE-DAG: Skipping pass 'Dead Code Elimination' +; OPT-MORE-DAG: Skipping pass 'Dead Instruction Elimination' +; OPT-MORE-DAG: Skipping pass 'Lower atomic intrinsics + +; Loop IR passes that opt doesn't turn on by default. +; OPT-LOOP-DAG: Skipping pass 'Delete dead loops' +; OPT-LOOP-DAG: Skipping pass 'Extract loops into new functions' +; OPT-LOOP-DAG: Skipping pass 'Induction Variable Simplification' +; OPT-LOOP-DAG: Skipping pass 'Loop Invariant Code Motion' +; OPT-LOOP-DAG: Skipping pass 'Loop Strength Reduction' +; OPT-LOOP-DAG: Skipping pass 'Recognize loop idioms' +; OPT-LOOP-DAG: Skipping pass 'Reroll loops' +; OPT-LOOP-DAG: Skipping pass 'Rotate Loops' +; OPT-LOOP-DAG: Skipping pass 'Simplify instructions in loops' +; OPT-LOOP-DAG: Skipping pass 'Unroll loops' +; OPT-LOOP-DAG: Skipping pass 'Unswitch loops' |