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 "TestDialect.h" 10 #include "mlir/Dialect/Func/IR/FuncOps.h" 11 #include "mlir/IR/BuiltinOps.h" 12 #include "mlir/Pass/Pass.h" 13 #include "mlir/Pass/PassManager.h" 14 15 using namespace mlir; 16 17 namespace { 18 struct TestModulePass 19 : public PassWrapper<TestModulePass, OperationPass<ModuleOp>> { 20 void runOnOperation() final {} 21 StringRef getArgument() const final { return "test-module-pass"; } 22 StringRef getDescription() const final { 23 return "Test a module pass in the pass manager"; 24 } 25 }; 26 struct TestFunctionPass 27 : public PassWrapper<TestFunctionPass, OperationPass<FuncOp>> { 28 void runOnOperation() final {} 29 StringRef getArgument() const final { return "test-function-pass"; } 30 StringRef getDescription() const final { 31 return "Test a function pass in the pass manager"; 32 } 33 }; 34 class TestInterfacePass 35 : public PassWrapper<TestInterfacePass, 36 InterfacePass<FunctionOpInterface>> { 37 void runOnOperation() final { 38 getOperation()->emitRemark() << "Executing interface pass on operation"; 39 } 40 StringRef getArgument() const final { return "test-interface-pass"; } 41 StringRef getDescription() const final { 42 return "Test an interface pass (running on FunctionOpInterface) in the " 43 "pass manager"; 44 } 45 }; 46 class TestOptionsPass 47 : public PassWrapper<TestOptionsPass, OperationPass<FuncOp>> { 48 public: 49 struct Options : public PassPipelineOptions<Options> { 50 ListOption<int> listOption{*this, "list", 51 llvm::cl::MiscFlags::CommaSeparated, 52 llvm::cl::desc("Example list option")}; 53 ListOption<std::string> stringListOption{ 54 *this, "string-list", llvm::cl::MiscFlags::CommaSeparated, 55 llvm::cl::desc("Example string list option")}; 56 Option<std::string> stringOption{*this, "string", 57 llvm::cl::desc("Example string option")}; 58 }; 59 TestOptionsPass() = default; 60 TestOptionsPass(const TestOptionsPass &) {} 61 TestOptionsPass(const Options &options) { 62 listOption = options.listOption; 63 stringOption = options.stringOption; 64 stringListOption = options.stringListOption; 65 } 66 67 void runOnOperation() final {} 68 StringRef getArgument() const final { return "test-options-pass"; } 69 StringRef getDescription() const final { 70 return "Test options parsing capabilities"; 71 } 72 73 ListOption<int> listOption{*this, "list", llvm::cl::MiscFlags::CommaSeparated, 74 llvm::cl::desc("Example list option")}; 75 ListOption<std::string> stringListOption{ 76 *this, "string-list", llvm::cl::MiscFlags::CommaSeparated, 77 llvm::cl::desc("Example string list option")}; 78 Option<std::string> stringOption{*this, "string", 79 llvm::cl::desc("Example string option")}; 80 }; 81 82 /// A test pass that always aborts to enable testing the crash recovery 83 /// mechanism of the pass manager. 84 class TestCrashRecoveryPass 85 : public PassWrapper<TestCrashRecoveryPass, OperationPass<>> { 86 void runOnOperation() final { abort(); } 87 StringRef getArgument() const final { return "test-pass-crash"; } 88 StringRef getDescription() const final { 89 return "Test a pass in the pass manager that always crashes"; 90 } 91 }; 92 93 /// A test pass that always fails to enable testing the failure recovery 94 /// mechanisms of the pass manager. 95 class TestFailurePass : public PassWrapper<TestFailurePass, OperationPass<>> { 96 void runOnOperation() final { signalPassFailure(); } 97 StringRef getArgument() const final { return "test-pass-failure"; } 98 StringRef getDescription() const final { 99 return "Test a pass in the pass manager that always fails"; 100 } 101 }; 102 103 /// A test pass that always fails to enable testing the failure recovery 104 /// mechanisms of the pass manager. 105 class TestInvalidParentPass 106 : public PassWrapper<TestInvalidParentPass, 107 InterfacePass<FunctionOpInterface>> { 108 StringRef getArgument() const final { return "test-pass-invalid-parent"; } 109 StringRef getDescription() const final { 110 return "Test a pass in the pass manager that makes the parent operation " 111 "invalid"; 112 } 113 void getDependentDialects(DialectRegistry ®istry) const final { 114 registry.insert<test::TestDialect>(); 115 } 116 void runOnOperation() final { 117 FunctionOpInterface op = getOperation(); 118 OpBuilder b(getOperation().getBody()); 119 b.create<test::TestCallOp>(op.getLoc(), TypeRange(), "some_unknown_func", 120 ValueRange()); 121 } 122 }; 123 124 /// A test pass that contains a statistic. 125 struct TestStatisticPass 126 : public PassWrapper<TestStatisticPass, OperationPass<>> { 127 TestStatisticPass() = default; 128 TestStatisticPass(const TestStatisticPass &) {} 129 StringRef getArgument() const final { return "test-stats-pass"; } 130 StringRef getDescription() const final { return "Test pass statistics"; } 131 132 Statistic opCount{this, "num-ops", "Number of operations counted"}; 133 134 void runOnOperation() final { 135 getOperation()->walk([&](Operation *) { ++opCount; }); 136 } 137 }; 138 } // namespace 139 140 static void testNestedPipeline(OpPassManager &pm) { 141 // Nest a module pipeline that contains: 142 /// A module pass. 143 auto &modulePM = pm.nest<ModuleOp>(); 144 modulePM.addPass(std::make_unique<TestModulePass>()); 145 /// A nested function pass. 146 auto &nestedFunctionPM = modulePM.nest<FuncOp>(); 147 nestedFunctionPM.addPass(std::make_unique<TestFunctionPass>()); 148 149 // Nest a function pipeline that contains a single pass. 150 auto &functionPM = pm.nest<FuncOp>(); 151 functionPM.addPass(std::make_unique<TestFunctionPass>()); 152 } 153 154 static void testNestedPipelineTextual(OpPassManager &pm) { 155 (void)parsePassPipeline("test-pm-nested-pipeline", pm); 156 } 157 158 namespace mlir { 159 void registerPassManagerTestPass() { 160 PassRegistration<TestOptionsPass>(); 161 162 PassRegistration<TestModulePass>(); 163 164 PassRegistration<TestFunctionPass>(); 165 166 PassRegistration<TestInterfacePass>(); 167 168 PassRegistration<TestCrashRecoveryPass>(); 169 PassRegistration<TestFailurePass>(); 170 PassRegistration<TestInvalidParentPass>(); 171 172 PassRegistration<TestStatisticPass>(); 173 174 PassPipelineRegistration<>("test-pm-nested-pipeline", 175 "Test a nested pipeline in the pass manager", 176 testNestedPipeline); 177 PassPipelineRegistration<>("test-textual-pm-nested-pipeline", 178 "Test a nested pipeline in the pass manager", 179 testNestedPipelineTextual); 180 PassPipelineRegistration<>( 181 "test-dump-pipeline", 182 "Dumps the pipeline build so far for debugging purposes", 183 [](OpPassManager &pm) { 184 pm.printAsTextualPipeline(llvm::errs()); 185 llvm::errs() << "\n"; 186 }); 187 188 PassPipelineRegistration<TestOptionsPass::Options> 189 registerOptionsPassPipeline( 190 "test-options-pass-pipeline", 191 "Parses options using pass pipeline registration", 192 [](OpPassManager &pm, const TestOptionsPass::Options &options) { 193 pm.addPass(std::make_unique<TestOptionsPass>(options)); 194 }); 195 } 196 } // namespace mlir 197