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/Dialect.h"
17 #include "mlir/IR/Identifier.h"
18 #include "mlir/IR/StandardTypes.h"
19 #include "gmock/gmock.h"
20 #include <vector>
21 
22 namespace mlir {
23 
24 //===----------------------------------------------------------------------===//
25 // Test Fixture
26 //===----------------------------------------------------------------------===//
27 
28 /// Test fixture for providing basic utilities for testing.
29 class OpBuildGenTest : public ::testing::Test {
30 protected:
31   OpBuildGenTest()
32       : ctx{}, builder(&ctx), loc(builder.getUnknownLoc()),
33         i32Ty(builder.getI32Type()), f32Ty(builder.getF32Type()),
34         cstI32(builder.create<TableGenConstant>(loc, i32Ty)),
35         cstF32(builder.create<TableGenConstant>(loc, f32Ty)),
36         noAttrs(), attrStorage{builder.getNamedAttr("attr0",
37                                                     builder.getBoolAttr(true)),
38                                builder.getNamedAttr(
39                                    "attr1", builder.getI32IntegerAttr(33))},
40         attrs(attrStorage) {}
41 
42   // Verify that `op` has the given set of result types, operands, and
43   // attributes.
44   template <typename OpTy>
45   void verifyOp(OpTy &&concreteOp, std::vector<Type> resultTypes,
46                 std::vector<Value> operands,
47                 std::vector<NamedAttribute> attrs) {
48     ASSERT_NE(concreteOp, nullptr);
49     Operation *op = concreteOp.getOperation();
50 
51     EXPECT_EQ(op->getNumResults(), resultTypes.size());
52     for (unsigned idx : llvm::seq(0U, op->getNumResults()))
53       EXPECT_EQ(op->getResult(idx).getType(), resultTypes[idx]);
54 
55     EXPECT_EQ(op->getNumOperands(), operands.size());
56     for (unsigned idx : llvm::seq(0U, op->getNumOperands()))
57       EXPECT_EQ(op->getOperand(idx), operands[idx]);
58 
59     EXPECT_EQ(op->getAttrs().size(), attrs.size());
60     for (unsigned idx : llvm::seq<unsigned>(0U, attrs.size()))
61       EXPECT_EQ(op->getAttr(attrs[idx].first.strref()), attrs[idx].second);
62 
63     concreteOp.erase();
64   }
65 
66 protected:
67   MLIRContext ctx;
68   OpBuilder builder;
69   Location loc;
70   Type i32Ty;
71   Type f32Ty;
72   TableGenConstant cstI32;
73   TableGenConstant cstF32;
74 
75   ArrayRef<NamedAttribute> noAttrs;
76   std::vector<NamedAttribute> attrStorage;
77   ArrayRef<NamedAttribute> attrs;
78 };
79 
80 /// Test basic build methods.
81 TEST_F(OpBuildGenTest, BasicBuildMethods) {
82   // Test separate args, separate results build method.
83   auto op = builder.create<TableGenBuildOp0>(loc, i32Ty, cstI32);
84   verifyOp(op, {i32Ty}, {cstI32}, noAttrs);
85 
86   // Test separate args, collective results build method.
87   op = builder.create<TableGenBuildOp0>(loc, ArrayRef<Type>{i32Ty}, cstI32);
88   verifyOp(op, {i32Ty}, {cstI32}, noAttrs);
89 
90   // Test collective args, collective params build method.
91   op = builder.create<TableGenBuildOp0>(loc, ArrayRef<Type>{i32Ty},
92                                         ArrayRef<Value>{cstI32});
93   verifyOp(op, {i32Ty}, {cstI32}, noAttrs);
94 
95   // Test collective args, collective results, non-empty attributes
96   op = builder.create<TableGenBuildOp0>(loc, ArrayRef<Type>{i32Ty},
97                                         ArrayRef<Value>{cstI32}, attrs);
98   verifyOp(op, {i32Ty}, {cstI32}, attrs);
99 }
100 
101 /// The following 3 tests exercise build methods generated for operations
102 /// with a combination of:
103 ///
104 /// single variadic arg x
105 /// {single variadic result, non-variadic result, multiple variadic results}
106 ///
107 /// Specifically to test that that ODS framework does not generate ambiguous
108 /// build() methods that fail to compile.
109 
110 /// Test build methods for an Op with a single varadic arg and a single
111 /// variadic result.
112 TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgAndResult) {
113   // Test collective args, collective results method, building a unary op.
114   auto op = builder.create<TableGenBuildOp1>(loc, ArrayRef<Type>{i32Ty},
115                                              ArrayRef<Value>{cstI32});
116   verifyOp(std::move(op), {i32Ty}, {cstI32}, noAttrs);
117 
118   // Test collective args, collective results method, building a unary op with
119   // named attributes.
120   op = builder.create<TableGenBuildOp1>(loc, ArrayRef<Type>{i32Ty},
121                                         ArrayRef<Value>{cstI32}, attrs);
122   verifyOp(std::move(op), {i32Ty}, {cstI32}, attrs);
123 
124   // Test collective args, collective results method, building a binary op.
125   op = builder.create<TableGenBuildOp1>(loc, ArrayRef<Type>{i32Ty, f32Ty},
126                                         ArrayRef<Value>{cstI32, cstF32});
127   verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32, cstF32}, noAttrs);
128 
129   // Test collective args, collective results method, building a binary op with
130   // named attributes.
131   op = builder.create<TableGenBuildOp1>(loc, ArrayRef<Type>{i32Ty, f32Ty},
132                                         ArrayRef<Value>{cstI32, cstF32}, attrs);
133   verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32, cstF32}, attrs);
134 }
135 
136 /// Test build methods for an Op with a single varadic arg and a non-variadic
137 /// result.
138 TEST_F(OpBuildGenTest, BuildMethodsSingleVariadicArgNonVariadicResults) {
139   // Test separate arg, separate param build method.
140   auto op =
141       builder.create<TableGenBuildOp1>(loc, i32Ty, ArrayRef<Value>{cstI32});
142   verifyOp(std::move(op), {i32Ty}, {cstI32}, noAttrs);
143 
144   // Test collective params build method, no attributes.
145   op = builder.create<TableGenBuildOp1>(loc, ArrayRef<Type>{i32Ty},
146                                         ArrayRef<Value>{cstI32});
147   verifyOp(std::move(op), {i32Ty}, {cstI32}, noAttrs);
148 
149   // Test collective params build method no attributes, 2 inputs.
150   op = builder.create<TableGenBuildOp1>(loc, ArrayRef<Type>{i32Ty},
151                                         ArrayRef<Value>{cstI32, cstF32});
152   verifyOp(std::move(op), {i32Ty}, {cstI32, cstF32}, noAttrs);
153 
154   // Test collective params build method, non-empty attributes.
155   op = builder.create<TableGenBuildOp1>(loc, ArrayRef<Type>{i32Ty},
156                                         ArrayRef<Value>{cstI32, cstF32}, attrs);
157   verifyOp(std::move(op), {i32Ty}, {cstI32, cstF32}, attrs);
158 }
159 
160 /// Test build methods for an Op with a single varadic arg and multiple variadic
161 /// result.
162 TEST_F(OpBuildGenTest,
163        BuildMethodsSingleVariadicArgAndMultipleVariadicResults) {
164   // Test separate arg, separate param build method.
165   auto op = builder.create<TableGenBuildOp3>(loc, ArrayRef<Type>{i32Ty},
166                                              ArrayRef<Type>{f32Ty},
167                                              ArrayRef<Value>{cstI32});
168   verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32}, noAttrs);
169 
170   // Test collective params build method, no attributes.
171   op = builder.create<TableGenBuildOp3>(loc, ArrayRef<Type>{i32Ty, f32Ty},
172                                         ArrayRef<Value>{cstI32});
173   verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32}, noAttrs);
174 
175   // Test collective params build method, with attributes.
176   op = builder.create<TableGenBuildOp3>(loc, ArrayRef<Type>{i32Ty, f32Ty},
177                                         ArrayRef<Value>{cstI32}, attrs);
178   verifyOp(std::move(op), {i32Ty, f32Ty}, {cstI32}, attrs);
179 }
180 
181 } // namespace mlir
182