1 //===- TestPassManager.cpp - Test pass manager functionality --------------===//
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 #include "mlir/IR/BuiltinOps.h"
10 #include "mlir/Pass/Pass.h"
11 #include "mlir/Pass/PassManager.h"
12 
13 using namespace mlir;
14 
15 namespace {
16 struct TestModulePass
17     : public PassWrapper<TestModulePass, OperationPass<ModuleOp>> {
18   void runOnOperation() final {}
19   StringRef getArgument() const final { return "test-module-pass"; }
20 };
21 struct TestFunctionPass : public PassWrapper<TestFunctionPass, FunctionPass> {
22   void runOnFunction() final {}
23   StringRef getArgument() const final { return "test-function-pass"; }
24 };
25 class TestOptionsPass : public PassWrapper<TestOptionsPass, FunctionPass> {
26 public:
27   struct Options : public PassPipelineOptions<Options> {
28     ListOption<int> listOption{*this, "list",
29                                llvm::cl::MiscFlags::CommaSeparated,
30                                llvm::cl::desc("Example list option")};
31     ListOption<std::string> stringListOption{
32         *this, "string-list", llvm::cl::MiscFlags::CommaSeparated,
33         llvm::cl::desc("Example string list option")};
34     Option<std::string> stringOption{*this, "string",
35                                      llvm::cl::desc("Example string option")};
36   };
37   TestOptionsPass() = default;
38   TestOptionsPass(const TestOptionsPass &) {}
39   TestOptionsPass(const Options &options) {
40     listOption = options.listOption;
41     stringOption = options.stringOption;
42     stringListOption = options.stringListOption;
43   }
44 
45   void runOnFunction() final {}
46   StringRef getArgument() const final { return "test-options-pass"; }
47 
48   ListOption<int> listOption{*this, "list", llvm::cl::MiscFlags::CommaSeparated,
49                              llvm::cl::desc("Example list option")};
50   ListOption<std::string> stringListOption{
51       *this, "string-list", llvm::cl::MiscFlags::CommaSeparated,
52       llvm::cl::desc("Example string list option")};
53   Option<std::string> stringOption{*this, "string",
54                                    llvm::cl::desc("Example string option")};
55 };
56 
57 /// A test pass that always aborts to enable testing the crash recovery
58 /// mechanism of the pass manager.
59 class TestCrashRecoveryPass
60     : public PassWrapper<TestCrashRecoveryPass, OperationPass<>> {
61   void runOnOperation() final { abort(); }
62   StringRef getArgument() const final { return "test-pass-crash"; }
63 };
64 
65 /// A test pass that always fails to enable testing the failure recovery
66 /// mechanisms of the pass manager.
67 class TestFailurePass : public PassWrapper<TestFailurePass, OperationPass<>> {
68   void runOnOperation() final { signalPassFailure(); }
69 };
70 
71 /// A test pass that contains a statistic.
72 struct TestStatisticPass
73     : public PassWrapper<TestStatisticPass, OperationPass<>> {
74   TestStatisticPass() = default;
75   TestStatisticPass(const TestStatisticPass &) {}
76 
77   Statistic opCount{this, "num-ops", "Number of operations counted"};
78 
79   void runOnOperation() final {
80     getOperation()->walk([&](Operation *) { ++opCount; });
81   }
82 };
83 } // end anonymous namespace
84 
85 static void testNestedPipeline(OpPassManager &pm) {
86   // Nest a module pipeline that contains:
87   /// A module pass.
88   auto &modulePM = pm.nest<ModuleOp>();
89   modulePM.addPass(std::make_unique<TestModulePass>());
90   /// A nested function pass.
91   auto &nestedFunctionPM = modulePM.nest<FuncOp>();
92   nestedFunctionPM.addPass(std::make_unique<TestFunctionPass>());
93 
94   // Nest a function pipeline that contains a single pass.
95   auto &functionPM = pm.nest<FuncOp>();
96   functionPM.addPass(std::make_unique<TestFunctionPass>());
97 }
98 
99 static void testNestedPipelineTextual(OpPassManager &pm) {
100   (void)parsePassPipeline("test-pm-nested-pipeline", pm);
101 }
102 
103 namespace mlir {
104 void registerPassManagerTestPass() {
105   PassRegistration<TestOptionsPass>("test-options-pass",
106                                     "Test options parsing capabilities");
107 
108   PassRegistration<TestModulePass>("test-module-pass",
109                                    "Test a module pass in the pass manager");
110 
111   PassRegistration<TestFunctionPass>(
112       "test-function-pass", "Test a function pass in the pass manager");
113 
114   PassRegistration<TestCrashRecoveryPass>(
115       "test-pass-crash", "Test a pass in the pass manager that always crashes");
116   PassRegistration<TestFailurePass>(
117       "test-pass-failure", "Test a pass in the pass manager that always fails");
118 
119   PassRegistration<TestStatisticPass> unusedStatP("test-stats-pass",
120                                                   "Test pass statistics");
121 
122   PassPipelineRegistration<>("test-pm-nested-pipeline",
123                              "Test a nested pipeline in the pass manager",
124                              testNestedPipeline);
125   PassPipelineRegistration<>("test-textual-pm-nested-pipeline",
126                              "Test a nested pipeline in the pass manager",
127                              testNestedPipelineTextual);
128   PassPipelineRegistration<>(
129       "test-dump-pipeline",
130       "Dumps the pipeline build so far for debugging purposes",
131       [](OpPassManager &pm) {
132         pm.printAsTextualPipeline(llvm::errs());
133         llvm::errs() << "\n";
134       });
135 
136   PassPipelineRegistration<TestOptionsPass::Options>
137       registerOptionsPassPipeline(
138           "test-options-pass-pipeline",
139           "Parses options using pass pipeline registration",
140           [](OpPassManager &pm, const TestOptionsPass::Options &options) {
141             pm.addPass(std::make_unique<TestOptionsPass>(options));
142           });
143 }
144 } // namespace mlir
145