aeubanks created this revision.
Herald added a reviewer: bollu.
Herald added subscribers: llvm-commits, cfe-commits, jfb, dexonsmith, 
steven_wu, hiraditya.
Herald added projects: clang, LLVM.

This uses pass instrumentation callbacks to skip optional passes.
PassInfoMixin now declares that passes inheriting from it are by default
optional. Using RequiredPassInfoMixin overrides the pass to be required.
The new OptNoneInstrumentation is part of StandardInstrumentations.

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 behaving incorrectly.
After that is done in following changes, we can remove the flag and
always enable this.

All adaptors/managers must be required, since the pass(es) they are
wrapping may be required.

In the future, opt-bisect will use this same mechanmism of determining
which passes are required/optional.

Depends on D83498 <https://reviews.llvm.org/D83498>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D83519

Files:
  clang/lib/CodeGen/BackendUtil.cpp
  llvm/include/llvm/Analysis/CGSCCPassManager.h
  llvm/include/llvm/IR/PassInstrumentation.h
  llvm/include/llvm/IR/PassManager.h
  llvm/include/llvm/IR/PassManagerInternal.h
  llvm/include/llvm/Passes/StandardInstrumentations.h
  llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
  llvm/lib/IR/PassTimingInfo.cpp
  llvm/lib/LTO/LTOBackend.cpp
  llvm/lib/Passes/StandardInstrumentations.cpp
  llvm/test/Feature/optnone-opt.ll
  llvm/tools/opt/NewPMDriver.cpp
  llvm/unittests/IR/PassBuilderCallbacksTest.cpp
  polly/include/polly/ScopPass.h

Index: polly/include/polly/ScopPass.h
===================================================================
--- polly/include/polly/ScopPass.h
+++ polly/include/polly/ScopPass.h
@@ -204,7 +204,7 @@
 
 template <typename ScopPassT>
 class FunctionToScopPassAdaptor
-    : public PassInfoMixin<FunctionToScopPassAdaptor<ScopPassT>> {
+    : public RequiredPassInfoMixin<FunctionToScopPassAdaptor<ScopPassT>> {
 public:
   explicit FunctionToScopPassAdaptor(ScopPassT Pass) : Pass(std::move(Pass)) {}
 
Index: llvm/unittests/IR/PassBuilderCallbacksTest.cpp
===================================================================
--- llvm/unittests/IR/PassBuilderCallbacksTest.cpp
+++ llvm/unittests/IR/PassBuilderCallbacksTest.cpp
@@ -317,18 +317,20 @@
   PassInstrumentationCallbacks Callbacks;
 
   MockPassInstrumentationCallbacks() {
-    ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true));
+    ON_CALL(*this, runBeforePass(_, _, _)).WillByDefault(Return(true));
   }
-  MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
+  MOCK_METHOD3(runBeforePass,
+               bool(StringRef PassID, bool PassIsRequired, llvm::Any));
   MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any));
   MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
   MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
   MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
 
   void registerPassInstrumentation() {
-    Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) {
-      return this->runBeforePass(P, IR);
-    });
+    Callbacks.registerBeforePassCallback(
+        [this](StringRef P, bool PassIsRequired, llvm::Any IR) {
+          return this->runBeforePass(P, PassIsRequired, IR);
+        });
     Callbacks.registerAfterPassCallback(
         [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); });
     Callbacks.registerAfterPassInvalidatedCallback(
@@ -347,7 +349,7 @@
     // Make sure to avoid ignoring Mock passes/analysis, we definitely want
     // to check these explicitly.
     EXPECT_CALL(*this,
-                runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName)))
+                runBeforePass(Not(HasNameRegex("Mock")), _, HasName(IRName)))
         .Times(AnyNumber());
     EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName)))
         .Times(AnyNumber());
@@ -497,7 +499,7 @@
   // PassInstrumentation calls should happen in-sequence, in the same order
   // as passes/analyses are scheduled.
   ::testing::Sequence PISequence;
-  EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
+  EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), _,
                                              HasName("<string>")))
       .InSequence(PISequence);
   EXPECT_CALL(CallbacksHandle,
@@ -525,7 +527,7 @@
   CallbacksHandle.ignoreNonMockPassInstrumentation("<string>");
 
   // Skip the pass by returning false.
-  EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"),
+  EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), _,
                                              HasName("<string>")))
       .WillOnce(Return(false));
 
