221
|
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 "mlir/IR/Identifier.h"
|
|
19 #include "gmock/gmock.h"
|
|
20 #include <vector>
|
|
21
|
|
22 namespace mlir {
|
|
23
|
|
24 //===----------------------------------------------------------------------===//
|
|
25 // Test Fixture
|
|
26 //===----------------------------------------------------------------------===//
|
|
27
|
|
28 static MLIRContext &getContext() {
|
|
29 static MLIRContext ctx;
|
|
30 ctx.getOrLoadDialect<test::TestDialect>();
|
|
31 return ctx;
|
|
32 }
|
|
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) {}
|
|
46
|
|
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();
|
|
55
|
|
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]);
|
|
59
|
|
60 EXPECT_EQ(op->getNumOperands(), operands.size());
|
|
61 for (unsigned idx : llvm::seq(0U, op->getNumOperands()))
|
|
62 EXPECT_EQ(op->getOperand(idx), operands[idx]);
|
|
63
|
|
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].first.strref()), attrs[idx].second);
|
|
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 =
|
|
81 builder.create<OpTy>(loc, TypeRange{i32Ty}, 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
|
|
93 protected:
|
|
94 MLIRContext &ctx;
|
|
95 OpBuilder builder;
|
|
96 Location loc;
|
|
97 Type i32Ty;
|
|
98 Type f32Ty;
|
|
99 test::TableGenConstant cstI32;
|
|
100 test::TableGenConstant cstF32;
|
|
101
|
|
102 ArrayRef<NamedAttribute> noAttrs;
|
|
103 std::vector<NamedAttribute> attrStorage;
|
|
104 ArrayRef<NamedAttribute> attrs;
|
|
105 };
|
|
106
|
|
107 /// Test basic build methods.
|
|
108 TEST_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 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.
|
|
139 TEST_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(std::move(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(std::move(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(std::move(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(std::move(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.
|
|
165 TEST_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(std::move(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(std::move(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(std::move(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(std::move(op), {i32Ty}, {cstI32, cstF32}, attrs);
|
|
185 }
|
|
186
|
|
187 /// Test build methods for an Op with a single varadic arg and multiple variadic
|
|
188 /// result.
|
|
189 TEST_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(std::move(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(std::move(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(std::move(op), {i32Ty, f32Ty}, {cstI32}, attrs);
|
|
205 }
|
|
206
|
|
207 // The next 2 tests test 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.
|
|
212 TEST_F(OpBuildGenTest, BuildMethodsSameOperandsAndResultTypeSuppression) {
|
|
213 testSingleVariadicInputInferredType<test::TableGenBuildOp4>();
|
|
214 }
|
|
215
|
|
216 TEST_F(
|
|
217 OpBuildGenTest,
|
|
218 BuildMethodsSameOperandsAndResultTypeAndInferOpTypeInterfaceSuppression) {
|
|
219 testSingleVariadicInputInferredType<test::TableGenBuildOp5>();
|
|
220 }
|
|
221
|
|
222 } // namespace mlir
|