From c136b2bbc84b00a8ea9520cf5b45758df7681684 Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Tue, 21 Jul 2020 09:48:22 -0700 Subject: [PATCH] [NewPM] Support optnone under new pass manager OptNoneInstrumentation is part of StandardInstrumentations. It skips functions (or loops) that are marked optnone. The feature of skipping optional passes for optnone functions under NPM is gated on a -enable-npm-optnone flag. Currently it is by default false. That is because we still need to mark all required passes to be required. Otherwise optnone functions will start having incorrect semantics. After that is done in following changes, we can remove the flag and always enable this. Reviewed By: ychen Differential Revision: https://reviews.llvm.org/D83519 --- .../llvm/Passes/StandardInstrumentations.h | 16 +++- lib/LTO/LTOBackend.cpp | 2 +- lib/Passes/StandardInstrumentations.cpp | 32 ++++++++ test/Feature/optnone-opt.ll | 81 ++++++++++++------- tools/opt/NewPMDriver.cpp | 2 +- 5 files changed, 103 insertions(+), 30 deletions(-) diff --git a/include/llvm/Passes/StandardInstrumentations.h b/include/llvm/Passes/StandardInstrumentations.h index 3d3002eecce..bd8b886a2bb 100644 --- a/include/llvm/Passes/StandardInstrumentations.h +++ b/include/llvm/Passes/StandardInstrumentations.h @@ -16,6 +16,7 @@ #define LLVM_PASSES_STANDARDINSTRUMENTATIONS_H #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/IR/PassInstrumentation.h" #include "llvm/IR/PassTimingInfo.h" @@ -53,14 +54,27 @@ private: bool StoreModuleDesc = false; }; +class OptNoneInstrumentation { +public: + OptNoneInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} + void registerCallbacks(PassInstrumentationCallbacks &PIC); + +private: + bool skip(StringRef PassID, Any IR); + + bool DebugLogging; +}; + /// This class provides an interface to register all the standard pass /// instrumentations and manages their state (if any). class StandardInstrumentations { PrintIRInstrumentation PrintIR; TimePassesHandler TimePasses; + OptNoneInstrumentation OptNone; public: - StandardInstrumentations() = default; + StandardInstrumentations(bool DebugLogging) + : PrintIR(), TimePasses(), OptNone(DebugLogging) {} void registerCallbacks(PassInstrumentationCallbacks &PIC); diff --git a/lib/LTO/LTOBackend.cpp b/lib/LTO/LTOBackend.cpp index 0c395f9bbf2..ca29548a4d7 100644 --- a/lib/LTO/LTOBackend.cpp +++ b/lib/LTO/LTOBackend.cpp @@ -197,7 +197,7 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM, } PassInstrumentationCallbacks PIC; - StandardInstrumentations SI; + StandardInstrumentations SI(Conf.DebugPassManager); SI.registerCallbacks(PIC); PassBuilder PB(TM, Conf.PTO, PGOOpt, &PIC); AAManager AA; diff --git a/lib/Passes/StandardInstrumentations.cpp b/lib/Passes/StandardInstrumentations.cpp index 1e1a6b98a65..22a7103715d 100644 --- a/lib/Passes/StandardInstrumentations.cpp +++ b/lib/Passes/StandardInstrumentations.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Passes/StandardInstrumentations.h" +#include "llvm/ADT/Any.h" #include "llvm/ADT/Optional.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LazyCallGraph.h" @@ -21,12 +22,19 @@ #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassInstrumentation.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; +// TODO: remove once all required passes are marked as such. +static cl::opt + EnableOptnone("enable-npm-optnone", cl::init(false), + cl::desc("Enable skipping optional passes optnone functions " + "under new pass manager")); + namespace { /// Extracting Module out of \p IR unit. Also fills a textual description @@ -243,8 +251,32 @@ void PrintIRInstrumentation::registerCallbacks( } } +void OptNoneInstrumentation::registerCallbacks( + PassInstrumentationCallbacks &PIC) { + PIC.registerBeforePassCallback( + [this](StringRef P, Any IR) { return this->skip(P, IR); }); +} + +bool OptNoneInstrumentation::skip(StringRef PassID, Any IR) { + if (!EnableOptnone) + return true; + const Function *F = nullptr; + if (any_isa(IR)) { + F = any_cast(IR); + } else if (any_isa(IR)) { + F = any_cast(IR)->getHeader()->getParent(); + } + if (F && F->hasOptNone()) { + if (DebugLogging) + dbgs() << "Skipping pass: " << PassID << " (optnone)\n"; + return false; + } + return true; +} + void StandardInstrumentations::registerCallbacks( PassInstrumentationCallbacks &PIC) { PrintIR.registerCallbacks(PIC); TimePasses.registerCallbacks(PIC); + OptNone.registerCallbacks(PIC); } diff --git a/test/Feature/optnone-opt.ll b/test/Feature/optnone-opt.ll index 27418063d55..3af0ce8d0fd 100644 --- a/test/Feature/optnone-opt.ll +++ b/test/Feature/optnone-opt.ll @@ -1,9 +1,15 @@ -; 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 -dce -die -gvn-hoist -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 +; RUN: opt -S -debug -enable-new-pm=0 %s 2>&1 | FileCheck %s --check-prefix=O0 +; RUN: opt -O1 -S -debug -enable-new-pm=0 %s 2>&1 | FileCheck %s --check-prefix=O1 +; RUN: opt -O2 -S -debug -enable-new-pm=0 %s 2>&1 | FileCheck %s --check-prefix=O1 --check-prefix=O2O3 +; RUN: opt -O3 -S -debug -enable-new-pm=0 %s 2>&1 | FileCheck %s --check-prefix=O1 --check-prefix=O2O3 +; RUN: opt -dce -die -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 ; REQUIRES: asserts @@ -34,32 +40,53 @@ while.end: ; preds = %while.cond attributes #0 = { optnone noinline } ; Nothing that runs at -O0 gets skipped. -; OPT-O0-NOT: Skipping pass +; O0-NOT: Skipping pass +; NPM-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 'Early CSE' -; OPT-O1-DAG: Skipping pass 'Reassociate expressions' -; OPT-O1-DAG: Skipping pass 'Simplify the CFG' -; OPT-O1-DAG: Skipping pass 'Sparse Conditional Constant Propagation' +; O1-DAG: Skipping pass 'Aggressive Dead Code Elimination' +; O1-DAG: Skipping pass 'Combine redundant instructions' +; O1-DAG: Skipping pass 'Early CSE' +; 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 +; NPM-O1-DAG: Skipping pass: SROA +; NPM-O1-DAG: Skipping pass: EarlyCSEPass +; NPM-O1-DAG: Skipping pass: LowerExpectIntrinsicPass +; NPM-O1-DAG: Skipping pass: PromotePass +; NPM-O1-DAG: Skipping pass: InstCombinePass ; Additional IR passes run at -O2 and higher. -; OPT-O2O3-DAG: Skipping pass 'Global Value Numbering' -; OPT-O2O3-DAG: Skipping pass 'SLP Vectorizer' +; O2O3-DAG: Skipping pass 'Global Value Numbering' +; O2O3-DAG: Skipping pass 'SLP Vectorizer' +; NPM-O2O3-DAG: Skipping pass: GVN +; NPM-O2O3-DAG: Skipping pass: SLPVectorizerPass ; Additional IR passes that opt doesn't turn on by default. -; OPT-MORE-DAG: Skipping pass 'Dead Code Elimination' -; OPT-MORE-DAG: Skipping pass 'Dead Instruction Elimination' +; MORE-DAG: Skipping pass 'Dead Code Elimination' +; MORE-DAG: Skipping pass 'Dead Instruction Elimination' +; NPM-MORE-DAG: Skipping pass: GVNHoistPass +; NPM-MORE-DAG: Skipping pass: LowerAtomicPass ; Loop IR passes that opt doesn't turn on by default. -; OPT-LOOP-DAG: Skipping pass 'Delete dead loops' -; 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' +; LOOP-DAG: Skipping pass 'Delete dead loops' +; LOOP-DAG: Skipping pass 'Induction Variable Simplification' +; LOOP-DAG: Skipping pass 'Loop Invariant Code Motion' +; LOOP-DAG: Skipping pass 'Loop Strength Reduction' +; LOOP-DAG: Skipping pass 'Recognize loop idioms' +; LOOP-DAG: Skipping pass 'Reroll loops' +; LOOP-DAG: Skipping pass 'Rotate Loops' +; LOOP-DAG: Skipping pass 'Simplify instructions in loops' +; LOOP-DAG: Skipping pass 'Unroll loops' +; LOOP-DAG: Skipping pass 'Unswitch loops' +; NPM-LOOP-DAG: Skipping pass: LoopSimplifyPass +; NPM-LOOP-DAG: Skipping pass: LCSSAPass +; NPM-LOOP-DAG: Skipping pass: IndVarSimplifyPass +; NPM-LOOP-DAG: Skipping pass: SimpleLoopUnswitchPass +; NPM-LOOP-DAG: Skipping pass: LoopUnrollPass +; NPM-LOOP-DAG: Skipping pass: LoopStrengthReducePass +; NPM-LOOP-DAG: Skipping pass: LoopDeletionPass +; NPM-LOOP-DAG: Skipping pass: LICMPass +; NPM-LOOP-DAG: Skipping pass: LoopIdiomRecognizePass +; NPM-LOOP-DAG: Skipping pass: LoopInstSimplifyPass diff --git a/tools/opt/NewPMDriver.cpp b/tools/opt/NewPMDriver.cpp index 47c9cfc65e7..acaa57540a1 100644 --- a/tools/opt/NewPMDriver.cpp +++ b/tools/opt/NewPMDriver.cpp @@ -261,7 +261,7 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM, } } PassInstrumentationCallbacks PIC; - StandardInstrumentations SI; + StandardInstrumentations SI(DebugPM); SI.registerCallbacks(PIC); PipelineTuningOptions PTO;