brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.8 KiB · 2e6950f Raw
279 lines · cpp
1//===- ControlFlowInterfacesTest.cpp - Unit Tests for Control Flow Interf. ===//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 "mlir/Interfaces/ControlFlowInterfaces.h"10#include "mlir/IR/BuiltinOps.h"11#include "mlir/IR/Dialect.h"12#include "mlir/IR/DialectImplementation.h"13#include "mlir/IR/OpDefinition.h"14#include "mlir/IR/OpImplementation.h"15#include "mlir/Parser/Parser.h"16#include "llvm/Support/DebugLog.h"17 18#include <gtest/gtest.h>19 20using namespace mlir;21 22/// A dummy op that is also a terminator.23struct DummyOp : public Op<DummyOp, OpTrait::IsTerminator, OpTrait::ZeroResults,24                           OpTrait::ZeroSuccessors,25                           RegionBranchTerminatorOpInterface::Trait> {26  using Op::Op;27  static ArrayRef<StringRef> getAttributeNames() { return {}; }28 29  static StringRef getOperationName() { return "cftest.dummy_op"; }30 31  MutableOperandRange getMutableSuccessorOperands(RegionSuccessor point) {32    return MutableOperandRange(getOperation(), 0, 0);33  }34};35 36/// All regions of this op are mutually exclusive.37struct MutuallyExclusiveRegionsOp38    : public Op<MutuallyExclusiveRegionsOp, RegionBranchOpInterface::Trait> {39  using Op::Op;40  static ArrayRef<StringRef> getAttributeNames() { return {}; }41 42  static StringRef getOperationName() {43    return "cftest.mutually_exclusive_regions_op";44  }45 46  // Regions have no successors.47  void getSuccessorRegions(RegionBranchPoint point,48                           SmallVectorImpl<RegionSuccessor> &regions) {}49  using RegionBranchOpInterface::Trait<50      MutuallyExclusiveRegionsOp>::getSuccessorRegions;51};52 53/// All regions of this op call each other in a large circle.54struct LoopRegionsOp55    : public Op<LoopRegionsOp, RegionBranchOpInterface::Trait> {56  using Op::Op;57  static const unsigned kNumRegions = 3;58 59  static ArrayRef<StringRef> getAttributeNames() { return {}; }60 61  static StringRef getOperationName() { return "cftest.loop_regions_op"; }62 63  void getSuccessorRegions(RegionBranchPoint point,64                           SmallVectorImpl<RegionSuccessor> &regions) {65    if (point.getTerminatorPredecessorOrNull()) {66      Region *region =67          point.getTerminatorPredecessorOrNull()->getParentRegion();68      if (region == &(*this)->getRegion(1))69        // This region also branches back to the parent.70        regions.push_back(71            RegionSuccessor(getOperation()->getParentOp(),72                            getOperation()->getParentOp()->getResults()));73      regions.push_back(RegionSuccessor(region));74    }75  }76  using RegionBranchOpInterface::Trait<LoopRegionsOp>::getSuccessorRegions;77};78 79/// Each region branches back it itself or the parent.80struct DoubleLoopRegionsOp81    : public Op<DoubleLoopRegionsOp, RegionBranchOpInterface::Trait> {82  using Op::Op;83 84  static ArrayRef<StringRef> getAttributeNames() { return {}; }85 86  static StringRef getOperationName() {87    return "cftest.double_loop_regions_op";88  }89 90  void getSuccessorRegions(RegionBranchPoint point,91                           SmallVectorImpl<RegionSuccessor> &regions) {92    if (point.getTerminatorPredecessorOrNull()) {93      Region *region =94          point.getTerminatorPredecessorOrNull()->getParentRegion();95      regions.push_back(96          RegionSuccessor(getOperation()->getParentOp(),97                          getOperation()->getParentOp()->getResults()));98      regions.push_back(RegionSuccessor(region));99    }100  }101  using RegionBranchOpInterface::Trait<102      DoubleLoopRegionsOp>::getSuccessorRegions;103};104 105/// Regions are executed sequentially.106struct SequentialRegionsOp107    : public Op<SequentialRegionsOp, RegionBranchOpInterface::Trait> {108  using Op::Op;109  static ArrayRef<StringRef> getAttributeNames() { return {}; }110 111  static StringRef getOperationName() { return "cftest.sequential_regions_op"; }112 113  // Region 0 has Region 1 as a successor.114  void getSuccessorRegions(RegionBranchPoint point,115                           SmallVectorImpl<RegionSuccessor> &regions) {116    if (point.getTerminatorPredecessorOrNull() &&117        point.getTerminatorPredecessorOrNull()->getParentRegion() ==118            &(*this)->getRegion(0)) {119      Operation *thisOp = this->getOperation();120      regions.push_back(RegionSuccessor(&thisOp->getRegion(1)));121    }122  }123  using RegionBranchOpInterface::Trait<124      SequentialRegionsOp>::getSuccessorRegions;125};126 127/// A dialect putting all the above together.128struct CFTestDialect : Dialect {129  explicit CFTestDialect(MLIRContext *ctx)130      : Dialect(getDialectNamespace(), ctx, TypeID::get<CFTestDialect>()) {131    addOperations<DummyOp, MutuallyExclusiveRegionsOp, LoopRegionsOp,132                  DoubleLoopRegionsOp, SequentialRegionsOp>();133  }134  static StringRef getDialectNamespace() { return "cftest"; }135};136 137TEST(RegionBranchOpInterface, MutuallyExclusiveOps) {138  const char *ir = R"MLIR(139"cftest.mutually_exclusive_regions_op"() (140      {"cftest.dummy_op"() : () -> ()},  // op1141      {"cftest.dummy_op"() : () -> ()}   // op2142  ) : () -> ()143  )MLIR";144 145  DialectRegistry registry;146  registry.insert<CFTestDialect>();147  MLIRContext ctx(registry);148 149  OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx);150  Operation *testOp = &module->getBody()->getOperations().front();151  Operation *op1 = &testOp->getRegion(0).front().front();152  Operation *op2 = &testOp->getRegion(1).front().front();153 154  EXPECT_TRUE(insideMutuallyExclusiveRegions(op1, op2));155  EXPECT_TRUE(insideMutuallyExclusiveRegions(op2, op1));156}157 158TEST(RegionBranchOpInterface, MutuallyExclusiveOps2) {159  const char *ir = R"MLIR(160"cftest.double_loop_regions_op"() (161      {"cftest.dummy_op"() : () -> ()},  // op1162      {"cftest.dummy_op"() : () -> ()}   // op2163  ) : () -> ()164  )MLIR";165 166  DialectRegistry registry;167  registry.insert<CFTestDialect>();168  MLIRContext ctx(registry);169 170  OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx);171  Operation *testOp = &module->getBody()->getOperations().front();172  Operation *op1 = &testOp->getRegion(0).front().front();173  Operation *op2 = &testOp->getRegion(1).front().front();174 175  EXPECT_TRUE(insideMutuallyExclusiveRegions(op1, op2));176  EXPECT_TRUE(insideMutuallyExclusiveRegions(op2, op1));177}178 179TEST(RegionBranchOpInterface, NotMutuallyExclusiveOps) {180  const char *ir = R"MLIR(181"cftest.sequential_regions_op"() (182      {"cftest.dummy_op"() : () -> ()},  // op1183      {"cftest.dummy_op"() : () -> ()}   // op2184  ) : () -> ()185  )MLIR";186 187  DialectRegistry registry;188  registry.insert<CFTestDialect>();189  MLIRContext ctx(registry);190 191  OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx);192  Operation *testOp = &module->getBody()->getOperations().front();193  Operation *op1 = &testOp->getRegion(0).front().front();194  Operation *op2 = &testOp->getRegion(1).front().front();195 196  EXPECT_FALSE(insideMutuallyExclusiveRegions(op1, op2));197  EXPECT_FALSE(insideMutuallyExclusiveRegions(op2, op1));198}199 200TEST(RegionBranchOpInterface, NestedMutuallyExclusiveOps) {201  const char *ir = R"MLIR(202"cftest.mutually_exclusive_regions_op"() (203      {204        "cftest.sequential_regions_op"() (205              {"cftest.dummy_op"() : () -> ()},  // op1206              {"cftest.dummy_op"() : () -> ()}   // op3207          ) : () -> ()208        "cftest.dummy_op"() : () -> ()209      },210      {"cftest.dummy_op"() : () -> ()}           // op2211  ) : () -> ()212  )MLIR";213 214  DialectRegistry registry;215  registry.insert<CFTestDialect>();216  MLIRContext ctx(registry);217 218  OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx);219  Operation *testOp = &module->getBody()->getOperations().front();220  Operation *op1 =221      &testOp->getRegion(0).front().front().getRegion(0).front().front();222  Operation *op2 = &testOp->getRegion(1).front().front();223  Operation *op3 =224      &testOp->getRegion(0).front().front().getRegion(1).front().front();225 226  EXPECT_TRUE(insideMutuallyExclusiveRegions(op1, op2));227  EXPECT_TRUE(insideMutuallyExclusiveRegions(op3, op2));228  EXPECT_FALSE(insideMutuallyExclusiveRegions(op1, op3));229}230 231TEST(RegionBranchOpInterface, RecursiveRegions) {232  const char *ir = R"MLIR(233"cftest.loop_regions_op"() (234      {"cftest.dummy_op"() : () -> ()},  // op1235      {"cftest.dummy_op"() : () -> ()},  // op2236      {"cftest.dummy_op"() : () -> ()}   // op3237  ) : () -> ()238  )MLIR";239 240  DialectRegistry registry;241  registry.insert<CFTestDialect>();242  MLIRContext ctx(registry);243 244  OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx);245  Operation *testOp = &module->getBody()->getOperations().front();246  auto regionOp = cast<RegionBranchOpInterface>(testOp);247  Operation *op1 = &testOp->getRegion(0).front().front();248  Operation *op2 = &testOp->getRegion(1).front().front();249  Operation *op3 = &testOp->getRegion(2).front().front();250 251  EXPECT_TRUE(regionOp.isRepetitiveRegion(0));252  EXPECT_TRUE(regionOp.isRepetitiveRegion(1));253  EXPECT_TRUE(regionOp.isRepetitiveRegion(2));254  EXPECT_NE(getEnclosingRepetitiveRegion(op1), nullptr);255  EXPECT_NE(getEnclosingRepetitiveRegion(op2), nullptr);256  EXPECT_NE(getEnclosingRepetitiveRegion(op3), nullptr);257}258 259TEST(RegionBranchOpInterface, NotRecursiveRegions) {260  const char *ir = R"MLIR(261"cftest.sequential_regions_op"() (262      {"cftest.dummy_op"() : () -> ()},  // op1263      {"cftest.dummy_op"() : () -> ()}   // op2264  ) : () -> ()265  )MLIR";266 267  DialectRegistry registry;268  registry.insert<CFTestDialect>();269  MLIRContext ctx(registry);270 271  OwningOpRef<ModuleOp> module = parseSourceString<ModuleOp>(ir, &ctx);272  Operation *testOp = &module->getBody()->getOperations().front();273  Operation *op1 = &testOp->getRegion(0).front().front();274  Operation *op2 = &testOp->getRegion(1).front().front();275 276  EXPECT_EQ(getEnclosingRepetitiveRegion(op1), nullptr);277  EXPECT_EQ(getEnclosingRepetitiveRegion(op2), nullptr);278}279