1 //===- TestPassManager.cpp - Test pass manager functionality --------------===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 18 #include "mlir/IR/Function.h" 19 #include "mlir/Pass/Pass.h" 20 #include "mlir/Pass/PassManager.h" 21 22 using namespace mlir; 23 24 namespace { 25 struct TestModulePass : public ModulePass<TestModulePass> { 26 void runOnModule() final {} 27 }; 28 struct TestFunctionPass : public FunctionPass<TestFunctionPass> { 29 void runOnFunction() final {} 30 }; 31 class TestOptionsPass : public FunctionPass<TestOptionsPass> { 32 public: 33 struct Options : public PassOptions<Options> { 34 List<int> listOption{*this, "list", llvm::cl::MiscFlags::CommaSeparated, 35 llvm::cl::desc("Example list option")}; 36 List<std::string> stringListOption{ 37 *this, "string-list", llvm::cl::MiscFlags::CommaSeparated, 38 llvm::cl::desc("Example string list option")}; 39 Option<std::string> stringOption{*this, "string", 40 llvm::cl::desc("Example string option")}; 41 }; 42 TestOptionsPass(const Options &options) { 43 listOption.assign(options.listOption.begin(), options.listOption.end()); 44 stringOption = options.stringOption; 45 stringListOption.assign(options.stringListOption.begin(), 46 options.stringListOption.end()); 47 } 48 49 void printAsTextualPipeline(raw_ostream &os) final { 50 os << "test-options-pass{"; 51 if (!listOption.empty()) { 52 os << "list="; 53 // Not interleaveComma to avoid spaces between the elements. 54 interleave(listOption, os, ","); 55 } 56 if (!stringListOption.empty()) { 57 os << " string-list="; 58 interleave(stringListOption, os, ","); 59 } 60 if (!stringOption.empty()) 61 os << " string=" << stringOption; 62 os << "}"; 63 } 64 65 void runOnFunction() final {} 66 67 SmallVector<int64_t, 4> listOption; 68 SmallVector<std::string, 4> stringListOption; 69 std::string stringOption; 70 }; 71 72 /// A test pass that always aborts to enable testing the crash recovery 73 /// mechanism of the pass manager. 74 class TestCrashRecoveryPass : public OperationPass<TestCrashRecoveryPass> { 75 void runOnOperation() final { abort(); } 76 }; 77 78 /// A test pass that contains a statistic. 79 struct TestStatisticPass : public OperationPass<TestStatisticPass> { 80 TestStatisticPass() = default; 81 TestStatisticPass(const TestStatisticPass &) {} 82 83 Statistic opCount{this, "num-ops", "Number of operations counted"}; 84 85 void runOnOperation() final { 86 getOperation()->walk([&](Operation *) { ++opCount; }); 87 } 88 }; 89 } // end anonymous namespace 90 91 static void testNestedPipeline(OpPassManager &pm) { 92 // Nest a module pipeline that contains: 93 /// A module pass. 94 auto &modulePM = pm.nest<ModuleOp>(); 95 modulePM.addPass(std::make_unique<TestModulePass>()); 96 /// A nested function pass. 97 auto &nestedFunctionPM = modulePM.nest<FuncOp>(); 98 nestedFunctionPM.addPass(std::make_unique<TestFunctionPass>()); 99 100 // Nest a function pipeline that contains a single pass. 101 auto &functionPM = pm.nest<FuncOp>(); 102 functionPM.addPass(std::make_unique<TestFunctionPass>()); 103 } 104 105 static void testNestedPipelineTextual(OpPassManager &pm) { 106 (void)parsePassPipeline("test-pm-nested-pipeline", pm); 107 } 108 109 static PassRegistration<TestOptionsPass, TestOptionsPass::Options> 110 reg("test-options-pass", "Test options parsing capabilities"); 111 112 static PassRegistration<TestModulePass> 113 unusedMP("test-module-pass", "Test a module pass in the pass manager"); 114 static PassRegistration<TestFunctionPass> 115 unusedFP("test-function-pass", "Test a function pass in the pass manager"); 116 117 static PassRegistration<TestCrashRecoveryPass> 118 unusedCrashP("test-pass-crash", 119 "Test a pass in the pass manager that always crashes"); 120 121 static PassRegistration<TestStatisticPass> unusedStatP("test-stats-pass", 122 "Test pass statistics"); 123 124 static PassPipelineRegistration<> 125 unused("test-pm-nested-pipeline", 126 "Test a nested pipeline in the pass manager", testNestedPipeline); 127 static PassPipelineRegistration<> 128 unusedTextual("test-textual-pm-nested-pipeline", 129 "Test a nested pipeline in the pass manager", 130 testNestedPipelineTextual); 131 static PassPipelineRegistration<> 132 unusedDump("test-dump-pipeline", 133 "Dumps the pipeline build so far for debugging purposes", 134 [](OpPassManager &pm) { 135 pm.printAsTextualPipeline(llvm::errs()); 136 llvm::errs() << "\n"; 137 }); 138 139 static PassPipelineRegistration<TestOptionsPass::Options> 140 registerOptionsPassPipeline( 141 "test-options-pass-pipeline", 142 "Parses options using pass pipeline registration", 143 [](OpPassManager &pm, const TestOptionsPass::Options &options) { 144 pm.addPass(std::make_unique<TestOptionsPass>(options)); 145 }); 146