@@ -575,7 +577,7 @@
   // as passes/analyses are scheduled.
   ::testing::Sequence PISequence;
   EXPECT_CALL(CallbacksHandle,
-              runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
+              runBeforePass(HasNameRegex("MockPassHandle"), _, HasName("foo")))
       .InSequence(PISequence);
   EXPECT_CALL(
       CallbacksHandle,
@@ -608,7 +610,7 @@
 
   // Skip the pass by returning false.
   EXPECT_CALL(CallbacksHandle,
-              runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo")))
+              runBeforePass(HasNameRegex("MockPassHandle"), _, HasName("foo")))
       .WillOnce(Return(false));
 
   EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0);
@@ -662,7 +664,7 @@
   // as passes/analyses are scheduled.
   ::testing::Sequence PISequence;
   EXPECT_CALL(CallbacksHandle,
-              runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
+              runBeforePass(HasNameRegex("MockPassHandle"), _, HasName("loop")))
       .InSequence(PISequence);
   EXPECT_CALL(
       CallbacksHandle,
@@ -703,7 +705,7 @@
   // as passes/analyses are scheduled.
   ::testing::Sequence PISequence;
   EXPECT_CALL(CallbacksHandle,
-              runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
+              runBeforePass(HasNameRegex("MockPassHandle"), _, HasName("loop")))
       .InSequence(PISequence);
   EXPECT_CALL(
       CallbacksHandle,
@@ -740,7 +742,7 @@
 
   // Skip the pass by returning false.
   EXPECT_CALL(CallbacksHandle,
-              runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
+              runBeforePass(HasNameRegex("MockPassHandle"), _, HasName("loop")))
       .WillOnce(Return(false));
 
   EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0);
@@ -791,8 +793,8 @@
   // PassInstrumentation calls should happen in-sequence, in the same order
   // as passes/analyses are scheduled.
   ::testing::Sequence PISequence;
-  EXPECT_CALL(CallbacksHandle,
-              runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
+  EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), _,
+                                             HasName("(foo)")))
       .InSequence(PISequence);
   EXPECT_CALL(
       CallbacksHandle,
@@ -832,8 +834,8 @@
   // PassInstrumentation calls should happen in-sequence, in the same order
   // as passes/analyses are scheduled.
   ::testing::Sequence PISequence;
-  EXPECT_CALL(CallbacksHandle,
-              runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
+  EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), _,
+                                             HasName("(foo)")))
       .InSequence(PISequence);
   EXPECT_CALL(
       CallbacksHandle,
@@ -869,8 +871,8 @@
   CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
 
   // Skip the pass by returning false.
-  EXPECT_CALL(CallbacksHandle,
-              runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
+  EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), _,
+                                             HasName("(foo)")))
       .WillOnce(Return(false));
 
   // neither Analysis nor Pass are called.
Index: llvm/tools/opt/NewPMDriver.cpp
===================================================================
--- llvm/tools/opt/NewPMDriver.cpp
+++ llvm/tools/opt/NewPMDriver.cpp
@@ -260,7 +260,7 @@
     }
   }
   PassInstrumentationCallbacks PIC;
-  StandardInstrumentations SI;
+  StandardInstrumentations SI(DebugPM);
   SI.registerCallbacks(PIC);
 
   PipelineTuningOptions PTO;
Index: llvm/test/Feature/optnone-opt.ll
===================================================================
--- llvm/test/Feature/optnone-opt.ll
+++ llvm/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 @@
 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
Index: llvm/lib/Passes/StandardInstrumentations.cpp
===================================================================
--- llvm/lib/Passes/StandardInstrumentations.cpp
+++ llvm/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,20 @@
 #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/ErrorHandling.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<bool>
+    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
@@ -233,7 +242,9 @@
   StoreModuleDesc = llvm::forcePrintModuleIR() && llvm::shouldPrintAfterPass();
   if (llvm::shouldPrintBeforePass() || StoreModuleDesc)
     PIC.registerBeforePassCallback(
-        [this](StringRef P, Any IR) { return this->printBeforePass(P, IR); });
+        [this](StringRef P, bool PassIsRequired, Any IR) {
+          return this->printBeforePass(P, IR);
+        });
 
   if (llvm::shouldPrintAfterPass()) {
     PIC.registerAfterPassCallback(
@@ -243,8 +254,38 @@
   }
 }
 
