MLIR  15.0.0git
Pass.h
Go to the documentation of this file.
1 //===- Pass.h - Base classes for compiler passes ----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef MLIR_PASS_PASS_H
10 #define MLIR_PASS_PASS_H
11 
13 #include "mlir/Pass/PassRegistry.h"
15 #include "llvm/ADT/PointerIntPair.h"
16 #include "llvm/ADT/Statistic.h"
17 
18 namespace mlir {
19 namespace detail {
20 class OpToOpPassAdaptor;
21 struct OpPassManagerImpl;
22 
23 /// The state for a single execution of a pass. This provides a unified
24 /// interface for accessing and initializing necessary state for pass execution.
29  : irAndPassFailed(ir, false), analysisManager(analysisManager),
31 
32  /// The current operation being transformed and a bool for if the pass
33  /// signaled a failure.
34  llvm::PointerIntPair<Operation *, 1, bool> irAndPassFailed;
35 
36  /// The analysis manager for the operation.
38 
39  /// The set of preserved analyses for the current execution.
41 
42  /// This is a callback in the PassManager that allows to schedule dynamic
43  /// pipelines that will be rooted at the provided operation.
45 };
46 } // namespace detail
47 
48 /// The abstract base pass class. This class contains information describing the
49 /// derived pass object, e.g its kind and abstract TypeID.
50 class Pass {
51 public:
52  virtual ~Pass() = default;
53 
54  /// Returns the unique identifier that corresponds to this pass.
55  TypeID getTypeID() const { return passID; }
56 
57  /// Returns the pass info for the specified pass class or null if unknown.
58  static const PassInfo *lookupPassInfo(StringRef passArg);
59 
60  /// Returns the pass info for this pass, or null if unknown.
61  const PassInfo *lookupPassInfo() const {
62  return lookupPassInfo(getArgument());
63  }
64 
65  /// Returns the derived pass name.
66  virtual StringRef getName() const = 0;
67 
68  /// Register dependent dialects for the current pass.
69  /// A pass is expected to register the dialects it will create entities for
70  /// (Operations, Types, Attributes), other than dialect that exists in the
71  /// input. For example, a pass that converts from Linalg to Affine would
72  /// register the Affine dialect but does not need to register Linalg.
73  virtual void getDependentDialects(DialectRegistry &registry) const {}
74 
75  /// Return the command line argument used when registering this pass. Return
76  /// an empty string if one does not exist.
77  virtual StringRef getArgument() const { return ""; }
78 
79  /// Return the command line description used when registering this pass.
80  /// Return an empty string if one does not exist.
81  virtual StringRef getDescription() const { return ""; }
82 
83  /// Returns the name of the operation that this pass operates on, or None if
84  /// this is a generic OperationPass.
85  Optional<StringRef> getOpName() const { return opName; }
86 
87  //===--------------------------------------------------------------------===//
88  // Options
89  //===--------------------------------------------------------------------===//
90 
91  /// This class represents a specific pass option, with a provided data type.
92  template <typename DataType,
93  typename OptionParser = detail::PassOptions::OptionParser<DataType>>
94  struct Option : public detail::PassOptions::Option<DataType, OptionParser> {
95  template <typename... Args>
96  Option(Pass &parent, StringRef arg, Args &&...args)
97  : detail::PassOptions::Option<DataType, OptionParser>(
98  parent.passOptions, arg, std::forward<Args>(args)...) {}
100  };
101  /// This class represents a specific pass option that contains a list of
102  /// values of the provided data type.
103  template <typename DataType,
104  typename OptionParser = detail::PassOptions::OptionParser<DataType>>
105  struct ListOption
106  : public detail::PassOptions::ListOption<DataType, OptionParser> {
107  template <typename... Args>
108  ListOption(Pass &parent, StringRef arg, Args &&...args)
109  : detail::PassOptions::ListOption<DataType, OptionParser>(
110  parent.passOptions, arg, std::forward<Args>(args)...) {}
112  };
113 
114  /// Attempt to initialize the options of this pass from the given string.
115  /// Derived classes may override this method to hook into the point at which
116  /// options are initialized, but should generally always invoke this base
117  /// class variant.
118  virtual LogicalResult initializeOptions(StringRef options);
119 
120  /// Prints out the pass in the textual representation of pipelines. If this is
121  /// an adaptor pass, print with the op_name(sub_pass,...) format.
122  void printAsTextualPipeline(raw_ostream &os);
123 
124  //===--------------------------------------------------------------------===//
125  // Statistics
126  //===--------------------------------------------------------------------===//
127 
128  /// This class represents a single pass statistic. This statistic functions
129  /// similarly to an unsigned integer value, and may be updated and incremented
130  /// accordingly. This class can be used to provide additional information
131  /// about the transformations and analyses performed by a pass.
132  class Statistic : public llvm::Statistic {
133  public:
134  /// The statistic is initialized by the pass owner, a name, and a
135  /// description.
136  Statistic(Pass *owner, const char *name, const char *description);
137 
138  /// Assign the statistic to the given value.
139  Statistic &operator=(unsigned value);
140  };
141 
142  /// Returns the main statistics for this pass instance.
143  ArrayRef<Statistic *> getStatistics() const { return statistics; }
145 
146  /// Returns the thread sibling of this pass.
147  ///
148  /// If this pass was cloned by the pass manager for the sake of
149  /// multi-threading, this function returns the original pass it was cloned
150  /// from. This is useful for diagnostic purposes to distinguish passes that
151  /// were replicated for threading purposes from passes instantiated by the
152  /// user. Used to collapse passes in timing statistics.
153  const Pass *getThreadingSibling() const { return threadingSibling; }
154 
155  /// Returns the thread sibling of this pass, or the pass itself it has no
156  /// sibling. See `getThreadingSibling()` for details.
158  return threadingSibling ? threadingSibling : this;
159  }
160 
161 protected:
162  explicit Pass(TypeID passID, Optional<StringRef> opName = llvm::None)
163  : passID(passID), opName(opName) {}
164  Pass(const Pass &other) : Pass(other.passID, other.opName) {}
165 
166  /// Returns the current pass state.
168  assert(passState && "pass state was never initialized");
169  return *passState;
170  }
171 
172  /// Return the MLIR context for the current operation being transformed.
173  MLIRContext &getContext() { return *getOperation()->getContext(); }
174 
175  /// The polymorphic API that runs the pass over the currently held operation.
176  virtual void runOnOperation() = 0;
177 
178  /// Initialize any complex state necessary for running this pass. This hook
179  /// should not rely on any state accessible during the execution of a pass.
180  /// For example, `getContext`/`getOperation`/`getAnalysis`/etc. should not be
181  /// invoked within this hook.
182  /// Returns a LogicalResult to indicate failure, in which case the pass
183  /// pipeline won't execute.
184  virtual LogicalResult initialize(MLIRContext *context) { return success(); }
185 
186  /// Indicate if the current pass can be scheduled on the given operation type.
187  /// This is useful for generic operation passes to add restrictions on the
188  /// operations they operate on.
189  virtual bool canScheduleOn(RegisteredOperationName opName) const = 0;
190 
191  /// Schedule an arbitrary pass pipeline on the provided operation.
192  /// This can be invoke any time in a pass to dynamic schedule more passes.
193  /// The provided operation must be the current one or one nested below.
195  return passState->pipelineExecutor(pipeline, op);
196  }
197 
198  /// A clone method to create a copy of this pass.
199  std::unique_ptr<Pass> clone() const {
200  auto newInst = clonePass();
201  newInst->copyOptionValuesFrom(this);
202  return newInst;
203  }
204 
205  /// Return the current operation being transformed.
207  return getPassState().irAndPassFailed.getPointer();
208  }
209 
210  /// Signal that some invariant was broken when running. The IR is allowed to
211  /// be in an invalid state.
212  void signalPassFailure() { getPassState().irAndPassFailed.setInt(true); }
213 
214  /// Query an analysis for the current ir unit.
215  template <typename AnalysisT> AnalysisT &getAnalysis() {
216  return getAnalysisManager().getAnalysis<AnalysisT>();
217  }
218 
219  /// Query an analysis for the current ir unit of a specific derived operation
220  /// type.
221  template <typename AnalysisT, typename OpT>
222  AnalysisT &getAnalysis() {
223  return getAnalysisManager().getAnalysis<AnalysisT, OpT>();
224  }
225 
226  /// Query a cached instance of an analysis for the current ir unit if one
227  /// exists.
228  template <typename AnalysisT>
230  return getAnalysisManager().getCachedAnalysis<AnalysisT>();
231  }
232 
233  /// Mark all analyses as preserved.
235  getPassState().preservedAnalyses.preserveAll();
236  }
237 
238  /// Mark the provided analyses as preserved.
239  template <typename... AnalysesT> void markAnalysesPreserved() {
240  getPassState().preservedAnalyses.preserve<AnalysesT...>();
241  }
243  getPassState().preservedAnalyses.preserve(id);
244  }
245 
246  /// Returns the analysis for the given parent operation if it exists.
247  template <typename AnalysisT>
250  return getAnalysisManager().getCachedParentAnalysis<AnalysisT>(parent);
251  }
252 
253  /// Returns the analysis for the parent operation if it exists.
254  template <typename AnalysisT>
256  return getAnalysisManager().getCachedParentAnalysis<AnalysisT>(
257  getOperation()->getParentOp());
258  }
259 
260  /// Returns the analysis for the given child operation if it exists.
261  template <typename AnalysisT>
264  return getAnalysisManager().getCachedChildAnalysis<AnalysisT>(child);
265  }
266 
267  /// Returns the analysis for the given child operation, or creates it if it
268  /// doesn't exist.
269  template <typename AnalysisT> AnalysisT &getChildAnalysis(Operation *child) {
270  return getAnalysisManager().getChildAnalysis<AnalysisT>(child);
271  }
272 
273  /// Returns the analysis for the given child operation of specific derived
274  /// operation type, or creates it if it doesn't exist.
275  template <typename AnalysisT, typename OpTy>
276  AnalysisT &getChildAnalysis(OpTy child) {
277  return getAnalysisManager().getChildAnalysis<AnalysisT>(child);
278  }
279 
280  /// Returns the current analysis manager.
282  return getPassState().analysisManager;
283  }
284 
285  /// Create a copy of this pass, ignoring statistics and options.
286  virtual std::unique_ptr<Pass> clonePass() const = 0;
287 
288  /// Copy the option values from 'other', which is another instance of this
289  /// pass.
290  void copyOptionValuesFrom(const Pass *other);
291 
292 private:
293  /// Out of line virtual method to ensure vtables and metadata are emitted to a
294  /// single .o file.
295  virtual void anchor();
296 
297  /// Represents a unique identifier for the pass.
298  TypeID passID;
299 
300  /// The name of the operation that this pass operates on, or None if this is a
301  /// generic OperationPass.
302  Optional<StringRef> opName;
303 
304  /// The current execution state for the pass.
306 
307  /// The set of statistics held by this pass.
308  std::vector<Statistic *> statistics;
309 
310  /// The pass options registered to this pass instance.
311  detail::PassOptions passOptions;
312 
313  /// A pointer to the pass this pass was cloned from, if the clone was made by
314  /// the pass manager for the sake of multi-threading.
315  const Pass *threadingSibling = nullptr;
316 
317  /// Allow access to 'clone'.
318  friend class OpPassManager;
319 
320  /// Allow access to 'canScheduleOn'.
322 
323  /// Allow access to 'passState'.
325 
326  /// Allow access to 'passOptions'.
327  friend class PassInfo;
328 };
329 
330 //===----------------------------------------------------------------------===//
331 // Pass Model Definitions
332 //===----------------------------------------------------------------------===//
333 
334 /// Pass to transform an operation of a specific type.
335 ///
336 /// Operation passes must not:
337 /// - modify any other operations within the parent region, as other threads
338 /// may be manipulating them concurrently.
339 /// - modify any state within the parent operation, this includes adding
340 /// additional operations.
341 ///
342 /// Derived operation passes are expected to provide the following:
343 /// - A 'void runOnOperation()' method.
344 /// - A 'StringRef getName() const' method.
345 /// - A 'std::unique_ptr<Pass> clonePass() const' method.
346 template <typename OpT = void> class OperationPass : public Pass {
347 protected:
348  OperationPass(TypeID passID) : Pass(passID, OpT::getOperationName()) {}
349  OperationPass(const OperationPass &) = default;
350 
351  /// Support isa/dyn_cast functionality.
352  static bool classof(const Pass *pass) {
353  return pass->getOpName() == OpT::getOperationName();
354  }
355 
356  /// Indicate if the current pass can be scheduled on the given operation type.
357  bool canScheduleOn(RegisteredOperationName opName) const final {
358  return opName.getStringRef() == getOpName();
359  }
360 
361  /// Return the current operation being transformed.
362  OpT getOperation() { return cast<OpT>(Pass::getOperation()); }
363 
364  /// Query an analysis for the current operation of the specific derived
365  /// operation type.
366  template <typename AnalysisT>
367  AnalysisT &getAnalysis() {
368  return Pass::getAnalysis<AnalysisT, OpT>();
369  }
370 };
371 
372 /// Pass to transform an operation.
373 ///
374 /// Operation passes must not:
375 /// - modify any other operations within the parent region, as other threads
376 /// may be manipulating them concurrently.
377 /// - modify any state within the parent operation, this includes adding
378 /// additional operations.
379 ///
380 /// Derived operation passes are expected to provide the following:
381 /// - A 'void runOnOperation()' method.
382 /// - A 'StringRef getName() const' method.
383 /// - A 'std::unique_ptr<Pass> clonePass() const' method.
384 template <> class OperationPass<void> : public Pass {
385 protected:
386  OperationPass(TypeID passID) : Pass(passID) {}
387  OperationPass(const OperationPass &) = default;
388 
389  /// Indicate if the current pass can be scheduled on the given operation type.
390  /// By default, generic operation passes can be scheduled on any operation.
391  bool canScheduleOn(RegisteredOperationName opName) const override {
392  return true;
393  }
394 };
395 
396 /// Pass to transform an operation that implements the given interface.
397 ///
398 /// Interface passes must not:
399 /// - modify any other operations within the parent region, as other threads
400 /// may be manipulating them concurrently.
401 /// - modify any state within the parent operation, this includes adding
402 /// additional operations.
403 ///
404 /// Derived interface passes are expected to provide the following:
405 /// - A 'void runOnOperation()' method.
406 /// - A 'StringRef getName() const' method.
407 /// - A 'std::unique_ptr<Pass> clonePass() const' method.
408 template <typename InterfaceT>
409 class InterfacePass : public OperationPass<> {
410 protected:
412 
413  /// Indicate if the current pass can be scheduled on the given operation type.
414  /// For an InterfacePass, this checks if the operation implements the given
415  /// interface.
416  bool canScheduleOn(RegisteredOperationName opName) const final {
417  return opName.hasInterface<InterfaceT>();
418  }
419 
420  /// Return the current operation being transformed.
421  InterfaceT getOperation() { return cast<InterfaceT>(Pass::getOperation()); }
422 
423  /// Query an analysis for the current operation.
424  template <typename AnalysisT>
425  AnalysisT &getAnalysis() {
426  return Pass::getAnalysis<AnalysisT, InterfaceT>();
427  }
428 };
429 
430 /// This class provides a CRTP wrapper around a base pass class to define
431 /// several necessary utility methods. This should only be used for passes that
432 /// are not suitably represented using the declarative pass specification(i.e.
433 /// tablegen backend).
434 template <typename PassT, typename BaseT> class PassWrapper : public BaseT {
435 public:
436  /// Support isa/dyn_cast functionality for the derived pass class.
437  static bool classof(const Pass *pass) {
438  return pass->getTypeID() == TypeID::get<PassT>();
439  }
440 
441 protected:
442  PassWrapper() : BaseT(TypeID::get<PassT>()) {}
443  PassWrapper(const PassWrapper &) = default;
444 
445  /// Returns the derived pass name.
446  StringRef getName() const override { return llvm::getTypeName<PassT>(); }
447 
448  /// A clone method to create a copy of this pass.
449  std::unique_ptr<Pass> clonePass() const override {
450  return std::make_unique<PassT>(*static_cast<const PassT *>(this));
451  }
452 };
453 
454 } // namespace mlir
455 
456 #endif // MLIR_PASS_PASS_H
This class represents a specific pass option that contains a list of values of the provided data type...
Definition: Pass.h:105
Pass to transform an operation that implements the given interface.
Definition: SCFToGPUPass.h:18
TODO: Remove this file when SCCP and integer range analysis have been ported to the new framework...
static void printAsTextualPipeline(ArrayRef< std::unique_ptr< Pass >> passes, raw_ostream &os)
Prints out the given passes as the textual representation of a pipeline.
Definition: Pass.cpp:360
Pass(TypeID passID, Optional< StringRef > opName=llvm::None)
Definition: Pass.h:162
StringRef getName() const override
Returns the derived pass name.
Definition: Pass.h:446
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
static bool classof(const Pass *pass)
Support isa/dyn_cast functionality for the derived pass class.
Definition: Pass.h:437
std::conditional_t< std::is_base_of< llvm::cl::generic_parser_base, llvm::cl::parser< DataType > >::value, GenericOptionParser< DataType >, llvm::cl::parser< DataType > > OptionParser
The specific parser to use depending on llvm::cl parser used.
Definition: PassOptions.h:154
bool canScheduleOn(RegisteredOperationName opName) const final
Indicate if the current pass can be scheduled on the given operation type.
Definition: Pass.h:416
This class represents a specific pass option that contains a list of values of the provided data type...
Definition: PassOptions.h:205
OpT getOperation()
Return the current operation being transformed.
Definition: Pass.h:362
LogicalResult runPipeline(OpPassManager &pipeline, Operation *op)
Schedule an arbitrary pass pipeline on the provided operation.
Definition: Pass.h:194
This class represents an analysis manager for a particular operation instance.
function_ref< LogicalResult(OpPassManager &, Operation *)> pipelineExecutor
This is a callback in the PassManager that allows to schedule dynamic pipelines that will be rooted a...
Definition: Pass.h:44
This class represents a specific pass option, with a provided data type.
Definition: Pass.h:94
void markAnalysesPreserved(TypeID id)
Definition: Pass.h:242
llvm::PointerIntPair< Operation *, 1, bool > irAndPassFailed
The current operation being transformed and a bool for if the pass signaled a failure.
Definition: Pass.h:34
An adaptor pass used to run operation passes over nested operations.
Definition: PassDetail.h:22
MLIRContext & getContext()
Return the MLIR context for the current operation being transformed.
Definition: Pass.h:173
static constexpr const bool value
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
void signalPassFailure()
Signal that some invariant was broken when running.
Definition: Pass.h:212
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
std::unique_ptr< Pass > clone() const
A clone method to create a copy of this pass.
Definition: Pass.h:199
Pass to transform an operation of a specific type.
Definition: AsyncToLLVM.h:19
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
static bool classof(const Pass *pass)
Support isa/dyn_cast functionality.
Definition: Pass.h:352
const Pass * getThreadingSibling() const
Returns the thread sibling of this pass.
Definition: Pass.h:153
AnalysisT & getAnalysis()
Query an analysis for the current operation.
Definition: Pass.h:425
The state for a single execution of a pass.
Definition: Pass.h:25
AnalysisManager analysisManager
The analysis manager for the operation.
Definition: Pass.h:37
ListOption(Pass &parent, StringRef arg, Args &&...args)
Definition: Pass.h:108
Optional< StringRef > getOpName() const
Returns the name of the operation that this pass operates on, or None if this is a generic OperationP...
Definition: Pass.h:85
A utility class to represent the analyses that are known to be preserved.
bool canScheduleOn(RegisteredOperationName opName) const final
Indicate if the current pass can be scheduled on the given operation type.
Definition: Pass.h:357
TypeID getTypeID() const
Returns the unique identifier that corresponds to this pass.
Definition: Pass.h:55
This class represents a specific pass option, with a provided data type.
Definition: PassOptions.h:158
std::unique_ptr< Pass > clonePass() const override
A clone method to create a copy of this pass.
Definition: Pass.h:449
detail::PreservedAnalyses preservedAnalyses
The set of preserved analyses for the current execution.
Definition: Pass.h:40
Optional< std::reference_wrapper< AnalysisT > > getCachedParentAnalysis(Operation *parent)
Returns the analysis for the given parent operation if it exists.
Definition: Pass.h:249
AnalysisT & getAnalysis()
Query an analysis for the current ir unit.
Definition: Pass.h:215
void markAllAnalysesPreserved()
Mark all analyses as preserved.
Definition: Pass.h:234
bool canScheduleOn(RegisteredOperationName opName) const override
Indicate if the current pass can be scheduled on the given operation type.
Definition: Pass.h:391
Base container class and manager for all pass options.
Definition: PassOptions.h:79
static llvm::ManagedStatic< PassManagerOptions > options
InterfaceT getOperation()
Return the current operation being transformed.
Definition: Pass.h:421
virtual StringRef getDescription() const
Return the command line description used when registering this pass.
Definition: Pass.h:81
OperationPass(TypeID passID)
Definition: Pass.h:386
AnalysisT & getChildAnalysis(OpTy child)
Returns the analysis for the given child operation of specific derived operation type, or creates it if it doesn&#39;t exist.
Definition: Pass.h:276
AnalysisManager getAnalysisManager()
Returns the current analysis manager.
Definition: Pass.h:281
AnalysisT & getChildAnalysis(Operation *child)
Returns the analysis for the given child operation, or creates it if it doesn&#39;t exist.
Definition: Pass.h:269
Optional< std::reference_wrapper< AnalysisT > > getCachedChildAnalysis(Operation *child)
Returns the analysis for the given child operation if it exists.
Definition: Pass.h:263
void markAnalysesPreserved()
Mark the provided analyses as preserved.
Definition: Pass.h:239
Optional< std::reference_wrapper< AnalysisT > > getCachedAnalysis()
Query a cached instance of an analysis for the current ir unit if one exists.
Definition: Pass.h:229
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
AnalysisT & getAnalysis()
Query an analysis for the current ir unit of a specific derived operation type.
Definition: Pass.h:222
Operation * getOperation()
Return the current operation being transformed.
Definition: Pass.h:206
A structure to represent the information for a derived pass class.
Definition: PassRegistry.h:110
Option(Pass &parent, StringRef arg, Args &&...args)
Definition: Pass.h:96
MutableArrayRef< Statistic * > getStatistics()
Definition: Pass.h:144
The abstract base pass class.
Definition: Pass.h:50
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
ArrayRef< Statistic * > getStatistics() const
Returns the main statistics for this pass instance.
Definition: Pass.h:143
Optional< std::reference_wrapper< AnalysisT > > getCachedParentAnalysis()
Returns the analysis for the parent operation if it exists.
Definition: Pass.h:255
detail::PassExecutionState & getPassState()
Returns the current pass state.
Definition: Pass.h:167
virtual StringRef getArgument() const
Return the command line argument used when registering this pass.
Definition: Pass.h:77
virtual void getDependentDialects(DialectRegistry &registry) const
Register dependent dialects for the current pass.
Definition: Pass.h:73
This is a "type erased" representation of a registered operation.
const PassInfo * lookupPassInfo() const
Returns the pass info for this pass, or null if unknown.
Definition: Pass.h:61
const Pass * getThreadingSiblingOrThis() const
Returns the thread sibling of this pass, or the pass itself it has no sibling.
Definition: Pass.h:157
virtual LogicalResult initialize(MLIRContext *context)
Initialize any complex state necessary for running this pass.
Definition: Pass.h:184
PassExecutionState(Operation *ir, AnalysisManager analysisManager, function_ref< LogicalResult(OpPassManager &, Operation *)> pipelineExecutor)
Definition: Pass.h:26
Pass(const Pass &other)
Definition: Pass.h:164
This class represents a pass manager that runs passes on either a specific operation type...
Definition: PassManager.h:52
OperationPass(TypeID passID)
Definition: Pass.h:348
This class represents a single pass statistic.
Definition: Pass.h:132
AnalysisT & getAnalysis()
Query an analysis for the current operation of the specific derived operation type.
Definition: Pass.h:367
This class provides a CRTP wrapper around a base pass class to define several necessary utility metho...
Definition: Pass.h:434