brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.8 KiB · df2736b Raw
370 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "TestDialect.h"10#include "TestOps.h"11#include "mlir/Dialect/Func/IR/FuncOps.h"12#include "mlir/IR/BuiltinOps.h"13#include "mlir/Pass/Pass.h"14#include "mlir/Pass/PassManager.h"15 16using namespace mlir;17 18namespace {19struct TestModulePass20    : public PassWrapper<TestModulePass, OperationPass<ModuleOp>> {21  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestModulePass)22 23  void runOnOperation() final {}24  StringRef getArgument() const final { return "test-module-pass"; }25  StringRef getDescription() const final {26    return "Test a module pass in the pass manager";27  }28};29struct TestFunctionPass30    : public PassWrapper<TestFunctionPass, OperationPass<func::FuncOp>> {31  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestFunctionPass)32 33  void runOnOperation() final {}34  StringRef getArgument() const final { return "test-function-pass"; }35  StringRef getDescription() const final {36    return "Test a function pass in the pass manager";37  }38};39struct TestInterfacePass40    : public PassWrapper<TestInterfacePass,41                         InterfacePass<FunctionOpInterface>> {42  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestInterfacePass)43 44  void runOnOperation() final {45    getOperation()->emitRemark() << "Executing interface pass on operation";46  }47  StringRef getArgument() const final { return "test-interface-pass"; }48  StringRef getDescription() const final {49    return "Test an interface pass (running on FunctionOpInterface) in the "50           "pass manager";51  }52};53struct TestOptionsPass54    : public PassWrapper<TestOptionsPass, OperationPass<func::FuncOp>> {55  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestOptionsPass)56 57  enum Enum { Zero, One, Two };58 59  struct Options : public PassPipelineOptions<Options> {60    ListOption<int> listOption{*this, "list",61                               llvm::cl::desc("Example list option")};62    ListOption<std::string> stringListOption{63        *this, "string-list", llvm::cl::desc("Example string list option")};64    Option<std::string> stringOption{*this, "string",65                                     llvm::cl::desc("Example string option")};66    Option<Enum> enumOption{67        *this, "enum", llvm::cl::desc("Example enum option"),68        llvm::cl::values(clEnumValN(0, "zero", "Example zero value"),69                         clEnumValN(1, "one", "Example one value"),70                         clEnumValN(2, "two", "Example two value"))};71 72    Options() = default;73    Options(const Options &rhs) { *this = rhs; }74    Options &operator=(const Options &rhs) {75      copyOptionValuesFrom(rhs);76      return *this;77    }78  };79  TestOptionsPass() = default;80  TestOptionsPass(const TestOptionsPass &) : PassWrapper() {}81  TestOptionsPass(const Options &options) {82    listOption = options.listOption;83    stringOption = options.stringOption;84    stringListOption = options.stringListOption;85    enumOption = options.enumOption;86  }87 88  void runOnOperation() final {}89  StringRef getArgument() const final { return "test-options-pass"; }90  StringRef getDescription() const final {91    return "Test options parsing capabilities";92  }93 94  ListOption<int> listOption{*this, "list",95                             llvm::cl::desc("Example list option")};96  ListOption<std::string> stringListOption{97      *this, "string-list", llvm::cl::desc("Example string list option")};98  Option<std::string> stringOption{*this, "string",99                                   llvm::cl::desc("Example string option")};100  Option<Enum> enumOption{101      *this, "enum", llvm::cl::desc("Example enum option"),102      llvm::cl::values(clEnumValN(0, "zero", "Example zero value"),103                       clEnumValN(1, "one", "Example one value"),104                       clEnumValN(2, "two", "Example two value"))};105};106 107struct TestOptionsSuperPass108    : public PassWrapper<TestOptionsSuperPass, OperationPass<func::FuncOp>> {109  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestOptionsSuperPass)110 111  struct Options : public PassPipelineOptions<Options> {112    ListOption<TestOptionsPass::Options> listOption{113        *this, "super-list",114        llvm::cl::desc("Example list of PassPipelineOptions option")};115 116    Options() = default;117  };118 119  TestOptionsSuperPass() = default;120  TestOptionsSuperPass(const TestOptionsSuperPass &) : PassWrapper() {}121  TestOptionsSuperPass(const Options &options) {122    listOption = options.listOption;123  }124 125  void runOnOperation() final {}126  StringRef getArgument() const final { return "test-options-super-pass"; }127  StringRef getDescription() const final {128    return "Test options of options parsing capabilities";129  }130 131  ListOption<TestOptionsPass::Options> listOption{132      *this, "list",133      llvm::cl::desc("Example list of PassPipelineOptions option")};134};135 136struct TestOptionsPassA137    : public PassWrapper<TestOptionsPassA, OperationPass<func::FuncOp>> {138  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestOptionsPassA)139 140  struct Options : public PassPipelineOptions<Options> {141    Option<bool> foo{*this, "foo", llvm::cl::desc("Example boolean option")};142  };143 144  TestOptionsPassA() = default;145  TestOptionsPassA(const TestOptionsPassA &) : PassWrapper() {}146  TestOptionsPassA(const Options &options) { this->options.foo = options.foo; }147 148  void runOnOperation() final {}149  StringRef getArgument() const final { return "test-options-pass-a"; }150  StringRef getDescription() const final {151    return "Test superset options parsing capabilities - subset A";152  }153 154  Options options;155};156 157struct TestOptionsPassB158    : public PassWrapper<TestOptionsPassB, OperationPass<func::FuncOp>> {159  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestOptionsPassB)160 161  struct Options : public PassPipelineOptions<Options> {162    Option<bool> bar{*this, "bar", llvm::cl::desc("Example boolean option")};163  };164 165  TestOptionsPassB() = default;166  TestOptionsPassB(const TestOptionsPassB &) : PassWrapper() {}167  TestOptionsPassB(const Options &options) { this->options.bar = options.bar; }168 169  void runOnOperation() final {}170  StringRef getArgument() const final { return "test-options-pass-b"; }171  StringRef getDescription() const final {172    return "Test superset options parsing capabilities - subset B";173  }174 175  Options options;176};177 178struct TestPipelineOptionsSuperSetAB : TestOptionsPassA::Options,179                                       TestOptionsPassB::Options {};180 181/// A test pass that always aborts to enable testing the crash recovery182/// mechanism of the pass manager.183struct TestCrashRecoveryPass184    : public PassWrapper<TestCrashRecoveryPass, OperationPass<>> {185  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestCrashRecoveryPass)186 187  void runOnOperation() final { abort(); }188  StringRef getArgument() const final { return "test-pass-crash"; }189  StringRef getDescription() const final {190    return "Test a pass in the pass manager that always crashes";191  }192};193 194/// A test pass that always fails to enable testing the failure recovery195/// mechanisms of the pass manager.196struct TestFailurePass : public PassWrapper<TestFailurePass, OperationPass<>> {197  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestFailurePass)198 199  TestFailurePass() = default;200  TestFailurePass(const TestFailurePass &other) : PassWrapper(other) {}201 202  void runOnOperation() final {203    signalPassFailure();204    if (genDiagnostics)205      mlir::emitError(getOperation()->getLoc(), "illegal operation");206  }207  StringRef getArgument() const final { return "test-pass-failure"; }208  StringRef getDescription() const final {209    return "Test a pass in the pass manager that always fails";210  }211 212  Option<bool> genDiagnostics{*this, "gen-diagnostics",213                              llvm::cl::desc("Generate a diagnostic message")};214};215 216/// A test pass that creates an invalid operation in a function body.217struct TestInvalidIRPass218    : public PassWrapper<TestInvalidIRPass,219                         InterfacePass<FunctionOpInterface>> {220  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestInvalidIRPass)221 222  TestInvalidIRPass() = default;223  TestInvalidIRPass(const TestInvalidIRPass &other) : PassWrapper(other) {}224 225  StringRef getArgument() const final { return "test-pass-create-invalid-ir"; }226  StringRef getDescription() const final {227    return "Test pass that adds an invalid operation in a function body";228  }229  void getDependentDialects(DialectRegistry &registry) const final {230    registry.insert<test::TestDialect>();231  }232  void runOnOperation() final {233    if (signalFailure)234      signalPassFailure();235    if (!emitInvalidIR)236      return;237    OpBuilder b(getOperation().getFunctionBody());238    OperationState state(b.getUnknownLoc(), "test.any_attr_of_i32_str");239    b.create(state);240  }241  Option<bool> signalFailure{*this, "signal-pass-failure",242                             llvm::cl::desc("Trigger a pass failure")};243  Option<bool> emitInvalidIR{*this, "emit-invalid-ir", llvm::cl::init(true),244                             llvm::cl::desc("Emit invalid IR")};245};246 247/// A test pass that always fails to enable testing the failure recovery248/// mechanisms of the pass manager.249struct TestInvalidParentPass250    : public PassWrapper<TestInvalidParentPass,251                         InterfacePass<FunctionOpInterface>> {252  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestInvalidParentPass)253 254  StringRef getArgument() const final { return "test-pass-invalid-parent"; }255  StringRef getDescription() const final {256    return "Test a pass in the pass manager that makes the parent operation "257           "invalid";258  }259  void getDependentDialects(DialectRegistry &registry) const final {260    registry.insert<test::TestDialect>();261  }262  void runOnOperation() final {263    FunctionOpInterface op = getOperation();264    OpBuilder b(op.getFunctionBody());265    test::TestCallOp::create(b, op.getLoc(), TypeRange(), "some_unknown_func",266                             ValueRange());267  }268};269 270/// A test pass that contains a statistic.271struct TestStatisticPass272    : public PassWrapper<TestStatisticPass, OperationPass<>> {273  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestStatisticPass)274 275  TestStatisticPass() = default;276  TestStatisticPass(const TestStatisticPass &) : PassWrapper() {}277  StringRef getArgument() const final { return "test-stats-pass"; }278  StringRef getDescription() const final { return "Test pass statistics"; }279 280  // Use a couple of statistics to verify their ordering281  // in the print out. The statistics are registered in the order282  // of construction, so put "num-ops2" before "num-ops" and283  // make sure that the order is reversed.284  Statistic opCountDuplicate{this, "num-ops2",285                             "Number of operations counted one more time"};286  Statistic opCount{this, "num-ops", "Number of operations counted"};287 288  void runOnOperation() final {289    getOperation()->walk([&](Operation *) { ++opCount; });290    getOperation()->walk([&](Operation *) { ++opCountDuplicate; });291  }292};293} // namespace294 295static void testNestedPipeline(OpPassManager &pm) {296  // Nest a module pipeline that contains:297  /// A module pass.298  auto &modulePM = pm.nest<ModuleOp>();299  modulePM.addPass(std::make_unique<TestModulePass>());300  /// A nested function pass.301  auto &nestedFunctionPM = modulePM.nest<func::FuncOp>();302  nestedFunctionPM.addPass(std::make_unique<TestFunctionPass>());303 304  // Nest a function pipeline that contains a single pass.305  auto &functionPM = pm.nest<func::FuncOp>();306  functionPM.addPass(std::make_unique<TestFunctionPass>());307}308 309static void testNestedPipelineTextual(OpPassManager &pm) {310  (void)parsePassPipeline("test-pm-nested-pipeline", pm);311}312 313namespace mlir {314void registerPassManagerTestPass() {315  PassRegistration<TestOptionsPass>();316  PassRegistration<TestOptionsSuperPass>();317 318  PassRegistration<TestOptionsPassA>();319  PassRegistration<TestOptionsPassB>();320 321  PassRegistration<TestModulePass>();322 323  PassRegistration<TestFunctionPass>();324 325  PassRegistration<TestInterfacePass>();326 327  PassRegistration<TestCrashRecoveryPass>();328  PassRegistration<TestFailurePass>();329  PassRegistration<TestInvalidIRPass>();330  PassRegistration<TestInvalidParentPass>();331 332  PassRegistration<TestStatisticPass>();333 334  PassPipelineRegistration<>("test-pm-nested-pipeline",335                             "Test a nested pipeline in the pass manager",336                             testNestedPipeline);337  PassPipelineRegistration<>("test-textual-pm-nested-pipeline",338                             "Test a nested pipeline in the pass manager",339                             testNestedPipelineTextual);340 341  PassPipelineRegistration<TestOptionsPass::Options>342      registerOptionsPassPipeline(343          "test-options-pass-pipeline",344          "Parses options using pass pipeline registration",345          [](OpPassManager &pm, const TestOptionsPass::Options &options) {346            pm.addPass(std::make_unique<TestOptionsPass>(options));347          });348 349  PassPipelineRegistration<TestOptionsSuperPass::Options>350      registerOptionsSuperPassPipeline(351          "test-options-super-pass-pipeline",352          "Parses options of PassPipelineOptions using pass pipeline "353          "registration",354          [](OpPassManager &pm, const TestOptionsSuperPass::Options &options) {355            pm.addPass(std::make_unique<TestOptionsSuperPass>(options));356          });357 358  PassPipelineRegistration<TestPipelineOptionsSuperSetAB>359      registerPipelineOptionsSuperSetABPipeline(360          "test-options-super-set-ab-pipeline",361          "Parses options of PassPipelineOptions using pass pipeline "362          "registration",363          [](OpPassManager &pm, const TestPipelineOptionsSuperSetAB &options) {364            // Pass superset AB options to subset options A and B365            pm.addPass(std::make_unique<TestOptionsPassA>(options));366            pm.addPass(std::make_unique<TestOptionsPassB>(options));367          });368}369} // namespace mlir370