diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h --- a/llvm/include/llvm/IR/PassInstrumentation.h +++ b/llvm/include/llvm/IR/PassInstrumentation.h @@ -124,16 +124,24 @@ private: friend class PassInstrumentation; + /// These are only run on passes that are not required. They return false when + /// an optional pass should be skipped. SmallVector, 4> BeforePassCallbacks; + /// These are run on passes that are skipped. SmallVector, 4> BeforeSkippedPassCallbacks; + /// These are run on passes that are about to be run. SmallVector, 4> BeforeNonSkippedPassCallbacks; + /// These are run on passes that have just run. SmallVector, 4> AfterPassCallbacks; + /// These are run passes that have just run on invalidated IR. SmallVector, 4> AfterPassInvalidatedCallbacks; + /// These are run on analyses that are about to be run. SmallVector, 4> BeforeAnalysisCallbacks; + /// These are run on analyses that have been run. SmallVector, 4> AfterAnalysisCallbacks; }; @@ -173,16 +181,19 @@ /// BeforePass instrumentation point - takes \p Pass instance to be executed /// and constant reference to IR it operates on. \Returns true if pass is - /// allowed to be executed. + /// allowed to be executed. These are only run on optional pass since required + /// passes must always be run. This allows these callbacks to print info when + /// they want to skip a pass. template bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const { if (!Callbacks) return true; bool ShouldRun = true; - for (auto &C : Callbacks->BeforePassCallbacks) - ShouldRun &= C(Pass.name(), llvm::Any(&IR)); - ShouldRun = ShouldRun || isRequired(Pass); + if (!isRequired(Pass)) { + for (auto &C : Callbacks->BeforePassCallbacks) + ShouldRun &= C(Pass.name(), llvm::Any(&IR)); + } if (ShouldRun) { for (auto &C : Callbacks->BeforeNonSkippedPassCallbacks) diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h --- a/llvm/include/llvm/Passes/StandardInstrumentations.h +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h @@ -59,10 +59,12 @@ class OptNoneInstrumentation { public: + OptNoneInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} void registerCallbacks(PassInstrumentationCallbacks &PIC); private: - bool skip(StringRef PassID, Any IR); + bool DebugLogging; + bool shouldRun(StringRef PassID, Any IR); }; // Debug logging for transformation and analysis passes. @@ -236,7 +238,8 @@ public: StandardInstrumentations(bool DebugLogging, bool VerifyEach = false) - : PrintPass(DebugLogging), Verify(DebugLogging), VerifyEach(VerifyEach) {} + : PrintPass(DebugLogging), OptNone(DebugLogging), Verify(DebugLogging), + VerifyEach(VerifyEach) {} void registerCallbacks(PassInstrumentationCallbacks &PIC); diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp --- a/llvm/lib/Passes/StandardInstrumentations.cpp +++ b/llvm/lib/Passes/StandardInstrumentations.cpp @@ -347,10 +347,8 @@ if (!PrintChanged) return; - PIC.registerBeforePassCallback([this](StringRef P, Any IR) { - saveIRBeforePass(IR, P); - return true; - }); + PIC.registerBeforeNonSkippedPassCallback( + [this](StringRef P, Any IR) { saveIRBeforePass(IR, P); }); PIC.registerAfterPassCallback( [this](StringRef P, Any IR, const PreservedAnalyses &) { @@ -522,10 +520,10 @@ void OptNoneInstrumentation::registerCallbacks( PassInstrumentationCallbacks &PIC) { PIC.registerBeforePassCallback( - [this](StringRef P, Any IR) { return this->skip(P, IR); }); + [this](StringRef P, Any IR) { return this->shouldRun(P, IR); }); } -bool OptNoneInstrumentation::skip(StringRef PassID, Any IR) { +bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) { if (!EnableOptnone) return true; const Function *F = nullptr; @@ -534,7 +532,12 @@ } else if (any_isa(IR)) { F = any_cast(IR)->getHeader()->getParent(); } - return !(F && F->hasOptNone()); + bool ShouldRun = !(F && F->hasOptNone()); + if (!ShouldRun && DebugLogging) { + errs() << "Skipping pass " << PassID << " on " << F->getName() + << " due to optnone attribute\n"; + } + return ShouldRun; } void PrintPassInstrumentation::registerCallbacks( diff --git a/llvm/test/Feature/optnone-opt.ll b/llvm/test/Feature/optnone-opt.ll --- a/llvm/test/Feature/optnone-opt.ll +++ b/llvm/test/Feature/optnone-opt.ll @@ -4,12 +4,13 @@ ; RUN: opt -O3 -S -debug -enable-new-pm=0 %s 2>&1 | FileCheck %s --check-prefix=O1 --check-prefix=O2O3 ; RUN: opt -dce -gvn-hoist -loweratomic -S -debug -enable-new-pm=0 %s 2>&1 | FileCheck %s --check-prefix=MORE ; RUN: opt -indvars -licm -loop-deletion -loop-extract -loop-idiom -loop-instsimplify -loop-reduce -loop-reroll -loop-rotate -loop-unroll -loop-unswitch -enable-new-pm=0 -S -debug %s 2>&1 | FileCheck %s --check-prefix=LOOP -; RUN: opt -enable-npm-optnone -S -debug-pass-manager -enable-new-pm %s 2>&1 | FileCheck %s --check-prefix=NPM-O0 -; RUN: opt -enable-npm-optnone -O1 -S -debug-pass-manager -enable-new-pm %s 2>&1 | FileCheck %s --check-prefix=NPM-O1 -; RUN: opt -enable-npm-optnone -O2 -S -debug-pass-manager -enable-new-pm %s 2>&1 | FileCheck %s --check-prefix=NPM-O1 --check-prefix=NPM-O2O3 -; RUN: opt -enable-npm-optnone -O3 -S -debug-pass-manager -enable-new-pm %s 2>&1 | FileCheck %s --check-prefix=NPM-O1 --check-prefix=NPM-O2O3 -; RUN: opt -enable-npm-optnone -dce -gvn-hoist -loweratomic -S -debug-pass-manager -enable-new-pm %s 2>&1 | FileCheck %s --check-prefix=NPM-MORE -; RUN: opt -enable-npm-optnone -indvars -licm -loop-deletion -loop-idiom -loop-instsimplify -loop-reduce -loop-unroll -simple-loop-unswitch -S -debug-pass-manager -enable-new-pm %s 2>&1 | FileCheck %s --check-prefix=NPM-LOOP +; RUN: opt -enable-npm-optnone -passes='default' -S -debug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=NPM-O0 +; RUN: opt -enable-npm-optnone -passes='default' -S -debug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=NPM-O1 +; RUN: opt -enable-npm-optnone -passes='default' -S -debug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=NPM-O1 --check-prefix=NPM-O2O3 +; RUN: opt -enable-npm-optnone -passes='default' -S -debug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=NPM-O1 --check-prefix=NPM-O2O3 +; RUN: opt -enable-npm-optnone -passes='dce,gvn-hoist,loweratomic' -S -debug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=NPM-MORE +; RUN: opt -enable-npm-optnone -passes='loop(indvars,licm,loop-deletion,loop-idiom,loop-instsimplify,loop-reduce,simple-loop-unswitch),loop-unroll' -S -debug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=NPM-LOOP +; RUN: opt -enable-npm-optnone -passes='instsimplify,verify' -S -debug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=NPM-REQUIRED ; REQUIRES: asserts @@ -17,7 +18,7 @@ ; optimizations on optnone functions. ; Function Attrs: noinline optnone -define i32 @_Z3fooi(i32 %x) #0 { +define i32 @foo(i32 %x) #0 { entry: %x.addr = alloca i32, align 4 store i32 %x, i32* %x.addr, align 4 @@ -50,7 +51,7 @@ ; O1-DAG: Skipping pass 'Reassociate expressions' ; O1-DAG: Skipping pass 'Simplify the CFG' ; O1-DAG: Skipping pass 'Sparse Conditional Constant Propagation' -; NPM-O1-DAG: Skipping pass: SimplifyCFGPass on {{.*}}foo +; NPM-O1-DAG: Skipping pass: SimplifyCFGPass on foo ; NPM-O1-DAG: Skipping pass: SROA ; NPM-O1-DAG: Skipping pass: EarlyCSEPass ; NPM-O1-DAG: Skipping pass: LowerExpectIntrinsicPass @@ -81,7 +82,7 @@ ; LOOP-DAG: Skipping pass 'Unswitch loops' ; LoopPassManager should not be skipped over an optnone function ; NPM-LOOP-NOT: Skipping pass: PassManager -; NPM-LOOP-DAG: Skipping pass: LoopSimplifyPass on {{.*}}foo +; NPM-LOOP-DAG: Skipping pass: LoopSimplifyPass on foo ; NPM-LOOP-DAG: Skipping pass: LCSSAPass ; NPM-LOOP-DAG: Skipping pass: IndVarSimplifyPass ; NPM-LOOP-DAG: Skipping pass: SimpleLoopUnswitchPass @@ -91,3 +92,9 @@ ; NPM-LOOP-DAG: Skipping pass: LICMPass ; NPM-LOOP-DAG: Skipping pass: LoopIdiomRecognizePass ; NPM-LOOP-DAG: Skipping pass: LoopInstSimplifyPass + +; NPM-REQUIRED-DAG: Skipping pass: InstSimplifyPass +; NPM-REQUIRED-DAG: Skipping pass InstSimplifyPass on foo due to optnone attribute +; NPM-REQUIRED-DAG: Running pass: VerifierPass +; NPM-REQUIRED-NOT: Skipping pass: VerifyPass +; NPM-REQUIRED-NOT: Skipping pass VerifyPass on foo due to optnone attribute