10b161defSRahul Joshi //===- OpBuildGen.cpp - TableGen OpBuildGen Tests -------------------------===//
20b161defSRahul Joshi //
30b161defSRahul Joshi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b161defSRahul Joshi // See https://llvm.org/LICENSE.txt for license information.
50b161defSRahul Joshi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b161defSRahul Joshi //
70b161defSRahul Joshi //===----------------------------------------------------------------------===//
80b161defSRahul Joshi //
90b161defSRahul Joshi // Test TableGen generated build() methods on Operations.
100b161defSRahul Joshi //
110b161defSRahul Joshi //===----------------------------------------------------------------------===//
120b161defSRahul Joshi
130b161defSRahul Joshi #include "TestDialect.h"
14e95e94adSJeff Niu #include "TestOps.h"
150b161defSRahul Joshi #include "mlir/IR/Attributes.h"
160b161defSRahul Joshi #include "mlir/IR/Builders.h"
1709f7a55fSRiver Riddle #include "mlir/IR/BuiltinTypes.h"
180b161defSRahul Joshi #include "mlir/IR/Dialect.h"
190b161defSRahul Joshi #include "gmock/gmock.h"
200b161defSRahul Joshi #include <vector>
210b161defSRahul Joshi
220b161defSRahul Joshi namespace mlir {
230b161defSRahul Joshi
240b161defSRahul Joshi //===----------------------------------------------------------------------===//
250b161defSRahul Joshi // Test Fixture
260b161defSRahul Joshi //===----------------------------------------------------------------------===//
270b161defSRahul Joshi
getContext()28f9dc2b70SMehdi Amini static MLIRContext &getContext() {
29e7021232SMehdi Amini static MLIRContext ctx;
30d413f4bcSAlexander Belyaev ctx.getOrLoadDialect<test::TestDialect>();
31f9dc2b70SMehdi Amini return ctx;
32f9dc2b70SMehdi Amini }
330b161defSRahul Joshi /// Test fixture for providing basic utilities for testing.
340b161defSRahul Joshi class OpBuildGenTest : public ::testing::Test {
350b161defSRahul Joshi protected:
OpBuildGenTest()360b161defSRahul Joshi OpBuildGenTest()
37f9dc2b70SMehdi Amini : ctx(getContext()), builder(&ctx), loc(builder.getUnknownLoc()),
380b161defSRahul Joshi i32Ty(builder.getI32Type()), f32Ty(builder.getF32Type()),
39d413f4bcSAlexander Belyaev cstI32(builder.create<test::TableGenConstant>(loc, i32Ty)),
40d413f4bcSAlexander Belyaev cstF32(builder.create<test::TableGenConstant>(loc, f32Ty)),
410b161defSRahul Joshi noAttrs(), attrStorage{builder.getNamedAttr("attr0",
420b161defSRahul Joshi builder.getBoolAttr(true)),
430b161defSRahul Joshi builder.getNamedAttr(
440b161defSRahul Joshi "attr1", builder.getI32IntegerAttr(33))},
450b161defSRahul Joshi attrs(attrStorage) {}
460b161defSRahul Joshi
470b161defSRahul Joshi // Verify that `op` has the given set of result types, operands, and
480b161defSRahul Joshi // attributes.
490b161defSRahul Joshi template <typename OpTy>
verifyOp(OpTy && concreteOp,std::vector<Type> resultTypes,std::vector<Value> operands,std::vector<NamedAttribute> attrs)500b161defSRahul Joshi void verifyOp(OpTy &&concreteOp, std::vector<Type> resultTypes,
510b161defSRahul Joshi std::vector<Value> operands,
520b161defSRahul Joshi std::vector<NamedAttribute> attrs) {
530b161defSRahul Joshi ASSERT_NE(concreteOp, nullptr);
540b161defSRahul Joshi Operation *op = concreteOp.getOperation();
550b161defSRahul Joshi
560b161defSRahul Joshi EXPECT_EQ(op->getNumResults(), resultTypes.size());
570b161defSRahul Joshi for (unsigned idx : llvm::seq(0U, op->getNumResults()))
580b161defSRahul Joshi EXPECT_EQ(op->getResult(idx).getType(), resultTypes[idx]);
590b161defSRahul Joshi
600b161defSRahul Joshi EXPECT_EQ(op->getNumOperands(), operands.size());
610b161defSRahul Joshi for (unsigned idx : llvm::seq(0U, op->getNumOperands()))
620b161defSRahul Joshi EXPECT_EQ(op->getOperand(idx), operands[idx]);
630b161defSRahul Joshi
640b161defSRahul Joshi EXPECT_EQ(op->getAttrs().size(), attrs.size());
650b161defSRahul Joshi for (unsigned idx : llvm::seq<unsigned>(0U, attrs.size()))
660c7890c8SRiver Riddle EXPECT_EQ(op->getAttr(attrs[idx].getName().strref()),
670c7890c8SRiver Riddle attrs[idx].getValue());
680b161defSRahul Joshi
69*e67080dfSJacques Pienaar EXPECT_TRUE(mlir::succeeded(concreteOp.verify()));
700b161defSRahul Joshi concreteOp.erase();
710b161defSRahul Joshi }
720b161defSRahul Joshi
7313d05787SRahul Joshi template <typename OpTy>
verifyOp(OpTy && concreteOp,std::vector<Type> resultTypes,std::vector<Value> operands1,std::vector<Value> operands2,std::vector<NamedAttribute> attrs)74*e67080dfSJacques Pienaar void verifyOp(OpTy &&concreteOp, std::vector<Type> resultTypes,
75*e67080dfSJacques Pienaar std::vector<Value> operands1, std::vector<Value> operands2,
76*e67080dfSJacques Pienaar std::vector<NamedAttribute> attrs) {
77*e67080dfSJacques Pienaar ASSERT_NE(concreteOp, nullptr);
78*e67080dfSJacques Pienaar Operation *op = concreteOp.getOperation();
7913d05787SRahul Joshi
80*e67080dfSJacques Pienaar EXPECT_EQ(op->getNumResults(), resultTypes.size());
81*e67080dfSJacques Pienaar for (unsigned idx : llvm::seq(0U, op->getNumResults()))
82*e67080dfSJacques Pienaar EXPECT_EQ(op->getResult(idx).getType(), resultTypes[idx]);
8313d05787SRahul Joshi
84*e67080dfSJacques Pienaar auto operands = llvm::to_vector(llvm::concat<Value>(operands1, operands2));
85*e67080dfSJacques Pienaar EXPECT_EQ(op->getNumOperands(), operands.size());
86*e67080dfSJacques Pienaar for (unsigned idx : llvm::seq(0U, op->getNumOperands()))
87*e67080dfSJacques Pienaar EXPECT_EQ(op->getOperand(idx), operands[idx]);
8813d05787SRahul Joshi
89*e67080dfSJacques Pienaar EXPECT_EQ(op->getAttrs().size(), attrs.size());
90*e67080dfSJacques Pienaar if (op->getAttrs().size() != attrs.size()) {
91*e67080dfSJacques Pienaar // Simple export where there is mismatch count.
92*e67080dfSJacques Pienaar llvm::errs() << "Op attrs:\n";
93*e67080dfSJacques Pienaar for (auto it : op->getAttrs())
94*e67080dfSJacques Pienaar llvm::errs() << "\t" << it.getName() << " = " << it.getValue() << "\n";
95*e67080dfSJacques Pienaar
96*e67080dfSJacques Pienaar llvm::errs() << "Expected attrs:\n";
97*e67080dfSJacques Pienaar for (auto it : attrs)
98*e67080dfSJacques Pienaar llvm::errs() << "\t" << it.getName() << " = " << it.getValue() << "\n";
99*e67080dfSJacques Pienaar } else {
100*e67080dfSJacques Pienaar for (unsigned idx : llvm::seq<unsigned>(0U, attrs.size()))
101*e67080dfSJacques Pienaar EXPECT_EQ(op->getAttr(attrs[idx].getName().strref()),
102*e67080dfSJacques Pienaar attrs[idx].getValue());
103*e67080dfSJacques Pienaar }
104*e67080dfSJacques Pienaar
105*e67080dfSJacques Pienaar EXPECT_TRUE(mlir::succeeded(concreteOp.verify()));
106*e67080dfSJacques Pienaar concreteOp.erase();
10713d05787SRahul Joshi }
10813d05787SRahul Joshi
1090b161defSRahul Joshi protected:
110f9dc2b70SMehdi Amini MLIRContext &ctx;
1110b161defSRahul Joshi OpBuilder builder;
1120b161defSRahul Joshi Location loc;
1130b161defSRahul Joshi Type i32Ty;
1140b161defSRahul Joshi Type f32Ty;
115107198feSMehdi Amini OwningOpRef<test::TableGenConstant> cstI32;
116107198feSMehdi Amini OwningOpRef<test::TableGenConstant> cstF32;
1170b161defSRahul Joshi
1180b161defSRahul Joshi ArrayRef<NamedAttribute> noAttrs;
1190b161defSRahul Joshi std::vector<NamedAttribute> attrStorage;
1200b161defSRahul Joshi ArrayRef<NamedAttribute> attrs;
1210b161defSRahul Joshi };
1220b161defSRahul Joshi
1230b161defSRahul Joshi /// Test basic build methods.
TEST_F(OpBuildGenTest,BasicBuildMethods)1240b161defSRahul Joshi TEST_F(OpBuildGenTest, BasicBuildMethods) {
1250b161defSRahul Joshi // Test separate args, separate results build method.
126107198feSMehdi Amini auto op = builder.create<test::TableGenBuildOp0>(loc, i32Ty, *cstI32);
127107198feSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
1280b161defSRahul Joshi
1290b161defSRahul Joshi // Test separate args, collective results build method.
130107198feSMehdi Amini op = builder.create<test::TableGenBuildOp0>(loc, TypeRange{i32Ty}, *cstI32);
131107198feSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
1320b161defSRahul Joshi
1330b161defSRahul Joshi // Test collective args, collective params build method.
134d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp0>(loc, TypeRange{i32Ty},
135107198feSMehdi Amini ValueRange{*cstI32});
136107198feSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
1370b161defSRahul Joshi
1380b161defSRahul Joshi // Test collective args, collective results, non-empty attributes
139d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp0>(loc, TypeRange{i32Ty},
140107198feSMehdi Amini ValueRange{*cstI32}, attrs);
141107198feSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32}, attrs);
1420b161defSRahul Joshi }
1430b161defSRahul Joshi
1440b161defSRahul Joshi /// The following 3 tests exercise build methods generated for operations
1450b161defSRahul Joshi /// with a combination of:
1460b161defSRahul Joshi ///
1470b161defSRahul Joshi /// single variadic arg x
1480b161defSRahul Joshi /// {single variadic result, non-variadic result, multiple variadic results}
1490b161defSRahul Joshi ///
1507557530fSFangrui Song /// Specifically to test that ODS framework does not generate ambiguous
1510b161defSRahul Joshi /// build() methods that fail to compile.
1520b161defSRahul Joshi
1530b161defSRahul Joshi /// Test build methods for an Op with a single varadic arg and a single
1540b161defSRahul Joshi /// variadic result.
TEST_F(OpBuildGenTest,BuildMethodsSingleVariadicArgAndResult)1550b161defSRahul Joshi TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgAndResult) {
1560b161defSRahul Joshi // Test collective args, collective results method, building a unary op.
157d413f4bcSAlexander Belyaev auto op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
158107198feSMehdi Amini ValueRange{*cstI32});
159337c937dSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
1600b161defSRahul Joshi
1610b161defSRahul Joshi // Test collective args, collective results method, building a unary op with
1620b161defSRahul Joshi // named attributes.
163d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
164107198feSMehdi Amini ValueRange{*cstI32}, attrs);
165337c937dSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32}, attrs);
1660b161defSRahul Joshi
1670b161defSRahul Joshi // Test collective args, collective results method, building a binary op.
168d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty, f32Ty},
169107198feSMehdi Amini ValueRange{*cstI32, *cstF32});
170337c937dSMehdi Amini verifyOp(op, {i32Ty, f32Ty}, {*cstI32, *cstF32}, noAttrs);
1710b161defSRahul Joshi
1720b161defSRahul Joshi // Test collective args, collective results method, building a binary op with
1730b161defSRahul Joshi // named attributes.
174d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp1>(
175107198feSMehdi Amini loc, TypeRange{i32Ty, f32Ty}, ValueRange{*cstI32, *cstF32}, attrs);
176337c937dSMehdi Amini verifyOp(op, {i32Ty, f32Ty}, {*cstI32, *cstF32}, attrs);
1770b161defSRahul Joshi }
1780b161defSRahul Joshi
1790b161defSRahul Joshi /// Test build methods for an Op with a single varadic arg and a non-variadic
1800b161defSRahul Joshi /// result.
TEST_F(OpBuildGenTest,BuildMethodsSingleVariadicArgNonVariadicResults)1810b161defSRahul Joshi TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgNonVariadicResults) {
1820b161defSRahul Joshi // Test separate arg, separate param build method.
183d413f4bcSAlexander Belyaev auto op =
184107198feSMehdi Amini builder.create<test::TableGenBuildOp1>(loc, i32Ty, ValueRange{*cstI32});
185337c937dSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
1860b161defSRahul Joshi
1870b161defSRahul Joshi // Test collective params build method, no attributes.
188d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
189107198feSMehdi Amini ValueRange{*cstI32});
190337c937dSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32}, noAttrs);
1910b161defSRahul Joshi
1920b161defSRahul Joshi // Test collective params build method no attributes, 2 inputs.
193d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp1>(loc, TypeRange{i32Ty},
194107198feSMehdi Amini ValueRange{*cstI32, *cstF32});
195337c937dSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, noAttrs);
1960b161defSRahul Joshi
1970b161defSRahul Joshi // Test collective params build method, non-empty attributes.
198d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp1>(
199107198feSMehdi Amini loc, TypeRange{i32Ty}, ValueRange{*cstI32, *cstF32}, attrs);
200337c937dSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, attrs);
2010b161defSRahul Joshi }
2020b161defSRahul Joshi
2030b161defSRahul Joshi /// Test build methods for an Op with a single varadic arg and multiple variadic
2040b161defSRahul Joshi /// result.
TEST_F(OpBuildGenTest,BuildMethodsSingleVariadicArgAndMultipleVariadicResults)2050b161defSRahul Joshi TEST_F(OpBuildGenTest,
2060b161defSRahul Joshi BuildMethodsSingleVariadicArgAndMultipleVariadicResults) {
2070b161defSRahul Joshi // Test separate arg, separate param build method.
208d413f4bcSAlexander Belyaev auto op = builder.create<test::TableGenBuildOp3>(
209107198feSMehdi Amini loc, TypeRange{i32Ty}, TypeRange{f32Ty}, ValueRange{*cstI32});
210337c937dSMehdi Amini verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, noAttrs);
2110b161defSRahul Joshi
2120b161defSRahul Joshi // Test collective params build method, no attributes.
213d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp3>(loc, TypeRange{i32Ty, f32Ty},
214107198feSMehdi Amini ValueRange{*cstI32});
215337c937dSMehdi Amini verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, noAttrs);
2160b161defSRahul Joshi
2170b161defSRahul Joshi // Test collective params build method, with attributes.
218d413f4bcSAlexander Belyaev op = builder.create<test::TableGenBuildOp3>(loc, TypeRange{i32Ty, f32Ty},
219107198feSMehdi Amini ValueRange{*cstI32}, attrs);
220337c937dSMehdi Amini verifyOp(op, {i32Ty, f32Ty}, {*cstI32}, attrs);
2210b161defSRahul Joshi }
2220b161defSRahul Joshi
223*e67080dfSJacques Pienaar // The next test checks suppression of ambiguous build methods for ops that
22413d05787SRahul Joshi // have a single variadic input, and single non-variadic result, and which
225*e67080dfSJacques Pienaar // support the SameOperandsAndResultType trait and optionally the
22613d05787SRahul Joshi // InferOpTypeInterface interface. For such ops, the ODS framework generates
22713d05787SRahul Joshi // build methods with no result types as they are inferred from the input types.
TEST_F(OpBuildGenTest,BuildMethodsSameOperandsAndResultTypeSuppression)22813d05787SRahul Joshi TEST_F(OpBuildGenTest, BuildMethodsSameOperandsAndResultTypeSuppression) {
229*e67080dfSJacques Pienaar // Test separate arg, separate param build method.
230*e67080dfSJacques Pienaar auto op = builder.create<test::TableGenBuildOp4>(
231*e67080dfSJacques Pienaar loc, i32Ty, ValueRange{*cstI32, *cstI32});
232*e67080dfSJacques Pienaar verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);
233*e67080dfSJacques Pienaar
234*e67080dfSJacques Pienaar // Test collective params build method.
235*e67080dfSJacques Pienaar op = builder.create<test::TableGenBuildOp4>(loc, TypeRange{i32Ty},
236*e67080dfSJacques Pienaar ValueRange{*cstI32, *cstI32});
237*e67080dfSJacques Pienaar verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);
238*e67080dfSJacques Pienaar
239*e67080dfSJacques Pienaar // Test build method with no result types, default value of attributes.
240*e67080dfSJacques Pienaar op =
241*e67080dfSJacques Pienaar builder.create<test::TableGenBuildOp4>(loc, ValueRange{*cstI32, *cstI32});
242*e67080dfSJacques Pienaar verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, noAttrs);
243*e67080dfSJacques Pienaar
244*e67080dfSJacques Pienaar // Test build method with no result types and supplied attributes.
245*e67080dfSJacques Pienaar op = builder.create<test::TableGenBuildOp4>(loc, ValueRange{*cstI32, *cstI32},
246*e67080dfSJacques Pienaar attrs);
247*e67080dfSJacques Pienaar verifyOp(std::move(op), {i32Ty}, {*cstI32, *cstI32}, attrs);
24813d05787SRahul Joshi }
24913d05787SRahul Joshi
TEST_F(OpBuildGenTest,BuildMethodsRegionsAndInferredType)250843534dbSMogball TEST_F(OpBuildGenTest, BuildMethodsRegionsAndInferredType) {
25192a836daSRiver Riddle auto op = builder.create<test::TableGenBuildOp5>(
252843534dbSMogball loc, ValueRange{*cstI32, *cstF32}, /*attributes=*/noAttrs);
253843534dbSMogball ASSERT_EQ(op->getNumRegions(), 1u);
254337c937dSMehdi Amini verifyOp(op, {i32Ty}, {*cstI32, *cstF32}, noAttrs);
255843534dbSMogball }
256843534dbSMogball
TEST_F(OpBuildGenTest,BuildMethodsVariadicProperties)257*e67080dfSJacques Pienaar TEST_F(OpBuildGenTest, BuildMethodsVariadicProperties) {
258*e67080dfSJacques Pienaar // Account for conversion as part of getAttrs().
259*e67080dfSJacques Pienaar std::vector<NamedAttribute> noAttrsStorage;
260*e67080dfSJacques Pienaar auto segmentSize = builder.getNamedAttr("operandSegmentSizes",
261*e67080dfSJacques Pienaar builder.getDenseI32ArrayAttr({1, 1}));
262*e67080dfSJacques Pienaar noAttrsStorage.push_back(segmentSize);
263*e67080dfSJacques Pienaar ArrayRef<NamedAttribute> noAttrs(noAttrsStorage);
264*e67080dfSJacques Pienaar std::vector<NamedAttribute> attrsStorage = this->attrStorage;
265*e67080dfSJacques Pienaar attrsStorage.push_back(segmentSize);
266*e67080dfSJacques Pienaar ArrayRef<NamedAttribute> attrs(attrsStorage);
267*e67080dfSJacques Pienaar
268*e67080dfSJacques Pienaar // Test separate arg, separate param build method.
269*e67080dfSJacques Pienaar auto op = builder.create<test::TableGenBuildOp6>(
270*e67080dfSJacques Pienaar loc, f32Ty, ValueRange{*cstI32}, ValueRange{*cstI32});
271*e67080dfSJacques Pienaar verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs);
272*e67080dfSJacques Pienaar
273*e67080dfSJacques Pienaar // Test build method with no result types, default value of attributes.
274*e67080dfSJacques Pienaar op = builder.create<test::TableGenBuildOp6>(loc, ValueRange{*cstI32},
275*e67080dfSJacques Pienaar ValueRange{*cstI32});
276*e67080dfSJacques Pienaar verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs);
277*e67080dfSJacques Pienaar
278*e67080dfSJacques Pienaar // Test collective params build method.
279*e67080dfSJacques Pienaar op = builder.create<test::TableGenBuildOp6>(
280*e67080dfSJacques Pienaar loc, TypeRange{f32Ty}, ValueRange{*cstI32}, ValueRange{*cstI32});
281*e67080dfSJacques Pienaar verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, noAttrs);
282*e67080dfSJacques Pienaar
283*e67080dfSJacques Pienaar // Test build method with result types, supplied attributes.
284*e67080dfSJacques Pienaar op = builder.create<test::TableGenBuildOp6>(
285*e67080dfSJacques Pienaar loc, TypeRange{f32Ty}, ValueRange{*cstI32, *cstI32}, attrs);
286*e67080dfSJacques Pienaar verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, attrs);
287*e67080dfSJacques Pienaar
288*e67080dfSJacques Pienaar // Test build method with no result types and supplied attributes.
289*e67080dfSJacques Pienaar op = builder.create<test::TableGenBuildOp6>(loc, ValueRange{*cstI32, *cstI32},
290*e67080dfSJacques Pienaar attrs);
291*e67080dfSJacques Pienaar verifyOp(std::move(op), {f32Ty}, {*cstI32}, {*cstI32}, attrs);
292*e67080dfSJacques Pienaar }
293*e67080dfSJacques Pienaar
2940b161defSRahul Joshi } // namespace mlir
295