brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.2 KiB · 9f3e7ed Raw
360 lines · cpp
1//===- OperationSupportTest.cpp - Operation support unit tests ------------===//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/IR/OperationSupport.h"10#include "../../test/lib/Dialect/Test/TestDialect.h"11#include "../../test/lib/Dialect/Test/TestOps.h"12#include "mlir/IR/Builders.h"13#include "mlir/IR/BuiltinTypes.h"14#include "llvm/ADT/BitVector.h"15#include "llvm/Support/FormatVariadic.h"16#include "gtest/gtest.h"17 18using namespace mlir;19using namespace mlir::detail;20 21static Operation *createOp(MLIRContext *context, ArrayRef<Value> operands = {},22                           ArrayRef<Type> resultTypes = {},23                           unsigned int numRegions = 0) {24  context->allowUnregisteredDialects();25  return Operation::create(UnknownLoc::get(context),26                           OperationName("foo.bar", context), resultTypes,27                           operands, NamedAttrList(), nullptr, {}, numRegions);28}29 30namespace {31TEST(OperandStorageTest, NonResizable) {32  MLIRContext context;33  Builder builder(&context);34 35  Operation *useOp =36      createOp(&context, /*operands=*/{}, builder.getIntegerType(16));37  Value operand = useOp->getResult(0);38 39  // Create a non-resizable operation with one operand.40  Operation *user = createOp(&context, operand);41 42  // The same number of operands is okay.43  user->setOperands(operand);44  EXPECT_EQ(user->getNumOperands(), 1u);45 46  // Removing is okay.47  user->setOperands({});48  EXPECT_EQ(user->getNumOperands(), 0u);49 50  // Destroy the operations.51  user->destroy();52  useOp->destroy();53}54 55TEST(OperandStorageTest, Resizable) {56  MLIRContext context;57  Builder builder(&context);58 59  Operation *useOp =60      createOp(&context, /*operands=*/{}, builder.getIntegerType(16));61  Value operand = useOp->getResult(0);62 63  // Create a resizable operation with one operand.64  Operation *user = createOp(&context, operand);65 66  // The same number of operands is okay.67  user->setOperands(operand);68  EXPECT_EQ(user->getNumOperands(), 1u);69 70  // Removing is okay.71  user->setOperands({});72  EXPECT_EQ(user->getNumOperands(), 0u);73 74  // Adding more operands is okay.75  user->setOperands({operand, operand, operand});76  EXPECT_EQ(user->getNumOperands(), 3u);77 78  // Destroy the operations.79  user->destroy();80  useOp->destroy();81}82 83TEST(OperandStorageTest, RangeReplace) {84  MLIRContext context;85  Builder builder(&context);86 87  Operation *useOp =88      createOp(&context, /*operands=*/{}, builder.getIntegerType(16));89  Value operand = useOp->getResult(0);90 91  // Create a resizable operation with one operand.92  Operation *user = createOp(&context, operand);93 94  // Check setting with the same number of operands.95  user->setOperands(/*start=*/0, /*length=*/1, operand);96  EXPECT_EQ(user->getNumOperands(), 1u);97 98  // Check setting with more operands.99  user->setOperands(/*start=*/0, /*length=*/1, {operand, operand, operand});100  EXPECT_EQ(user->getNumOperands(), 3u);101 102  // Check setting with less operands.103  user->setOperands(/*start=*/1, /*length=*/2, {operand});104  EXPECT_EQ(user->getNumOperands(), 2u);105 106  // Check inserting without replacing operands.107  user->setOperands(/*start=*/2, /*length=*/0, {operand});108  EXPECT_EQ(user->getNumOperands(), 3u);109 110  // Check erasing operands.111  user->setOperands(/*start=*/0, /*length=*/3, {});112  EXPECT_EQ(user->getNumOperands(), 0u);113 114  // Destroy the operations.115  user->destroy();116  useOp->destroy();117}118 119TEST(OperandStorageTest, MutableRange) {120  MLIRContext context;121  Builder builder(&context);122 123  Operation *useOp =124      createOp(&context, /*operands=*/{}, builder.getIntegerType(16));125  Value operand = useOp->getResult(0);126 127  // Create a resizable operation with one operand.128  Operation *user = createOp(&context, operand);129 130  // Check setting with the same number of operands.131  MutableOperandRange mutableOperands(user);132  mutableOperands.assign(operand);133  EXPECT_EQ(mutableOperands.size(), 1u);134  EXPECT_EQ(user->getNumOperands(), 1u);135 136  // Check setting with more operands.137  mutableOperands.assign({operand, operand, operand});138  EXPECT_EQ(mutableOperands.size(), 3u);139  EXPECT_EQ(user->getNumOperands(), 3u);140 141  // Check with inserting a new operand.142  mutableOperands.append({operand, operand});143  EXPECT_EQ(mutableOperands.size(), 5u);144  EXPECT_EQ(user->getNumOperands(), 5u);145 146  // Check erasing operands.147  mutableOperands.clear();148  EXPECT_EQ(mutableOperands.size(), 0u);149  EXPECT_EQ(user->getNumOperands(), 0u);150 151  // Destroy the operations.152  user->destroy();153  useOp->destroy();154}155 156TEST(OperandStorageTest, RangeErase) {157  MLIRContext context;158  Builder builder(&context);159 160  Type type = builder.getNoneType();161  Operation *useOp = createOp(&context, /*operands=*/{}, {type, type});162  Value operand1 = useOp->getResult(0);163  Value operand2 = useOp->getResult(1);164 165  // Create an operation with operands to erase.166  Operation *user =167      createOp(&context, {operand2, operand1, operand2, operand1});168  BitVector eraseIndices(user->getNumOperands());169 170  // Check erasing no operands.171  user->eraseOperands(eraseIndices);172  EXPECT_EQ(user->getNumOperands(), 4u);173 174  // Check erasing disjoint operands.175  eraseIndices.set(0);176  eraseIndices.set(3);177  user->eraseOperands(eraseIndices);178  EXPECT_EQ(user->getNumOperands(), 2u);179  EXPECT_EQ(user->getOperand(0), operand1);180  EXPECT_EQ(user->getOperand(1), operand2);181 182  // Destroy the operations.183  user->destroy();184  useOp->destroy();185}186 187TEST(OperationOrderTest, OrderIsAlwaysValid) {188  MLIRContext context;189  Builder builder(&context);190 191  Operation *containerOp = createOp(&context, /*operands=*/{},192                                    /*resultTypes=*/{},193                                    /*numRegions=*/1);194  Region &region = containerOp->getRegion(0);195  Block *block = new Block();196  region.push_back(block);197 198  // Insert two operations, then iteratively add more operations in the middle199  // of them. Eventually we will insert more than kOrderStride operations and200  // the block order will need to be recomputed.201  Operation *frontOp = createOp(&context);202  Operation *backOp = createOp(&context);203  block->push_back(frontOp);204  block->push_back(backOp);205 206  // Chosen to be larger than Operation::kOrderStride.207  int kNumOpsToInsert = 10;208  for (int i = 0; i < kNumOpsToInsert; ++i) {209    Operation *op = createOp(&context);210    block->getOperations().insert(backOp->getIterator(), op);211    ASSERT_TRUE(op->isBeforeInBlock(backOp));212    // Note verifyOpOrder() returns false if the order is valid.213    ASSERT_FALSE(block->verifyOpOrder());214  }215 216  containerOp->destroy();217}218 219TEST(OperationFormatPrintTest, CanUseVariadicFormat) {220  MLIRContext context;221  Builder builder(&context);222 223  Operation *op = createOp(&context);224 225  std::string str = formatv("{0}", *op).str();226  ASSERT_STREQ(str.c_str(), "\"foo.bar\"() : () -> ()");227 228  op->destroy();229}230 231TEST(OperationFormatPrintTest, CanPrintNameAsPrefix) {232  MLIRContext context;233  Builder builder(&context);234 235  context.allowUnregisteredDialects();236  Operation *op = Operation::create(237      NameLoc::get(StringAttr::get(&context, "my_named_loc")),238      OperationName("t.op", &context), builder.getIntegerType(16), {},239      NamedAttrList(), nullptr, {}, 0);240 241  std::string str;242  OpPrintingFlags flags;243  flags.printNameLocAsPrefix(true);244  llvm::raw_string_ostream os(str);245  op->print(os, flags);246  ASSERT_STREQ(str.c_str(), "%my_named_loc = \"t.op\"() : () -> i16\n");247 248  op->destroy();249}250 251TEST(NamedAttrListTest, TestAppendAssign) {252  MLIRContext ctx;253  NamedAttrList attrs;254  Builder b(&ctx);255 256  attrs.append(b.getStringAttr("foo"), b.getStringAttr("bar"));257  attrs.append("baz", b.getStringAttr("boo"));258 259  {260    auto *it = attrs.begin();261    EXPECT_EQ(it->getName(), b.getStringAttr("foo"));262    EXPECT_EQ(it->getValue(), b.getStringAttr("bar"));263    ++it;264    EXPECT_EQ(it->getName(), b.getStringAttr("baz"));265    EXPECT_EQ(it->getValue(), b.getStringAttr("boo"));266  }267 268  attrs.append("foo", b.getStringAttr("zoo"));269  {270    auto dup = attrs.findDuplicate();271    ASSERT_TRUE(dup.has_value());272  }273 274  SmallVector<NamedAttribute> newAttrs = {275      b.getNamedAttr("foo", b.getStringAttr("f")),276      b.getNamedAttr("zoo", b.getStringAttr("z")),277  };278  attrs.assign(newAttrs);279 280  auto dup = attrs.findDuplicate();281  ASSERT_FALSE(dup.has_value());282 283  {284    auto *it = attrs.begin();285    EXPECT_EQ(it->getName(), b.getStringAttr("foo"));286    EXPECT_EQ(it->getValue(), b.getStringAttr("f"));287    ++it;288    EXPECT_EQ(it->getName(), b.getStringAttr("zoo"));289    EXPECT_EQ(it->getValue(), b.getStringAttr("z"));290  }291 292  attrs.assign({});293  ASSERT_TRUE(attrs.empty());294}295 296TEST(OperandStorageTest, PopulateDefaultAttrs) {297  MLIRContext context;298  context.getOrLoadDialect<test::TestDialect>();299  Builder builder(&context);300 301  OpBuilder b(&context);302  auto req1 = b.getI32IntegerAttr(10);303  auto req2 = b.getI32IntegerAttr(60);304  // Verify default attributes populated post op creation.305  Operation *op = test::OpAttrMatch1::create(b, b.getUnknownLoc(), req1,306                                             nullptr, nullptr, req2);307  auto opt = op->getInherentAttr("default_valued_attr");308  EXPECT_NE(opt, nullptr) << *op;309 310  op->destroy();311}312 313TEST(OperationEquivalenceTest, HashWorksWithFlags) {314  MLIRContext context;315  context.getOrLoadDialect<test::TestDialect>();316  OpBuilder b(&context);317 318  auto *op1 = createOp(&context);319  // `op1` has an unknown loc.320  auto *op2 = createOp(&context);321  op2->setLoc(NameLoc::get(StringAttr::get(&context, "foo")));322  auto getHash = [](Operation *op, OperationEquivalence::Flags flags) {323    return OperationEquivalence::computeHash(324        op, OperationEquivalence::ignoreHashValue,325        OperationEquivalence::ignoreHashValue, flags);326  };327  // Check ignore location.328  EXPECT_EQ(getHash(op1, OperationEquivalence::IgnoreLocations),329            getHash(op2, OperationEquivalence::IgnoreLocations));330  EXPECT_NE(getHash(op1, OperationEquivalence::None),331            getHash(op2, OperationEquivalence::None));332  op1->setLoc(NameLoc::get(StringAttr::get(&context, "foo")));333  // Check ignore discardable dictionary attributes.334  SmallVector<NamedAttribute> newAttrs = {335      b.getNamedAttr("foo", b.getStringAttr("f"))};336  op1->setAttrs(newAttrs);337  EXPECT_EQ(getHash(op1, OperationEquivalence::IgnoreDiscardableAttrs),338            getHash(op2, OperationEquivalence::IgnoreDiscardableAttrs));339  EXPECT_NE(getHash(op1, OperationEquivalence::None),340            getHash(op2, OperationEquivalence::None));341  op1->destroy();342  op2->destroy();343 344  // Check ignore properties.345  auto req1 = b.getI32IntegerAttr(10);346  Operation *opWithProperty1 = test::OpAttrMatch1::create(347      b, b.getUnknownLoc(), req1, nullptr, nullptr, req1);348  auto req2 = b.getI32IntegerAttr(60);349  Operation *opWithProperty2 = test::OpAttrMatch1::create(350      b, b.getUnknownLoc(), req2, nullptr, nullptr, req2);351  EXPECT_EQ(getHash(opWithProperty1, OperationEquivalence::IgnoreProperties),352            getHash(opWithProperty2, OperationEquivalence::IgnoreProperties));353  EXPECT_NE(getHash(opWithProperty1, OperationEquivalence::None),354            getHash(opWithProperty2, OperationEquivalence::None));355  opWithProperty1->destroy();356  opWithProperty2->destroy();357}358 359} // namespace360