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