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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Test TableGen generated build() methods on Operations.
10//
11//===----------------------------------------------------------------------===//
12
13#include "TestDialect.h"
14#include "mlir/IR/Attributes.h"
15#include "mlir/IR/Builders.h"
16#include "mlir/IR/BuiltinTypes.h"
17#include "mlir/IR/Dialect.h"
18#include "gmock/gmock.h"
19#include <vector>
20
21namespace mlir {
22
23//===----------------------------------------------------------------------===//
24// Test Fixture
25//===----------------------------------------------------------------------===//
26
27static MLIRContext &getContext() {
28 static MLIRContext ctx;
29 ctx.getOrLoadDialect<test::TestDialect>();
30 return ctx;
31}
32/// Test fixture for providing basic utilities for testing.
33class OpBuildGenTest : public ::testing::Test {
34protected:
35 OpBuildGenTest()
36 : ctx(getContext()), builder(&ctx), loc(builder.getUnknownLoc()),
37 i32Ty(builder.getI32Type()), f32Ty(builder.getF32Type()),
38 cstI32(builder.create<test::TableGenConstant>(loc, i32Ty)),
39 cstF32(builder.create<test::TableGenConstant>(loc, f32Ty)),
40 noAttrs(), attrStorage{builder.getNamedAttr(name: "attr0",
41 val: builder.getBoolAttr(value: true)),
42 builder.getNamedAttr(
43 "attr1", builder.getI32IntegerAttr(33))},
44 attrs(attrStorage) {}
45
46 // Verify that `op` has the given set of result types, operands, and
47 // 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(Begin: 0U, End: 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(Begin: 0U, End: 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>(Begin: 0U, End: attrs.size()))
65 EXPECT_EQ(op->getAttr(attrs[idx].getName().strref()),
66 attrs[idx].getValue());
67
68 concreteOp.erase();
69 }
70
71 // Helper method to test ops with inferred result types and single variadic
72 // input.
73 template <typename OpTy>
74 void testSingleVariadicInputInferredType() {
75 // Test separate arg, separate param build method.
76 auto op = builder.create<OpTy>(loc, i32Ty, ValueRange{*cstI32, *cstI32});
77 verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);
78
79 // Test collective params build method.
80 op = builder.create<OpTy>(loc, TypeRange{i32Ty},
81 ValueRange{*cstI32, *cstI32});
82 verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);
83
84 // Test build method with no result types, default value of attributes.
85 op = builder.create<OpTy>(loc, ValueRange{*cstI32, *cstI32});
86 verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);
87
88 // Test build method with no result types and supplied attributes.
89 op = builder.create<OpTy>(loc, ValueRange{*cstI32, *cstI32}, attrs);
90 verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, attrs);
91 }
92
93protected:
94 MLIRContext &ctx;
95 OpBuilder builder;
96 Location loc;
97 Type i32Ty;
98 Type f32Ty;
99 OwningOpRef<test::TableGenConstant> cstI32;
100 OwningOpRef<test::TableGenConstant> cstF32;
101
102 ArrayRef<NamedAttribute> noAttrs;
103 std::vector<NamedAttribute> attrStorage;
104 ArrayRef<NamedAttribute> attrs;
105};
106
107/// Test basic build methods.
108TEST_F(OpBuildGenTest, BasicBuildMethods) {
109 // Test separate args, separate results build method.
110 auto op = builder.create<test::TableGenBuildOp0>(loc, i32Ty, *cstI32);
111 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
112
113 // Test separate args, collective results build method.
114 op = builder.create<test::TableGenBuildOp0>(loc, TypeRange{i32Ty}, *cstI32);
115 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
116
117 // Test collective args, collective params build method.
118 op = builder.create<test::TableGenBuildOp0>(loc, TypeRange{i32Ty},
119 ValueRange{*cstI32});
120 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
121
122 // Test collective args, collective results, non-empty attributes
123 op = builder.create<test::TableGenBuildOp0>(loc, TypeRange{i32Ty},
124 ValueRange{*cstI32}, attrs);
125 verifyOp(op, {i32Ty}, {*cstI32}, attrs);
126}
127
128/// The following 3 tests exercise build methods generated for operations
129/// with a combination of:
130///
131/// single variadic arg x
132/// {single variadic result, non-variadic result, multiple variadic results}
133///
134/// Specifically to test that ODS framework does not generate ambiguous
135/// build() methods that fail to compile.
136
137/// Test build methods for an Op with a single varadic arg and a single
138/// variadic result.
139TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgAndResult) {
140 // Test collective args, collective results method, building a unary op.
141 auto op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
142 ValueRange{*cstI32});
143 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
144
145 // Test collective args, collective results method, building a unary op with
146 // named attributes.
147 op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
148 ValueRange{*cstI32}, attrs);
149 verifyOp(op, {i32Ty}, {*cstI32}, attrs);
150
151 // Test collective args, collective results method, building a binary op.
152 op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty, f32Ty},
153 ValueRange{*cstI32, *cstF32});
154 verifyOp(op, {i32Ty, f32Ty}, {*cstI32, *cstF32}, noAttrs);
155
156 // Test collective args, collective results method, building a binary op with
157 // named attributes.
158 op = builder.create<test::TableGenBuildOp1>(
159 loc, TypeRange{i32Ty, f32Ty}, ValueRange{*cstI32, *cstF32}, attrs);
160 verifyOp(op, {i32Ty, f32Ty}, {*cstI32, *cstF32}, attrs);
161}
162
163/// Test build methods for an Op with a single varadic arg and a non-variadic
164/// result.
165TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgNonVariadicResults) {
166 // Test separate arg, separate param build method.
167 auto op =
168 builder.create<test::TableGenBuildOp1>(loc, i32Ty, ValueRange{*cstI32});
169 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
170
171 // Test collective params build method, no attributes.
172 op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
173 ValueRange{*cstI32});
174 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
175
176 // Test collective params build method no attributes, 2 inputs.
177 op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
178 ValueRange{*cstI32, *cstF32});
179 verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, noAttrs);
180
181 // Test collective params build method, non-empty attributes.
182 op = builder.create<test::TableGenBuildOp1>(
183 loc, TypeRange{i32Ty}, ValueRange{*cstI32, *cstF32}, attrs);
184 verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, attrs);
185}
186
187/// Test build methods for an Op with a single varadic arg and multiple variadic
188/// result.
189TEST_F(OpBuildGenTest,
190 BuildMethodsSingleVariadicArgAndMultipleVariadicResults) {
191 // Test separate arg, separate param build method.
192 auto op = builder.create<test::TableGenBuildOp3>(
193 loc, TypeRange{i32Ty}, TypeRange{f32Ty}, ValueRange{*cstI32});
194 verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, noAttrs);
195
196 // Test collective params build method, no attributes.
197 op = builder.create<test::TableGenBuildOp3>(loc, TypeRange{i32Ty, f32Ty},
198 ValueRange{*cstI32});
199 verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, noAttrs);
200
201 // Test collective params build method, with attributes.
202 op = builder.create<test::TableGenBuildOp3>(loc, TypeRange{i32Ty, f32Ty},
203 ValueRange{*cstI32}, attrs);
204 verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, attrs);
205}
206
207// The next test checks supression of ambiguous build methods for ops that
208// have a single variadic input, and single non-variadic result, and which
209// support the SameOperandsAndResultType trait and and optionally the
210// InferOpTypeInterface interface. For such ops, the ODS framework generates
211// build methods with no result types as they are inferred from the input types.
212TEST_F(OpBuildGenTest, BuildMethodsSameOperandsAndResultTypeSuppression) {
213 testSingleVariadicInputInferredType<test::TableGenBuildOp4>();
214}
215
216TEST_F(OpBuildGenTest, BuildMethodsRegionsAndInferredType) {
217 auto op = builder.create<test::TableGenBuildOp5>(
218 loc, ValueRange{*cstI32, *cstF32}, /*attributes=*/noAttrs);
219 ASSERT_EQ(op->getNumRegions(), 1u);
220 verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, noAttrs);
221}
222
223} // namespace mlir
224

source code of mlir/unittests/TableGen/OpBuildGen.cpp