brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.2 KiB · 0943033 Raw
312 lines · cpp
1//===- OpBuildGen.cpp - TableGen OpBuildGen 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// Test TableGen generated build() methods on Operations.10//11//===----------------------------------------------------------------------===//12 13#include "TestDialect.h"14#include "TestOps.h"15#include "mlir/IR/Attributes.h"16#include "mlir/IR/Builders.h"17#include "mlir/IR/BuiltinTypes.h"18#include "mlir/IR/Dialect.h"19#include "gmock/gmock.h"20#include <vector>21 22namespace mlir {23 24//===----------------------------------------------------------------------===//25// Test Fixture26//===----------------------------------------------------------------------===//27 28static MLIRContext &getContext() {29  static MLIRContext ctx;30  ctx.getOrLoadDialect<test::TestDialect>();31  return ctx;32}33/// Test fixture for providing basic utilities for testing.34class OpBuildGenTest : public ::testing::Test {35protected:36  OpBuildGenTest()37      : ctx(getContext()), builder(&ctx), loc(builder.getUnknownLoc()),38        i32Ty(builder.getI32Type()), f32Ty(builder.getF32Type()),39        cstI32(test::TableGenConstant::create(builder, loc, i32Ty)),40        cstF32(test::TableGenConstant::create(builder, loc, f32Ty)), noAttrs(),41        attrStorage{42            builder.getNamedAttr("attr0", builder.getBoolAttr(true)),43            builder.getNamedAttr("attr1", builder.getI32IntegerAttr(33))},44        attrs(attrStorage) {}45 46  // Verify that `op` has the given set of result types, operands, and47  // attributes.48  template <typename OpTy>49  void verifyOp(OpTy &&concreteOp, std::vector<Type> resultTypes,50                std::vector<Value> operands,51                std::vector<NamedAttribute> attrs) {52    ASSERT_NE(concreteOp, nullptr);53    Operation *op = concreteOp.getOperation();54 55    EXPECT_EQ(op->getNumResults(), resultTypes.size());56    for (unsigned idx : llvm::seq(0U, op->getNumResults()))57      EXPECT_EQ(op->getResult(idx).getType(), resultTypes[idx]);58 59    EXPECT_EQ(op->getNumOperands(), operands.size());60    for (unsigned idx : llvm::seq(0U, op->getNumOperands()))61      EXPECT_EQ(op->getOperand(idx), operands[idx]);62 63    EXPECT_EQ(op->getAttrs().size(), attrs.size());64    for (unsigned idx : llvm::seq<unsigned>(0U, attrs.size()))65      EXPECT_EQ(op->getAttr(attrs[idx].getName().strref()),66                attrs[idx].getValue());67 68    EXPECT_TRUE(mlir::succeeded(concreteOp.verify()));69    concreteOp.erase();70  }71 72  template <typename OpTy>73  void verifyOp(OpTy &&concreteOp, std::vector<Type> resultTypes,74                std::vector<Value> operands1, std::vector<Value> operands2,75                std::vector<NamedAttribute> attrs) {76    ASSERT_NE(concreteOp, nullptr);77    Operation *op = concreteOp.getOperation();78 79    EXPECT_EQ(op->getNumResults(), resultTypes.size());80    for (unsigned idx : llvm::seq(0U, op->getNumResults()))81      EXPECT_EQ(op->getResult(idx).getType(), resultTypes[idx]);82 83    auto operands = llvm::to_vector(llvm::concat<Value>(operands1, operands2));84    EXPECT_EQ(op->getNumOperands(), operands.size());85    for (unsigned idx : llvm::seq(0U, op->getNumOperands()))86      EXPECT_EQ(op->getOperand(idx), operands[idx]);87 88    EXPECT_EQ(op->getAttrs().size(), attrs.size());89    if (op->getAttrs().size() != attrs.size()) {90      // Simple export where there is mismatch count.91      llvm::errs() << "Op attrs:\n";92      for (auto it : op->getAttrs())93        llvm::errs() << "\t" << it.getName() << " = " << it.getValue() << "\n";94 95      llvm::errs() << "Expected attrs:\n";96      for (auto it : attrs)97        llvm::errs() << "\t" << it.getName() << " = " << it.getValue() << "\n";98    } else {99      for (unsigned idx : llvm::seq<unsigned>(0U, attrs.size()))100        EXPECT_EQ(op->getAttr(attrs[idx].getName().strref()),101                  attrs[idx].getValue());102    }103 104    EXPECT_TRUE(mlir::succeeded(concreteOp.verify()));105    concreteOp.erase();106  }107 108protected:109  MLIRContext &ctx;110  OpBuilder builder;111  Location loc;112  Type i32Ty;113  Type f32Ty;114  OwningOpRef<test::TableGenConstant> cstI32;115  OwningOpRef<test::TableGenConstant> cstF32;116 117  ArrayRef<NamedAttribute> noAttrs;118  std::vector<NamedAttribute> attrStorage;119  ArrayRef<NamedAttribute> attrs;120};121 122/// Test basic build methods.123TEST_F(OpBuildGenTest, BasicBuildMethods) {124  // Test separate args, separate results build method.125  auto op = test::TableGenBuildOp0::create(builder, loc, i32Ty, *cstI32);126  verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);127 128  // Test separate args, collective results build method.129  op = test::TableGenBuildOp0::create(builder, loc, TypeRange{i32Ty}, *cstI32);130  verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);131 132  // Test collective args, collective params build method.133  op = test::TableGenBuildOp0::create(builder, loc, TypeRange{i32Ty},134                                      ValueRange{*cstI32});135  verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);136 137  // Test collective args, collective results, non-empty attributes138  op = test::TableGenBuildOp0::create(builder, loc, TypeRange{i32Ty},139                                      ValueRange{*cstI32}, attrs);140  verifyOp(op, {i32Ty}, {*cstI32}, attrs);141}142 143/// The following 3 tests exercise build methods generated for operations144/// with a combination of:145///146/// single variadic arg x147/// {single variadic result, non-variadic result, multiple variadic results}148///149/// Specifically to test that ODS framework does not generate ambiguous150/// build() methods that fail to compile.151 152/// Test build methods for an Op with a single varadic arg and a single153/// variadic result.154TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgAndResult) {155  // Test collective args, collective results method, building a unary op.156  auto op = test::TableGenBuildOp1::create(builder, loc, TypeRange{i32Ty},157                                           ValueRange{*cstI32});158  verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);159 160  // Test collective args, collective results method, building a unary op with161  // named attributes.162  op = test::TableGenBuildOp1::create(builder, loc, TypeRange{i32Ty},163                                      ValueRange{*cstI32}, attrs);164  verifyOp(op, {i32Ty}, {*cstI32}, attrs);165 166  // Test collective args, collective results method, building a binary op.167  op = test::TableGenBuildOp1::create(builder, loc, TypeRange{i32Ty, f32Ty},168                                      ValueRange{*cstI32, *cstF32});169  verifyOp(op, {i32Ty, f32Ty}, {*cstI32, *cstF32}, noAttrs);170 171  // Test collective args, collective results method, building a binary op with172  // named attributes.173  op = test::TableGenBuildOp1::create(builder, loc, TypeRange{i32Ty, f32Ty},174                                      ValueRange{*cstI32, *cstF32}, attrs);175  verifyOp(op, {i32Ty, f32Ty}, {*cstI32, *cstF32}, attrs);176}177 178/// Test build methods for an Op with a single varadic arg and a non-variadic179/// result.180TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgNonVariadicResults) {181  // Test separate arg, separate param build method.182  auto op =183      test::TableGenBuildOp1::create(builder, loc, i32Ty, ValueRange{*cstI32});184  verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);185 186  // Test collective params build method, no attributes.187  op = test::TableGenBuildOp1::create(builder, loc, TypeRange{i32Ty},188                                      ValueRange{*cstI32});189  verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);190 191  // Test collective params build method no attributes, 2 inputs.192  op = test::TableGenBuildOp1::create(builder, loc, TypeRange{i32Ty},193                                      ValueRange{*cstI32, *cstF32});194  verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, noAttrs);195 196  // Test collective params build method, non-empty attributes.197  op = test::TableGenBuildOp1::create(builder, loc, TypeRange{i32Ty},198                                      ValueRange{*cstI32, *cstF32}, attrs);199  verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, attrs);200}201 202/// Test build methods for an Op with a single varadic arg and multiple variadic203/// result.204TEST_F(OpBuildGenTest,205       BuildMethodsSingleVariadicArgAndMultipleVariadicResults) {206  // Test separate arg, separate param build method.207  auto op = test::TableGenBuildOp3::create(208      builder, loc, TypeRange{i32Ty}, TypeRange{f32Ty}, ValueRange{*cstI32});209  verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, noAttrs);210 211  // Test collective params build method, no attributes.212  op = test::TableGenBuildOp3::create(builder, loc, TypeRange{i32Ty, f32Ty},213                                      ValueRange{*cstI32});214  verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, noAttrs);215 216  // Test collective params build method, with attributes.217  op = test::TableGenBuildOp3::create(builder, loc, TypeRange{i32Ty, f32Ty},218                                      ValueRange{*cstI32}, attrs);219  verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, attrs);220}221 222// The next test checks suppression of ambiguous build methods for ops that223// have a single variadic input, and single non-variadic result, and which224// support the SameOperandsAndResultType trait and optionally the225// InferOpTypeInterface interface. For such ops, the ODS framework generates226// build methods with no result types as they are inferred from the input types.227TEST_F(OpBuildGenTest, BuildMethodsSameOperandsAndResultTypeSuppression) {228  // Test separate arg, separate param build method.229  auto op = test::TableGenBuildOp4::create(builder, loc, i32Ty,230                                           ValueRange{*cstI32, *cstI32});231  verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);232 233  // Test collective params build method.234  op = test::TableGenBuildOp4::create(builder, loc, TypeRange{i32Ty},235                                      ValueRange{*cstI32, *cstI32});236  verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);237 238  // Test build method with no result types, default value of attributes.239  op = test::TableGenBuildOp4::create(builder, loc,240                                      ValueRange{*cstI32, *cstI32});241  verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);242 243  // Test build method with no result types and supplied attributes.244  op = test::TableGenBuildOp4::create(builder, loc,245                                      ValueRange{*cstI32, *cstI32}, attrs);246  verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, attrs);247}248 249TEST_F(OpBuildGenTest, BuildMethodsRegionsAndInferredType) {250  auto op = test::TableGenBuildOp5::create(251      builder, loc, ValueRange{*cstI32, *cstF32}, /*attributes=*/noAttrs);252  ASSERT_EQ(op->getNumRegions(), 1u);253  verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, noAttrs);254}255 256TEST_F(OpBuildGenTest, BuildMethodsVariadicProperties) {257  // Account for conversion as part of getAttrs().258  std::vector<NamedAttribute> noAttrsStorage;259  auto segmentSize = builder.getNamedAttr("operandSegmentSizes",260                                          builder.getDenseI32ArrayAttr({1, 1}));261  noAttrsStorage.push_back(segmentSize);262  ArrayRef<NamedAttribute> noAttrs(noAttrsStorage);263  std::vector<NamedAttribute> attrsStorage = this->attrStorage;264  attrsStorage.push_back(segmentSize);265  ArrayRef<NamedAttribute> attrs(attrsStorage);266 267  // Test separate arg, separate param build method.268  auto op = test::TableGenBuildOp6::create(269      builder, loc, f32Ty, ValueRange{*cstI32}, ValueRange{*cstI32});270  verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs);271 272  // Test build method with no result types, default value of attributes.273  op = test::TableGenBuildOp6::create(builder, loc, ValueRange{*cstI32},274                                      ValueRange{*cstI32});275  verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs);276 277  // Test collective params build method.278  op = test::TableGenBuildOp6::create(builder, loc, TypeRange{f32Ty},279                                      ValueRange{*cstI32}, ValueRange{*cstI32});280  verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs);281 282  // Test build method with result types, supplied attributes.283  op = test::TableGenBuildOp6::create(builder, loc, TypeRange{f32Ty},284                                      ValueRange{*cstI32, *cstI32}, attrs);285  verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, attrs);286 287  // Test build method with no result types and supplied attributes.288  op = test::TableGenBuildOp6::create(builder, loc,289                                      ValueRange{*cstI32, *cstI32}, attrs);290  verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, attrs);291}292 293TEST_F(OpBuildGenTest, BuildMethodsInherentDiscardableAttrs) {294  test::TableGenBuildOp7::Properties props;295  props.attr0 = cast<BoolAttr>(attrs[0].getValue());296  ArrayRef<NamedAttribute> discardableAttrs = attrs.drop_front();297  auto op7 = test::TableGenBuildOp7::create(298      builder, loc, TypeRange{}, ValueRange{}, props, discardableAttrs);299  verifyOp(op7, {}, {}, attrs);300 301  // Check that the old-style builder where all the attributes go in the same302  // place works.303  auto op7b = test::TableGenBuildOp7::create(builder, loc, TypeRange{},304                                             ValueRange{}, attrs);305  // Note: this goes before verifyOp() because verifyOp() calls erase(), causing306  // use-after-free.307  ASSERT_EQ(op7b.getProperties().getAttr0(), attrs[0].getValue());308  verifyOp(op7b, {}, {}, attrs);309}310 311} // namespace mlir312