/// 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 {
/// 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;
};
/// 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
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;
+}
//===----------------------------------------------------------------------===//
#include "llvm/Pass.h"
+#include "llvm/IR/Function.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/PassRegistry.h"
#include "llvm/Support/Debug.h"
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
//
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;
}
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;
}
bool InstCombiner::runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
TD = getAnalysisIfAvailable<DataLayout>();
TLI = &getAnalysis<TargetLibraryInfo>();
// Minimizing size?
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;
}
bool CorrelatedValuePropagation::runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
LVI = &getAnalysis<LazyValueInfo>();
bool FnChanged = false;
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(); ) {
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...
}
virtual bool runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
AA = &getAnalysis<AliasAnalysis>();
MD = &getAnalysis<MemoryDependenceAnalysis>();
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
bool EarlyCSE::runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
std::vector<StackNode *> nodesToProcess;
TD = getAnalysisIfAvailable<DataLayout>();
/// 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();
//===----------------------------------------------------------------------===//
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"
/// 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>();
/// 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...
/// 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();
}
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
}
bool LoopInstSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
+ if (skipOptnoneFunction(L))
+ return false;
+
DominatorTreeWrapperPass *DTWP =
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
DominatorTree *DT = DTWP ? &DTWP->getDomTree() : 0;
}
bool LoopReroll::runOnLoop(Loop *L, LPPassManager &LPM) {
+ if (skipOptnoneFunction(L))
+ return false;
+
AA = &getAnalysis<AliasAnalysis>();
LI = &getAnalysis<LoopInfo>();
SE = &getAnalysis<ScalarEvolution>();
/// 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>();
}
bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager & /*LPM*/) {
+ if (skipOptnoneFunction(L))
+ return false;
+
bool Changed = false;
// Run the main LSR transformation.
}
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>();
}
bool LoopUnswitch::runOnLoop(Loop *L, LPPassManager &LPM_Ref) {
+ if (skipOptnoneFunction(L))
+ return false;
+
LI = &getAnalysis<LoopInfo>();
LPM = &LPM_Ref;
DominatorTreeWrapperPass *DTWP =
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++;
// function.
//
bool MemCpyOpt::runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
bool MadeChange = false;
MD = &getAnalysis<MemoryDependenceAnalysis>();
TD = getAnalysisIfAvailable<DataLayout>();
}
bool Reassociate::runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
// Calculate the rank map for F
BuildRankMap(F);
// 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>();
}
bool SROA::runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
DEBUG(dbgs() << "SROA function: " << F.getName() << "\n");
C = &F.getContext();
DL = getAnalysisIfAvailable<DataLayout>();
bool SROA::runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
TD = getAnalysisIfAvailable<DataLayout>();
bool Changed = performPromotion(F);
// 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);
} // 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;
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");
}
virtual bool runOnBasicBlock(BasicBlock &BB) {
+ // OptimizeNone check deferred to vectorizeBB().
+
AA = &getAnalysis<AliasAnalysis>();
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
SE = &getAnalysis<ScalarEvolution>();
DominatorTree *DT;
virtual bool runOnFunction(Function &F) {
+ if (skipOptnoneFunction(F))
+ return false;
+
SE = &getAnalysis<ScalarEvolution>();
DL = getAnalysisIfAvailable<DataLayout>();
TTI = &getAnalysis<TargetTransformInfo>();
--- /dev/null
+; 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'