summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Analysis/LoopPass.h5
-rw-r--r--include/llvm/Pass.h10
-rw-r--r--lib/Analysis/LoopPass.cpp14
-rw-r--r--lib/IR/Pass.cpp22
-rw-r--r--lib/Transforms/IPO/LoopExtractor.cpp3
-rw-r--r--lib/Transforms/InstCombine/InstructionCombining.cpp3
-rw-r--r--lib/Transforms/Scalar/ADCE.cpp3
-rw-r--r--lib/Transforms/Scalar/CorrelatedValuePropagation.cpp3
-rw-r--r--lib/Transforms/Scalar/DCE.cpp5
-rw-r--r--lib/Transforms/Scalar/DeadStoreElimination.cpp3
-rw-r--r--lib/Transforms/Scalar/EarlyCSE.cpp3
-rw-r--r--lib/Transforms/Scalar/GVN.cpp3
-rw-r--r--lib/Transforms/Scalar/IndVarSimplify.cpp3
-rw-r--r--lib/Transforms/Scalar/JumpThreading.cpp3
-rw-r--r--lib/Transforms/Scalar/LICM.cpp3
-rw-r--r--lib/Transforms/Scalar/LoopDeletion.cpp3
-rw-r--r--lib/Transforms/Scalar/LoopIdiomRecognize.cpp3
-rw-r--r--lib/Transforms/Scalar/LoopInstSimplify.cpp3
-rw-r--r--lib/Transforms/Scalar/LoopRerollPass.cpp3
-rw-r--r--lib/Transforms/Scalar/LoopRotation.cpp3
-rw-r--r--lib/Transforms/Scalar/LoopStrengthReduce.cpp3
-rw-r--r--lib/Transforms/Scalar/LoopUnrollPass.cpp3
-rw-r--r--lib/Transforms/Scalar/LoopUnswitch.cpp3
-rw-r--r--lib/Transforms/Scalar/LowerAtomic.cpp2
-rw-r--r--lib/Transforms/Scalar/MemCpyOptimizer.cpp3
-rw-r--r--lib/Transforms/Scalar/Reassociate.cpp3
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp3
-rw-r--r--lib/Transforms/Scalar/SROA.cpp3
-rw-r--r--lib/Transforms/Scalar/ScalarReplAggregates.cpp3
-rw-r--r--lib/Transforms/Scalar/SimplifyCFGPass.cpp3
-rw-r--r--lib/Transforms/Scalar/TailRecursionElimination.cpp3
-rw-r--r--lib/Transforms/Vectorize/BBVectorize.cpp4
-rw-r--r--lib/Transforms/Vectorize/SLPVectorizer.cpp3
-rw-r--r--test/Feature/optnone-opt.ll74
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'