+void OptNoneInstrumentation::registerCallbacks(
+    PassInstrumentationCallbacks &PIC) {
+  PIC.registerBeforePassCallback(
+      [this](StringRef P, bool PassIsRequired, Any IR) {
+        return this->skip(P, PassIsRequired, IR);
+      });
+}
+
+bool OptNoneInstrumentation::skip(StringRef PassID, bool PassIsRequired,
+                                  Any IR) {
+  if (!EnableOptnone)
+    return true;
+  const Function *F = nullptr;
+  if (any_isa<const Function *>(IR)) {
+    F = any_cast<const Function *>(IR);
+  } else if (any_isa<const Loop *>(IR)) {
+    F = any_cast<const Loop *>(IR)->getHeader()->getParent();
+  }
+  if (F) {
+    bool HasOptNone = F->hasOptNone();
+    if (HasOptNone && !PassIsRequired) {
+      if (DebugPM)
+        dbgs() << "Skipping pass: " << PassID << " (optnone)\n";
+      return false;
+    }
+  }
+  return true;
+}
+
 void StandardInstrumentations::registerCallbacks(
     PassInstrumentationCallbacks &PIC) {
   PrintIR.registerCallbacks(PIC);
   TimePasses.registerCallbacks(PIC);
+  OptNone.registerCallbacks(PIC);
 }
Index: llvm/lib/LTO/LTOBackend.cpp
===================================================================
--- llvm/lib/LTO/LTOBackend.cpp
+++ llvm/lib/LTO/LTOBackend.cpp
@@ -197,7 +197,7 @@
   }
 
   PassInstrumentationCallbacks PIC;
-  StandardInstrumentations SI;
+  StandardInstrumentations SI(Conf.DebugPassManager);
   SI.registerCallbacks(PIC);
   PassBuilder PB(TM, Conf.PTO, PGOOpt, &PIC);
   AAManager AA;
Index: llvm/lib/IR/PassTimingInfo.cpp
===================================================================
--- llvm/lib/IR/PassTimingInfo.cpp
+++ llvm/lib/IR/PassTimingInfo.cpp
@@ -270,8 +270,9 @@
   if (!Enabled)
     return;
 
-  PIC.registerBeforePassCallback(
-      [this](StringRef P, Any) { return this->runBeforePass(P); });
+  PIC.registerBeforePassCallback([this](StringRef P, bool PassIsRequired, Any) {
+    return this->runBeforePass(P);
+  });
   PIC.registerAfterPassCallback(
       [this](StringRef P, Any) { this->runAfterPass(P); });
   PIC.registerAfterPassInvalidatedCallback(
Index: llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
===================================================================
--- llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
+++ llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
@@ -229,7 +229,7 @@
 /// LoopAnalysisManager to be used within this run safely.
 template <typename LoopPassT>
 class FunctionToLoopPassAdaptor
-    : public PassInfoMixin<FunctionToLoopPassAdaptor<LoopPassT>> {
+    : public RequiredPassInfoMixin<FunctionToLoopPassAdaptor<LoopPassT>> {
 public:
   explicit FunctionToLoopPassAdaptor(LoopPassT Pass, bool UseMemorySSA = false,
                                      bool DebugLogging = false)
Index: llvm/include/llvm/Passes/StandardInstrumentations.h
===================================================================
--- llvm/include/llvm/Passes/StandardInstrumentations.h
+++ llvm/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 @@
   bool StoreModuleDesc = false;
 };
 
+class OptNoneInstrumentation {
+public:
+  OptNoneInstrumentation(bool DebugPM) : DebugPM(DebugPM) {}
+  void registerCallbacks(PassInstrumentationCallbacks &PIC);
+
+private:
+  bool skip(StringRef PassID, bool PassIsRequired, Any IR);
+
+  bool DebugPM;
+};
+
 /// 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 DebugPM)
+      : PrintIR(), TimePasses(), OptNone(DebugPM) {}
 
   void registerCallbacks(PassInstrumentationCallbacks &PIC);
 
Index: llvm/include/llvm/IR/PassManagerInternal.h
===================================================================
--- llvm/include/llvm/IR/PassManagerInternal.h
+++ llvm/include/llvm/IR/PassManagerInternal.h
@@ -48,6 +48,11 @@
 
   /// Polymorphic method to access the name of a pass.
   virtual StringRef name() const = 0;
+
+  /// Whether or not this pass is required to create executable code.
+  ///
+  /// Used for optnone and opt-bisect.
+  virtual bool isRequired() const = 0;
 };
 
 /// A template wrapper used to implement the polymorphic API.
@@ -81,6 +86,8 @@
 
   StringRef name() const override { return PassT::name(); }
 
+  bool isRequired() const override { return PassT::isRequired(); }
+
   PassT Pass;
 };
 
