1120509a6SRiver Riddle //===- TestPassManager.cpp - Test pass manager functionality --------------===//
2120509a6SRiver Riddle //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6120509a6SRiver Riddle //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
8120509a6SRiver Riddle
950f82e68SRiver Riddle #include "TestDialect.h"
1036550692SRiver Riddle #include "mlir/Dialect/Func/IR/FuncOps.h"
1165fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h"
12120509a6SRiver Riddle #include "mlir/Pass/Pass.h"
13120509a6SRiver Riddle #include "mlir/Pass/PassManager.h"
14120509a6SRiver Riddle
15120509a6SRiver Riddle using namespace mlir;
16120509a6SRiver Riddle
17120509a6SRiver Riddle namespace {
1880aca1eaSRiver Riddle struct TestModulePass
1980aca1eaSRiver Riddle : public PassWrapper<TestModulePass, OperationPass<ModuleOp>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon0807c3400111::TestModulePass205e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestModulePass)
215e50dd04SRiver Riddle
22722f909fSRiver Riddle void runOnOperation() final {}
getArgument__anon0807c3400111::TestModulePass23fa51c5afSRiver Riddle StringRef getArgument() const final { return "test-module-pass"; }
getDescription__anon0807c3400111::TestModulePass24b5e22e6dSMehdi Amini StringRef getDescription() const final {
25b5e22e6dSMehdi Amini return "Test a module pass in the pass manager";
26b5e22e6dSMehdi Amini }
27120509a6SRiver Riddle };
2841574554SRiver Riddle struct TestFunctionPass
2958ceae95SRiver Riddle : public PassWrapper<TestFunctionPass, OperationPass<func::FuncOp>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon0807c3400111::TestFunctionPass305e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestFunctionPass)
315e50dd04SRiver Riddle
3241574554SRiver Riddle void runOnOperation() final {}
getArgument__anon0807c3400111::TestFunctionPass33fa51c5afSRiver Riddle StringRef getArgument() const final { return "test-function-pass"; }
getDescription__anon0807c3400111::TestFunctionPass34b5e22e6dSMehdi Amini StringRef getDescription() const final {
35b5e22e6dSMehdi Amini return "Test a function pass in the pass manager";
36b5e22e6dSMehdi Amini }
37120509a6SRiver Riddle };
385e50dd04SRiver Riddle struct TestInterfacePass
399c9a4317SRiver Riddle : public PassWrapper<TestInterfacePass,
409c9a4317SRiver Riddle InterfacePass<FunctionOpInterface>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon0807c3400111::TestInterfacePass415e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestInterfacePass)
425e50dd04SRiver Riddle
439c9a4317SRiver Riddle void runOnOperation() final {
449c9a4317SRiver Riddle getOperation()->emitRemark() << "Executing interface pass on operation";
459c9a4317SRiver Riddle }
getArgument__anon0807c3400111::TestInterfacePass469c9a4317SRiver Riddle StringRef getArgument() const final { return "test-interface-pass"; }
getDescription__anon0807c3400111::TestInterfacePass479c9a4317SRiver Riddle StringRef getDescription() const final {
489c9a4317SRiver Riddle return "Test an interface pass (running on FunctionOpInterface) in the "
499c9a4317SRiver Riddle "pass manager";
509c9a4317SRiver Riddle }
519c9a4317SRiver Riddle };
525e50dd04SRiver Riddle struct TestOptionsPass
5358ceae95SRiver Riddle : public PassWrapper<TestOptionsPass, OperationPass<func::FuncOp>> {
545e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestOptionsPass)
555e50dd04SRiver Riddle
5621610e66SRiver Riddle struct Options : public PassPipelineOptions<Options> {
5721610e66SRiver Riddle ListOption<int> listOption{*this, "list",
5874461512SMLIR Team llvm::cl::desc("Example list option")};
5921610e66SRiver Riddle ListOption<std::string> stringListOption{
606edef135SRiver Riddle *this, "string-list", llvm::cl::desc("Example string list option")};
6174461512SMLIR Team Option<std::string> stringOption{*this, "string",
6274461512SMLIR Team llvm::cl::desc("Example string option")};
6374461512SMLIR Team };
6421610e66SRiver Riddle TestOptionsPass() = default;
TestOptionsPass__anon0807c3400111::TestOptionsPass658919447cSJaved Absar TestOptionsPass(const TestOptionsPass &) : PassWrapper() {}
TestOptionsPass__anon0807c3400111::TestOptionsPass6674461512SMLIR Team TestOptionsPass(const Options &options) {
67400ad6f9SRiver Riddle listOption = options.listOption;
68400ad6f9SRiver Riddle stringOption = options.stringOption;
69400ad6f9SRiver Riddle stringListOption = options.stringListOption;
7074461512SMLIR Team }
7174461512SMLIR Team
runOnOperation__anon0807c3400111::TestOptionsPass7241574554SRiver Riddle void runOnOperation() final {}
getArgument__anon0807c3400111::TestOptionsPass73fa51c5afSRiver Riddle StringRef getArgument() const final { return "test-options-pass"; }
getDescription__anon0807c3400111::TestOptionsPass74b5e22e6dSMehdi Amini StringRef getDescription() const final {
75b5e22e6dSMehdi Amini return "Test options parsing capabilities";
76b5e22e6dSMehdi Amini }
7774461512SMLIR Team
786edef135SRiver Riddle ListOption<int> listOption{*this, "list",
7921610e66SRiver Riddle llvm::cl::desc("Example list option")};
8021610e66SRiver Riddle ListOption<std::string> stringListOption{
816edef135SRiver Riddle *this, "string-list", llvm::cl::desc("Example string list option")};
8221610e66SRiver Riddle Option<std::string> stringOption{*this, "string",
8321610e66SRiver Riddle llvm::cl::desc("Example string option")};
8474461512SMLIR Team };
857a7dcc17SRiver Riddle
867a7dcc17SRiver Riddle /// A test pass that always aborts to enable testing the crash recovery
877a7dcc17SRiver Riddle /// mechanism of the pass manager.
885e50dd04SRiver Riddle struct TestCrashRecoveryPass
8980aca1eaSRiver Riddle : public PassWrapper<TestCrashRecoveryPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon0807c3400111::TestCrashRecoveryPass905e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestCrashRecoveryPass)
915e50dd04SRiver Riddle
927a7dcc17SRiver Riddle void runOnOperation() final { abort(); }
getArgument__anon0807c3400111::TestCrashRecoveryPass93fa51c5afSRiver Riddle StringRef getArgument() const final { return "test-pass-crash"; }
getDescription__anon0807c3400111::TestCrashRecoveryPass94b5e22e6dSMehdi Amini StringRef getDescription() const final {
95b5e22e6dSMehdi Amini return "Test a pass in the pass manager that always crashes";
96b5e22e6dSMehdi Amini }
977a7dcc17SRiver Riddle };
9833a64540SRiver Riddle
9964ce90e1SRiver Riddle /// A test pass that always fails to enable testing the failure recovery
10064ce90e1SRiver Riddle /// mechanisms of the pass manager.
1015e50dd04SRiver Riddle struct TestFailurePass : public PassWrapper<TestFailurePass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon0807c3400111::TestFailurePass1025e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestFailurePass)
1035e50dd04SRiver Riddle
10464ce90e1SRiver Riddle void runOnOperation() final { signalPassFailure(); }
getArgument__anon0807c3400111::TestFailurePass105b5e22e6dSMehdi Amini StringRef getArgument() const final { return "test-pass-failure"; }
getDescription__anon0807c3400111::TestFailurePass106b5e22e6dSMehdi Amini StringRef getDescription() const final {
107b5e22e6dSMehdi Amini return "Test a pass in the pass manager that always fails";
108b5e22e6dSMehdi Amini }
10964ce90e1SRiver Riddle };
11064ce90e1SRiver Riddle
11183892d76SMehdi Amini /// A test pass that creates an invalid operation in a function body.
11283892d76SMehdi Amini struct TestInvalidIRPass
11383892d76SMehdi Amini : public PassWrapper<TestInvalidIRPass,
11483892d76SMehdi Amini InterfacePass<FunctionOpInterface>> {
11583892d76SMehdi Amini MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestInvalidIRPass)
11683892d76SMehdi Amini
11783892d76SMehdi Amini TestInvalidIRPass() = default;
TestInvalidIRPass__anon0807c3400111::TestInvalidIRPass118b37d158fSMehdi Amini TestInvalidIRPass(const TestInvalidIRPass &other) : PassWrapper(other) {}
11983892d76SMehdi Amini
getArgument__anon0807c3400111::TestInvalidIRPass12083892d76SMehdi Amini StringRef getArgument() const final { return "test-pass-create-invalid-ir"; }
getDescription__anon0807c3400111::TestInvalidIRPass12183892d76SMehdi Amini StringRef getDescription() const final {
12283892d76SMehdi Amini return "Test pass that adds an invalid operation in a function body";
12383892d76SMehdi Amini }
getDependentDialects__anon0807c3400111::TestInvalidIRPass12483892d76SMehdi Amini void getDependentDialects(DialectRegistry ®istry) const final {
12583892d76SMehdi Amini registry.insert<test::TestDialect>();
12683892d76SMehdi Amini }
runOnOperation__anon0807c3400111::TestInvalidIRPass12783892d76SMehdi Amini void runOnOperation() final {
12883892d76SMehdi Amini if (signalFailure)
12983892d76SMehdi Amini signalPassFailure();
13083892d76SMehdi Amini if (!emitInvalidIR)
13183892d76SMehdi Amini return;
13283892d76SMehdi Amini OpBuilder b(getOperation().getBody());
13383892d76SMehdi Amini OperationState state(b.getUnknownLoc(), "test.any_attr_of_i32_str");
13483892d76SMehdi Amini b.create(state);
13583892d76SMehdi Amini }
13683892d76SMehdi Amini Option<bool> signalFailure{*this, "signal-pass-failure",
13783892d76SMehdi Amini llvm::cl::desc("Trigger a pass failure")};
13883892d76SMehdi Amini Option<bool> emitInvalidIR{*this, "emit-invalid-ir", llvm::cl::init(true),
13983892d76SMehdi Amini llvm::cl::desc("Emit invalid IR")};
14083892d76SMehdi Amini };
14183892d76SMehdi Amini
14250f82e68SRiver Riddle /// A test pass that always fails to enable testing the failure recovery
14350f82e68SRiver Riddle /// mechanisms of the pass manager.
1445e50dd04SRiver Riddle struct TestInvalidParentPass
14550f82e68SRiver Riddle : public PassWrapper<TestInvalidParentPass,
14650f82e68SRiver Riddle InterfacePass<FunctionOpInterface>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon0807c3400111::TestInvalidParentPass1475e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestInvalidParentPass)
1485e50dd04SRiver Riddle
14950f82e68SRiver Riddle StringRef getArgument() const final { return "test-pass-invalid-parent"; }
getDescription__anon0807c3400111::TestInvalidParentPass15050f82e68SRiver Riddle StringRef getDescription() const final {
15150f82e68SRiver Riddle return "Test a pass in the pass manager that makes the parent operation "
15250f82e68SRiver Riddle "invalid";
15350f82e68SRiver Riddle }
getDependentDialects__anon0807c3400111::TestInvalidParentPass15450f82e68SRiver Riddle void getDependentDialects(DialectRegistry ®istry) const final {
15550f82e68SRiver Riddle registry.insert<test::TestDialect>();
15650f82e68SRiver Riddle }
runOnOperation__anon0807c3400111::TestInvalidParentPass15750f82e68SRiver Riddle void runOnOperation() final {
15850f82e68SRiver Riddle FunctionOpInterface op = getOperation();
15950f82e68SRiver Riddle OpBuilder b(getOperation().getBody());
16050f82e68SRiver Riddle b.create<test::TestCallOp>(op.getLoc(), TypeRange(), "some_unknown_func",
16150f82e68SRiver Riddle ValueRange());
16250f82e68SRiver Riddle }
16350f82e68SRiver Riddle };
16450f82e68SRiver Riddle
16533a64540SRiver Riddle /// A test pass that contains a statistic.
16680aca1eaSRiver Riddle struct TestStatisticPass
16780aca1eaSRiver Riddle : public PassWrapper<TestStatisticPass, OperationPass<>> {
1685e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestStatisticPass)
1695e50dd04SRiver Riddle
17033a64540SRiver Riddle TestStatisticPass() = default;
TestStatisticPass__anon0807c3400111::TestStatisticPass1718919447cSJaved Absar TestStatisticPass(const TestStatisticPass &) : PassWrapper() {}
getArgument__anon0807c3400111::TestStatisticPass172b5e22e6dSMehdi Amini StringRef getArgument() const final { return "test-stats-pass"; }
getDescription__anon0807c3400111::TestStatisticPass173b5e22e6dSMehdi Amini StringRef getDescription() const final { return "Test pass statistics"; }
17433a64540SRiver Riddle
175*04644a9eSSlava Zakharin // Use a couple of statistics to verify their ordering
176*04644a9eSSlava Zakharin // in the print out. The statistics are registered in the order
177*04644a9eSSlava Zakharin // of construction, so put "num-ops2" before "num-ops" and
178*04644a9eSSlava Zakharin // make sure that the order is reversed.
179*04644a9eSSlava Zakharin Statistic opCountDuplicate{this, "num-ops2",
180*04644a9eSSlava Zakharin "Number of operations counted one more time"};
18133a64540SRiver Riddle Statistic opCount{this, "num-ops", "Number of operations counted"};
18233a64540SRiver Riddle
runOnOperation__anon0807c3400111::TestStatisticPass18333a64540SRiver Riddle void runOnOperation() final {
18433a64540SRiver Riddle getOperation()->walk([&](Operation *) { ++opCount; });
185*04644a9eSSlava Zakharin getOperation()->walk([&](Operation *) { ++opCountDuplicate; });
18633a64540SRiver Riddle }
18733a64540SRiver Riddle };
188be0a7e9fSMehdi Amini } // namespace
189120509a6SRiver Riddle
testNestedPipeline(OpPassManager & pm)1909274ed66SRiver Riddle static void testNestedPipeline(OpPassManager &pm) {
191120509a6SRiver Riddle // Nest a module pipeline that contains:
192120509a6SRiver Riddle /// A module pass.
193120509a6SRiver Riddle auto &modulePM = pm.nest<ModuleOp>();
194120509a6SRiver Riddle modulePM.addPass(std::make_unique<TestModulePass>());
195120509a6SRiver Riddle /// A nested function pass.
19658ceae95SRiver Riddle auto &nestedFunctionPM = modulePM.nest<func::FuncOp>();
197120509a6SRiver Riddle nestedFunctionPM.addPass(std::make_unique<TestFunctionPass>());
198120509a6SRiver Riddle
199120509a6SRiver Riddle // Nest a function pipeline that contains a single pass.
20058ceae95SRiver Riddle auto &functionPM = pm.nest<func::FuncOp>();
201120509a6SRiver Riddle functionPM.addPass(std::make_unique<TestFunctionPass>());
202120509a6SRiver Riddle }
203120509a6SRiver Riddle
testNestedPipelineTextual(OpPassManager & pm)204d780bdefSRiver Riddle static void testNestedPipelineTextual(OpPassManager &pm) {
205d780bdefSRiver Riddle (void)parsePassPipeline("test-pm-nested-pipeline", pm);
206d780bdefSRiver Riddle }
207d780bdefSRiver Riddle
208c6477050SMehdi Amini namespace mlir {
registerPassManagerTestPass()209c6477050SMehdi Amini void registerPassManagerTestPass() {
210b5e22e6dSMehdi Amini PassRegistration<TestOptionsPass>();
21174461512SMLIR Team
212b5e22e6dSMehdi Amini PassRegistration<TestModulePass>();
2139274ed66SRiver Riddle
214b5e22e6dSMehdi Amini PassRegistration<TestFunctionPass>();
2157a7dcc17SRiver Riddle
2169c9a4317SRiver Riddle PassRegistration<TestInterfacePass>();
2179c9a4317SRiver Riddle
218b5e22e6dSMehdi Amini PassRegistration<TestCrashRecoveryPass>();
219b5e22e6dSMehdi Amini PassRegistration<TestFailurePass>();
22083892d76SMehdi Amini PassRegistration<TestInvalidIRPass>();
22150f82e68SRiver Riddle PassRegistration<TestInvalidParentPass>();
222c6477050SMehdi Amini
223b5e22e6dSMehdi Amini PassRegistration<TestStatisticPass>();
22433a64540SRiver Riddle
225c6477050SMehdi Amini PassPipelineRegistration<>("test-pm-nested-pipeline",
226c6477050SMehdi Amini "Test a nested pipeline in the pass manager",
227c6477050SMehdi Amini testNestedPipeline);
228c6477050SMehdi Amini PassPipelineRegistration<>("test-textual-pm-nested-pipeline",
229d780bdefSRiver Riddle "Test a nested pipeline in the pass manager",
230d780bdefSRiver Riddle testNestedPipelineTextual);
231c6477050SMehdi Amini PassPipelineRegistration<>(
232c6477050SMehdi Amini "test-dump-pipeline",
233ae6946ecSMLIR Team "Dumps the pipeline build so far for debugging purposes",
234ae6946ecSMLIR Team [](OpPassManager &pm) {
235ae6946ecSMLIR Team pm.printAsTextualPipeline(llvm::errs());
236ae6946ecSMLIR Team llvm::errs() << "\n";
237ae6946ecSMLIR Team });
23874461512SMLIR Team
239c6477050SMehdi Amini PassPipelineRegistration<TestOptionsPass::Options>
24074461512SMLIR Team registerOptionsPassPipeline(
24174461512SMLIR Team "test-options-pass-pipeline",
24274461512SMLIR Team "Parses options using pass pipeline registration",
24374461512SMLIR Team [](OpPassManager &pm, const TestOptionsPass::Options &options) {
24474461512SMLIR Team pm.addPass(std::make_unique<TestOptionsPass>(options));
24574461512SMLIR Team });
246c6477050SMehdi Amini }
247c6477050SMehdi Amini } // namespace mlir
248