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