Bump version to 19.1.0 (final)
[llvm-project.git] / mlir / unittests / TableGen / OpBuildGen.cpp
blob94fbfa28803c4862bfa5fcb31c0cf29721e3b769
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.
11 //===----------------------------------------------------------------------===//
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>
22 namespace mlir {
24 //===----------------------------------------------------------------------===//
25 // Test Fixture
26 //===----------------------------------------------------------------------===//
28 static MLIRContext &getContext() {
29 static MLIRContext ctx;
30 ctx.getOrLoadDialect<test::TestDialect>();
31 return ctx;
33 /// Test fixture for providing basic utilities for testing.
34 class OpBuildGenTest : public ::testing::Test {
35 protected:
36 OpBuildGenTest()
37 : ctx(getContext()), builder(&ctx), loc(builder.getUnknownLoc()),
38 i32Ty(builder.getI32Type()), f32Ty(builder.getF32Type()),
39 cstI32(builder.create<test::TableGenConstant>(loc, i32Ty)),
40 cstF32(builder.create<test::TableGenConstant>(loc, f32Ty)),
41 noAttrs(), attrStorage{builder.getNamedAttr("attr0",
42 builder.getBoolAttr(true)),
43 builder.getNamedAttr(
44 "attr1", builder.getI32IntegerAttr(33))},
45 attrs(attrStorage) {}
47 // Verify that `op` has the given set of result types, operands, and
48 // attributes.
49 template <typename OpTy>
50 void verifyOp(OpTy &&concreteOp, std::vector<Type> resultTypes,
51 std::vector<Value> operands,
52 std::vector<NamedAttribute> attrs) {
53 ASSERT_NE(concreteOp, nullptr);
54 Operation *op = concreteOp.getOperation();
56 EXPECT_EQ(op->getNumResults(), resultTypes.size());
57 for (unsigned idx : llvm::seq(0U, op->getNumResults()))
58 EXPECT_EQ(op->getResult(idx).getType(), resultTypes[idx]);
60 EXPECT_EQ(op->getNumOperands(), operands.size());
61 for (unsigned idx : llvm::seq(0U, op->getNumOperands()))
62 EXPECT_EQ(op->getOperand(idx), operands[idx]);
64 EXPECT_EQ(op->getAttrs().size(), attrs.size());
65 for (unsigned idx : llvm::seq<unsigned>(0U, attrs.size()))
66 EXPECT_EQ(op->getAttr(attrs[idx].getName().strref()),
67 attrs[idx].getValue());
69 EXPECT_TRUE(mlir::succeeded(concreteOp.verify()));
70 concreteOp.erase();
73 template <typename OpTy>
74 void verifyOp(OpTy &&concreteOp, std::vector<Type> resultTypes,
75 std::vector<Value> operands1, std::vector<Value> operands2,
76 std::vector<NamedAttribute> attrs) {
77 ASSERT_NE(concreteOp, nullptr);
78 Operation *op = concreteOp.getOperation();
80 EXPECT_EQ(op->getNumResults(), resultTypes.size());
81 for (unsigned idx : llvm::seq(0U, op->getNumResults()))
82 EXPECT_EQ(op->getResult(idx).getType(), resultTypes[idx]);
84 auto operands = llvm::to_vector(llvm::concat<Value>(operands1, operands2));
85 EXPECT_EQ(op->getNumOperands(), operands.size());
86 for (unsigned idx : llvm::seq(0U, op->getNumOperands()))
87 EXPECT_EQ(op->getOperand(idx), operands[idx]);
89 EXPECT_EQ(op->getAttrs().size(), attrs.size());
90 if (op->getAttrs().size() != attrs.size()) {
91 // Simple export where there is mismatch count.
92 llvm::errs() << "Op attrs:\n";
93 for (auto it : op->getAttrs())
94 llvm::errs() << "\t" << it.getName() << " = " << it.getValue() << "\n";
96 llvm::errs() << "Expected attrs:\n";
97 for (auto it : attrs)
98 llvm::errs() << "\t" << it.getName() << " = " << it.getValue() << "\n";
99 } else {
100 for (unsigned idx : llvm::seq<unsigned>(0U, attrs.size()))
101 EXPECT_EQ(op->getAttr(attrs[idx].getName().strref()),
102 attrs[idx].getValue());
105 EXPECT_TRUE(mlir::succeeded(concreteOp.verify()));
106 concreteOp.erase();
109 protected:
110 MLIRContext &ctx;
111 OpBuilder builder;
112 Location loc;
113 Type i32Ty;
114 Type f32Ty;
115 OwningOpRef<test::TableGenConstant> cstI32;
116 OwningOpRef<test::TableGenConstant> cstF32;
118 ArrayRef<NamedAttribute> noAttrs;
119 std::vector<NamedAttribute> attrStorage;
120 ArrayRef<NamedAttribute> attrs;
123 /// Test basic build methods.
124 TEST_F(OpBuildGenTest, BasicBuildMethods) {
125 // Test separate args, separate results build method.
126 auto op = builder.create<test::TableGenBuildOp0>(loc, i32Ty, *cstI32);
127 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
129 // Test separate args, collective results build method.
130 op = builder.create<test::TableGenBuildOp0>(loc, TypeRange{i32Ty}, *cstI32);
131 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
133 // Test collective args, collective params build method.
134 op = builder.create<test::TableGenBuildOp0>(loc, TypeRange{i32Ty},
135 ValueRange{*cstI32});
136 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
138 // Test collective args, collective results, non-empty attributes
139 op = builder.create<test::TableGenBuildOp0>(loc, TypeRange{i32Ty},
140 ValueRange{*cstI32}, attrs);
141 verifyOp(op, {i32Ty}, {*cstI32}, attrs);
144 /// The following 3 tests exercise build methods generated for operations
145 /// with a combination of:
147 /// single variadic arg x
148 /// {single variadic result, non-variadic result, multiple variadic results}
150 /// Specifically to test that ODS framework does not generate ambiguous
151 /// build() methods that fail to compile.
153 /// Test build methods for an Op with a single varadic arg and a single
154 /// variadic result.
155 TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgAndResult) {
156 // Test collective args, collective results method, building a unary op.
157 auto op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
158 ValueRange{*cstI32});
159 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
161 // Test collective args, collective results method, building a unary op with
162 // named attributes.
163 op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
164 ValueRange{*cstI32}, attrs);
165 verifyOp(op, {i32Ty}, {*cstI32}, attrs);
167 // Test collective args, collective results method, building a binary op.
168 op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty, f32Ty},
169 ValueRange{*cstI32, *cstF32});
170 verifyOp(op, {i32Ty, f32Ty}, {*cstI32, *cstF32}, noAttrs);
172 // Test collective args, collective results method, building a binary op with
173 // named attributes.
174 op = builder.create<test::TableGenBuildOp1>(
175 loc, TypeRange{i32Ty, f32Ty}, ValueRange{*cstI32, *cstF32}, attrs);
176 verifyOp(op, {i32Ty, f32Ty}, {*cstI32, *cstF32}, attrs);
179 /// Test build methods for an Op with a single varadic arg and a non-variadic
180 /// result.
181 TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgNonVariadicResults) {
182 // Test separate arg, separate param build method.
183 auto op =
184 builder.create<test::TableGenBuildOp1>(loc, i32Ty, ValueRange{*cstI32});
185 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
187 // Test collective params build method, no attributes.
188 op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
189 ValueRange{*cstI32});
190 verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
192 // Test collective params build method no attributes, 2 inputs.
193 op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
194 ValueRange{*cstI32, *cstF32});
195 verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, noAttrs);
197 // Test collective params build method, non-empty attributes.
198 op = builder.create<test::TableGenBuildOp1>(
199 loc, TypeRange{i32Ty}, ValueRange{*cstI32, *cstF32}, attrs);
200 verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, attrs);
203 /// Test build methods for an Op with a single varadic arg and multiple variadic
204 /// result.
205 TEST_F(OpBuildGenTest,
206 BuildMethodsSingleVariadicArgAndMultipleVariadicResults) {
207 // Test separate arg, separate param build method.
208 auto op = builder.create<test::TableGenBuildOp3>(
209 loc, TypeRange{i32Ty}, TypeRange{f32Ty}, ValueRange{*cstI32});
210 verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, noAttrs);
212 // Test collective params build method, no attributes.
213 op = builder.create<test::TableGenBuildOp3>(loc, TypeRange{i32Ty, f32Ty},
214 ValueRange{*cstI32});
215 verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, noAttrs);
217 // Test collective params build method, with attributes.
218 op = builder.create<test::TableGenBuildOp3>(loc, TypeRange{i32Ty, f32Ty},
219 ValueRange{*cstI32}, attrs);
220 verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, attrs);
223 // The next test checks suppression of ambiguous build methods for ops that
224 // have a single variadic input, and single non-variadic result, and which
225 // support the SameOperandsAndResultType trait and optionally the
226 // InferOpTypeInterface interface. For such ops, the ODS framework generates
227 // build methods with no result types as they are inferred from the input types.
228 TEST_F(OpBuildGenTest, BuildMethodsSameOperandsAndResultTypeSuppression) {
229 // Test separate arg, separate param build method.
230 auto op = builder.create<test::TableGenBuildOp4>(
231 loc, i32Ty, ValueRange{*cstI32, *cstI32});
232 verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);
234 // Test collective params build method.
235 op = builder.create<test::TableGenBuildOp4>(loc, TypeRange{i32Ty},
236 ValueRange{*cstI32, *cstI32});
237 verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);
239 // Test build method with no result types, default value of attributes.
240 op =
241 builder.create<test::TableGenBuildOp4>(loc, ValueRange{*cstI32, *cstI32});
242 verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);
244 // Test build method with no result types and supplied attributes.
245 op = builder.create<test::TableGenBuildOp4>(loc, ValueRange{*cstI32, *cstI32},
246 attrs);
247 verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, attrs);
250 TEST_F(OpBuildGenTest, BuildMethodsRegionsAndInferredType) {
251 auto op = builder.create<test::TableGenBuildOp5>(
252 loc, ValueRange{*cstI32, *cstF32}, /*attributes=*/noAttrs);
253 ASSERT_EQ(op->getNumRegions(), 1u);
254 verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, noAttrs);
257 TEST_F(OpBuildGenTest, BuildMethodsVariadicProperties) {
258 // Account for conversion as part of getAttrs().
259 std::vector<NamedAttribute> noAttrsStorage;
260 auto segmentSize = builder.getNamedAttr("operandSegmentSizes",
261 builder.getDenseI32ArrayAttr({1, 1}));
262 noAttrsStorage.push_back(segmentSize);
263 ArrayRef<NamedAttribute> noAttrs(noAttrsStorage);
264 std::vector<NamedAttribute> attrsStorage = this->attrStorage;
265 attrsStorage.push_back(segmentSize);
266 ArrayRef<NamedAttribute> attrs(attrsStorage);
268 // Test separate arg, separate param build method.
269 auto op = builder.create<test::TableGenBuildOp6>(
270 loc, f32Ty, ValueRange{*cstI32}, ValueRange{*cstI32});
271 verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs);
273 // Test build method with no result types, default value of attributes.
274 op = builder.create<test::TableGenBuildOp6>(loc, ValueRange{*cstI32},
275 ValueRange{*cstI32});
276 verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs);
278 // Test collective params build method.
279 op = builder.create<test::TableGenBuildOp6>(
280 loc, TypeRange{f32Ty}, ValueRange{*cstI32}, ValueRange{*cstI32});
281 verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs);
283 // Test build method with result types, supplied attributes.
284 op = builder.create<test::TableGenBuildOp6>(
285 loc, TypeRange{f32Ty}, ValueRange{*cstI32, *cstI32}, attrs);
286 verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, attrs);
288 // Test build method with no result types and supplied attributes.
289 op = builder.create<test::TableGenBuildOp6>(loc, ValueRange{*cstI32, *cstI32},
290 attrs);
291 verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, attrs);
294 } // namespace mlir