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