Index: llvm/include/llvm/IR/PassManager.h
===================================================================
--- llvm/include/llvm/IR/PassManager.h
+++ llvm/include/llvm/IR/PassManager.h
@@ -370,6 +370,7 @@
 /// passes.
 ///
 /// This provides some boilerplate for types that are passes.
+/// Use this for optional (usually optimization) passes.
 template <typename DerivedT> struct PassInfoMixin {
   /// Gets the name of the pass we are mixed into.
   static StringRef name() {
@@ -380,6 +381,20 @@
       Name = Name.drop_front(strlen("llvm::"));
     return Name;
   }
+
+  /// This pass is not required to produce a valid executable.
+  /// Use RequiredPassInfoMixin for required passes.
+  static bool isRequired() { return false; }
+};
+
+/// A CRTP mix-in to automatically provide informational APIs needed for
+/// passes.
+///
+/// Use this for passes required to produce a valid executable.
+template <typename DerivedT>
+struct RequiredPassInfoMixin : PassInfoMixin<DerivedT> {
+  /// This pass is required to produce a valid executable.
+  static bool isRequired() { return true; }
 };
 
 /// A CRTP mix-in that provides informational APIs needed for analysis passes.
@@ -462,7 +477,7 @@
 template <typename IRUnitT,
           typename AnalysisManagerT = AnalysisManager<IRUnitT>,
           typename... ExtraArgTs>
-class PassManager : public PassInfoMixin<
+class PassManager : public RequiredPassInfoMixin<
                         PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
 public:
   /// Construct a pass manager.
@@ -1207,7 +1222,7 @@
 /// may be stale.  Function analyses will not be stale.
 template <typename FunctionPassT>
 class ModuleToFunctionPassAdaptor
-    : public PassInfoMixin<ModuleToFunctionPassAdaptor<FunctionPassT>> {
+    : public RequiredPassInfoMixin<ModuleToFunctionPassAdaptor<FunctionPassT>> {
 public:
   explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass)
       : Pass(std::move(Pass)) {}
Index: llvm/include/llvm/IR/PassInstrumentation.h
===================================================================
--- llvm/include/llvm/IR/PassInstrumentation.h
+++ llvm/include/llvm/IR/PassInstrumentation.h
@@ -75,7 +75,7 @@
   // already invalidated IRUnit is unsafe. There are ways to handle invalidated IRUnits
   // in a safe way, and we might pursue that as soon as there is a useful instrumentation
   // that needs it.
-  using BeforePassFunc = bool(StringRef, Any);
+  using BeforePassFunc = bool(StringRef, bool, Any);
   using AfterPassFunc = void(StringRef, Any);
   using AfterPassInvalidatedFunc = void(StringRef);
   using BeforeAnalysisFunc = void(StringRef, Any);
@@ -147,7 +147,7 @@
 
     bool ShouldRun = true;
     for (auto &C : Callbacks->BeforePassCallbacks)
-      ShouldRun &= C(Pass.name(), llvm::Any(&IR));
+      ShouldRun &= C(Pass.name(), Pass.isRequired(), llvm::Any(&IR));
     return ShouldRun;
   }
 
Index: llvm/include/llvm/Analysis/CGSCCPassManager.h
===================================================================
--- llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -327,7 +327,8 @@
 /// within this run safely.
 template <typename CGSCCPassT>
 class ModuleToPostOrderCGSCCPassAdaptor
-    : public PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>> {
+    : public RequiredPassInfoMixin<
+          ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>> {
 public:
   explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
       : Pass(std::move(Pass)) {}
@@ -444,7 +445,7 @@
 /// within this run safely.
 template <typename FunctionPassT>
 class CGSCCToFunctionPassAdaptor
-    : public PassInfoMixin<CGSCCToFunctionPassAdaptor<FunctionPassT>> {
+    : public RequiredPassInfoMixin<CGSCCToFunctionPassAdaptor<FunctionPassT>> {
 public:
   explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
       : Pass(std::move(Pass)) {}
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -1148,7 +1148,7 @@
   PTO.Coroutines = LangOpts.Coroutines;
 
   PassInstrumentationCallbacks PIC;
-  StandardInstrumentations SI;
+  StandardInstrumentations SI(CodeGenOpts.DebugPassManager);
   SI.registerCallbacks(PIC);
   PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to