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