From 0b161def6cacff1a63d3cf1a1efe95b550814d7a Mon Sep 17 00:00:00 2001 From: Rahul Joshi Date: Tue, 28 Jul 2020 10:29:43 -0700 Subject: [PATCH] [MLIR] Add unit test for tblgen Op build methods - Initiate the unit test with a test that tests variants of build() methods generated for ops with variadic operands and results. - The intent is to migrate unit .td tests in mlir/test/mlir-tblgen that check for generated C++ code to these unit tests which test both that the generated code compiles and also is functionally correct. Differential Revision: https://reviews.llvm.org/D84074 --- mlir/test/lib/Dialect/Test/TestOps.td | 32 ++++++ mlir/unittests/TableGen/CMakeLists.txt | 9 +- mlir/unittests/TableGen/OpBuildGen.cpp | 181 +++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 mlir/unittests/TableGen/OpBuildGen.cpp diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index 528d219..af20034 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -1473,4 +1473,36 @@ def RegionIfOp : TEST_Op<"region_if", }]; } +//===----------------------------------------------------------------------===// +// Test TableGen generated build() methods +//===----------------------------------------------------------------------===// + +def TableGenConstant : TEST_Op<"tblgen_constant"> { + let results = (outs AnyType); +} + +// No variadic args or results. +def TableGenBuildOp0 : TEST_Op<"tblgen_build_0"> { + let arguments = (ins AnyType:$value); + let results = (outs AnyType:$result); +} + +// Sigle variadic arg and single variadic results. +def TableGenBuildOp1 : TEST_Op<"tblgen_build_1"> { + let arguments = (ins Variadic:$inputs); + let results = (outs Variadic:$results); +} + +// Single variadic arg and non-variadic results. +def TableGenBuildOp2 : TEST_Op<"tblgen_build_2"> { + let arguments = (ins Variadic:$inputs); + let results = (outs AnyType:$result); +} + +// Single variadic arg and multiple variadic results. +def TableGenBuildOp3 : TEST_Op<"tblgen_build_3", [SameVariadicResultSize]> { + let arguments = (ins Variadic:$inputs); + let results = (outs Variadic:$resultA, Variadic:$resultB); +} + #endif // TEST_OPS diff --git a/mlir/unittests/TableGen/CMakeLists.txt b/mlir/unittests/TableGen/CMakeLists.txt index cb4dea6..7cee691 100644 --- a/mlir/unittests/TableGen/CMakeLists.txt +++ b/mlir/unittests/TableGen/CMakeLists.txt @@ -12,10 +12,17 @@ add_mlir_unittest(MLIRTableGenTests EnumsGenTest.cpp StructsGenTest.cpp FormatTest.cpp + OpBuildGen.cpp ) add_dependencies(MLIRTableGenTests MLIRTableGenEnumsIncGen) add_dependencies(MLIRTableGenTests MLIRTableGenStructAttrIncGen) +add_dependencies(MLIRTableGenTests MLIRTestDialect) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../test/lib/Dialect/Test) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../test/lib/Dialect/Test) target_link_libraries(MLIRTableGenTests - PRIVATE MLIRTableGen MLIRIR) + PRIVATE MLIRTableGen MLIRIR + PUBLIC MLIRTestDialect +) diff --git a/mlir/unittests/TableGen/OpBuildGen.cpp b/mlir/unittests/TableGen/OpBuildGen.cpp new file mode 100644 index 0000000..e90f96b --- /dev/null +++ b/mlir/unittests/TableGen/OpBuildGen.cpp @@ -0,0 +1,181 @@ +//===- OpBuildGen.cpp - TableGen OpBuildGen Tests -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Test TableGen generated build() methods on Operations. +// +//===----------------------------------------------------------------------===// + +#include "TestDialect.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/Dialect.h" +#include "mlir/IR/Identifier.h" +#include "mlir/IR/StandardTypes.h" +#include "gmock/gmock.h" +#include + +namespace mlir { + +//===----------------------------------------------------------------------===// +// Test Fixture +//===----------------------------------------------------------------------===// + +/// Test fixture for providing basic utilities for testing. +class OpBuildGenTest : public ::testing::Test { +protected: + OpBuildGenTest() + : ctx{}, builder(&ctx), loc(builder.getUnknownLoc()), + i32Ty(builder.getI32Type()), f32Ty(builder.getF32Type()), + cstI32(builder.create(loc, i32Ty)), + cstF32(builder.create(loc, f32Ty)), + noAttrs(), attrStorage{builder.getNamedAttr("attr0", + builder.getBoolAttr(true)), + builder.getNamedAttr( + "attr1", builder.getI32IntegerAttr(33))}, + attrs(attrStorage) {} + + // Verify that `op` has the given set of result types, operands, and + // attributes. + template + void verifyOp(OpTy &&concreteOp, std::vector resultTypes, + std::vector operands, + std::vector attrs) { + ASSERT_NE(concreteOp, nullptr); + Operation *op = concreteOp.getOperation(); + + EXPECT_EQ(op->getNumResults(), resultTypes.size()); + for (unsigned idx : llvm::seq(0U, op->getNumResults())) + EXPECT_EQ(op->getResult(idx).getType(), resultTypes[idx]); + + EXPECT_EQ(op->getNumOperands(), operands.size()); + for (unsigned idx : llvm::seq(0U, op->getNumOperands())) + EXPECT_EQ(op->getOperand(idx), operands[idx]); + + EXPECT_EQ(op->getAttrs().size(), attrs.size()); + for (unsigned idx : llvm::seq(0U, attrs.size())) + EXPECT_EQ(op->getAttr(attrs[idx].first.strref()), attrs[idx].second); + + concreteOp.erase(); + } + +protected: + MLIRContext ctx; + OpBuilder builder; + Location loc; + Type i32Ty; + Type f32Ty; + TableGenConstant cstI32; + TableGenConstant cstF32; + + ArrayRef noAttrs; + std::vector attrStorage; + ArrayRef attrs; +}; + +/// Test basic build methods. +TEST_F(OpBuildGenTest, BasicBuildMethods) { + // Test separate args, separate results build method. + auto op = builder.create(loc, i32Ty, cstI32); + verifyOp(op, {i32Ty}, {cstI32}, noAttrs); + + // Test separate args, collective results build method. + op = builder.create(loc, ArrayRef{i32Ty}, cstI32); + verifyOp(op, {i32Ty}, {cstI32}, noAttrs); + + // Test collective args, collective params build method. + op = builder.create(loc, ArrayRef{i32Ty}, + ArrayRef{cstI32}); + verifyOp(op, {i32Ty}, {cstI32}, noAttrs); + + // Test collective args, collective results, non-empty attributes + op = builder.create(loc, ArrayRef{i32Ty}, + ArrayRef{cstI32}, attrs); + verifyOp(op, {i32Ty}, {cstI32}, attrs); +} + +/// The following 3 tests exercise build methods generated for operations +/// with a combination of: +/// +/// single variadic arg x +/// {single variadic result, non-variadic result, multiple variadic results} +/// +/// Specifically to test that that ODS framework does not generate ambiguous +/// build() methods that fail to compile. + +/// Test build methods for an Op with a single varadic arg and a single +/// variadic result. +TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgAndResult) { + // Test collective args, collective results method, building a unary op. + auto op = builder.create(loc, ArrayRef{i32Ty}, + ArrayRef{cstI32}); + verifyOp(std::move(op), {i32Ty}, {cstI32}, noAttrs); + + // Test collective args, collective results method, building a unary op with + // named attributes. + op = builder.create(loc, ArrayRef{i32Ty}, + ArrayRef{cstI32}, attrs); + verifyOp(std::move(op), {i32Ty}, {cstI32}, attrs); + + // Test collective args, collective results method, building a binary op. + op = builder.create(loc, ArrayRef{i32Ty, f32Ty}, + ArrayRef{cstI32, cstF32}); + verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32, cstF32}, noAttrs); + + // Test collective args, collective results method, building a binary op with + // named attributes. + op = builder.create(loc, ArrayRef{i32Ty, f32Ty}, + ArrayRef{cstI32, cstF32}, attrs); + verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32, cstF32}, attrs); +} + +/// Test build methods for an Op with a single varadic arg and a non-variadic +/// result. +TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgNonVariadicResults) { + // Test separate arg, separate param build method. + auto op = + builder.create(loc, i32Ty, ArrayRef{cstI32}); + verifyOp(std::move(op), {i32Ty}, {cstI32}, noAttrs); + + // Test collective params build method, no attributes. + op = builder.create(loc, ArrayRef{i32Ty}, + ArrayRef{cstI32}); + verifyOp(std::move(op), {i32Ty}, {cstI32}, noAttrs); + + // Test collective params build method no attributes, 2 inputs. + op = builder.create(loc, ArrayRef{i32Ty}, + ArrayRef{cstI32, cstF32}); + verifyOp(std::move(op), {i32Ty}, {cstI32, cstF32}, noAttrs); + + // Test collective params build method, non-empty attributes. + op = builder.create(loc, ArrayRef{i32Ty}, + ArrayRef{cstI32, cstF32}, attrs); + verifyOp(std::move(op), {i32Ty}, {cstI32, cstF32}, attrs); +} + +/// Test build methods for an Op with a single varadic arg and multiple variadic +/// result. +TEST_F(OpBuildGenTest, + BuildMethodsSingleVariadicArgAndMultipleVariadicResults) { + // Test separate arg, separate param build method. + auto op = builder.create(loc, ArrayRef{i32Ty}, + ArrayRef{f32Ty}, + ArrayRef{cstI32}); + verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32}, noAttrs); + + // Test collective params build method, no attributes. + op = builder.create(loc, ArrayRef{i32Ty, f32Ty}, + ArrayRef{cstI32}); + verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32}, noAttrs); + + // Test collective params build method, with attributes. + op = builder.create(loc, ArrayRef{i32Ty, f32Ty}, + ArrayRef{cstI32}, attrs); + verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32}, attrs); +} + +} // namespace mlir -- 2.7.4