| 1 | //===- PassDetail.h - MLIR Pass details -------------------------*- 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 | #ifndef MLIR_PASS_PASSDETAIL_H_ |
| 9 | #define MLIR_PASS_PASSDETAIL_H_ |
| 10 | |
| 11 | #include "mlir/IR/Action.h" |
| 12 | #include "mlir/Pass/Pass.h" |
| 13 | #include "mlir/Pass/PassManager.h" |
| 14 | #include "llvm/ADT/ArrayRef.h" |
| 15 | #include "llvm/Support/FormatVariadic.h" |
| 16 | |
| 17 | namespace mlir { |
| 18 | namespace detail { |
| 19 | |
| 20 | //===----------------------------------------------------------------------===// |
| 21 | // OpToOpPassAdaptor |
| 22 | //===----------------------------------------------------------------------===// |
| 23 | |
| 24 | /// An adaptor pass used to run operation passes over nested operations. |
| 25 | class OpToOpPassAdaptor |
| 26 | : public PassWrapper<OpToOpPassAdaptor, OperationPass<>> { |
| 27 | public: |
| 28 | OpToOpPassAdaptor(OpPassManager &&mgr); |
| 29 | OpToOpPassAdaptor(const OpToOpPassAdaptor &rhs) = default; |
| 30 | |
| 31 | /// Run the held pipeline over all operations. |
| 32 | void runOnOperation(bool verifyPasses); |
| 33 | void runOnOperation() override; |
| 34 | |
| 35 | /// Try to merge the current pass adaptor into 'rhs'. This will try to append |
| 36 | /// the pass managers of this adaptor into those within `rhs`, or return |
| 37 | /// failure if merging isn't possible. The main situation in which merging is |
| 38 | /// not possible is if one of the adaptors has an `any` pipeline that is not |
| 39 | /// compatible with a pass manager in the other adaptor. For example, if this |
| 40 | /// adaptor has a `func.func` pipeline and `rhs` has an `any` pipeline that |
| 41 | /// operates on FunctionOpInterface. In this situation the pipelines have a |
| 42 | /// conflict (they both want to run on the same operations), so we can't |
| 43 | /// merge. |
| 44 | LogicalResult tryMergeInto(MLIRContext *ctx, OpToOpPassAdaptor &rhs); |
| 45 | |
| 46 | /// Returns the pass managers held by this adaptor. |
| 47 | MutableArrayRef<OpPassManager> getPassManagers() { return mgrs; } |
| 48 | |
| 49 | /// Populate the set of dependent dialects for the passes in the current |
| 50 | /// adaptor. |
| 51 | void getDependentDialects(DialectRegistry &dialects) const override; |
| 52 | |
| 53 | /// Return the async pass managers held by this parallel adaptor. |
| 54 | MutableArrayRef<SmallVector<OpPassManager, 1>> getParallelPassManagers() { |
| 55 | return asyncExecutors; |
| 56 | } |
| 57 | |
| 58 | /// Returns the adaptor pass name. |
| 59 | std::string getAdaptorName(); |
| 60 | |
| 61 | private: |
| 62 | /// Run this pass adaptor synchronously. |
| 63 | void runOnOperationImpl(bool verifyPasses); |
| 64 | |
| 65 | /// Run this pass adaptor asynchronously. |
| 66 | void runOnOperationAsyncImpl(bool verifyPasses); |
| 67 | |
| 68 | /// Run the given operation and analysis manager on a single pass. |
| 69 | /// `parentInitGeneration` is the initialization generation of the parent pass |
| 70 | /// manager, and is used to initialize any dynamic pass pipelines run by the |
| 71 | /// given pass. |
| 72 | static LogicalResult run(Pass *pass, Operation *op, AnalysisManager am, |
| 73 | bool verifyPasses, unsigned parentInitGeneration); |
| 74 | |
| 75 | /// Run the given operation and analysis manager on a provided op pass |
| 76 | /// manager. `parentInitGeneration` is the initialization generation of the |
| 77 | /// parent pass manager, and is used to initialize any dynamic pass pipelines |
| 78 | /// run by the given passes. |
| 79 | static LogicalResult runPipeline( |
| 80 | OpPassManager &pm, Operation *op, AnalysisManager am, bool verifyPasses, |
| 81 | unsigned parentInitGeneration, PassInstrumentor *instrumentor = nullptr, |
| 82 | const PassInstrumentation::PipelineParentInfo *parentInfo = nullptr); |
| 83 | |
| 84 | /// A set of adaptors to run. |
| 85 | SmallVector<OpPassManager, 1> mgrs; |
| 86 | |
| 87 | /// A set of executors, cloned from the main executor, that run asynchronously |
| 88 | /// on different threads. This is used when threading is enabled. |
| 89 | SmallVector<SmallVector<OpPassManager, 1>, 8> asyncExecutors; |
| 90 | |
| 91 | // For accessing "runPipeline". |
| 92 | friend class mlir::PassManager; |
| 93 | }; |
| 94 | |
| 95 | //===----------------------------------------------------------------------===// |
| 96 | // PassCrashReproducerGenerator |
| 97 | //===----------------------------------------------------------------------===// |
| 98 | |
| 99 | class PassCrashReproducerGenerator { |
| 100 | public: |
| 101 | PassCrashReproducerGenerator(ReproducerStreamFactory &streamFactory, |
| 102 | bool localReproducer); |
| 103 | ~PassCrashReproducerGenerator(); |
| 104 | |
| 105 | /// Initialize the generator in preparation for reproducer generation. The |
| 106 | /// generator should be reinitialized before each run of the pass manager. |
| 107 | void initialize(iterator_range<PassManager::pass_iterator> passes, |
| 108 | Operation *op, bool pmFlagVerifyPasses); |
| 109 | /// Finalize the current run of the generator, generating any necessary |
| 110 | /// reproducers if the provided execution result is a failure. |
| 111 | void finalize(Operation *rootOp, LogicalResult executionResult); |
| 112 | |
| 113 | /// Prepare a new reproducer for the given pass, operating on `op`. |
| 114 | void prepareReproducerFor(Pass *pass, Operation *op); |
| 115 | |
| 116 | /// Prepare a new reproducer for the given passes, operating on `op`. |
| 117 | void prepareReproducerFor(iterator_range<PassManager::pass_iterator> passes, |
| 118 | Operation *op); |
| 119 | |
| 120 | /// Remove the last recorded reproducer anchored at the given pass and |
| 121 | /// operation. |
| 122 | void removeLastReproducerFor(Pass *pass, Operation *op); |
| 123 | |
| 124 | private: |
| 125 | struct Impl; |
| 126 | |
| 127 | /// The internal implementation of the crash reproducer. |
| 128 | std::unique_ptr<Impl> impl; |
| 129 | }; |
| 130 | |
| 131 | } // namespace detail |
| 132 | } // namespace mlir |
| 133 | #endif // MLIR_PASS_PASSDETAIL_H_ |
| 134 | |