1 //===- OpBuildGen.cpp - TableGen OpBuildGen Tests -------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Test TableGen generated build() methods on Operations.
11 //===----------------------------------------------------------------------===//
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"
23 //===----------------------------------------------------------------------===//
25 //===----------------------------------------------------------------------===//
27 static MLIRContext
&getContext() {
28 static MLIRContext ctx
;
29 ctx
.getOrLoadDialect
<test::TestDialect
>();
32 /// Test fixture for providing basic utilities for testing.
33 class OpBuildGenTest
: public ::testing::Test
{
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("attr0",
41 builder
.getBoolAttr(true)),
43 "attr1", builder
.getI32IntegerAttr(33))},
46 // Verify that `op` has the given set of result types, operands, and
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();
55 EXPECT_EQ(op
->getNumResults(), resultTypes
.size());
56 for (unsigned idx
: llvm::seq(0U, op
->getNumResults()))
57 EXPECT_EQ(op
->getResult(idx
).getType(), resultTypes
[idx
]);
59 EXPECT_EQ(op
->getNumOperands(), operands
.size());
60 for (unsigned idx
: llvm::seq(0U, op
->getNumOperands()))
61 EXPECT_EQ(op
->getOperand(idx
), operands
[idx
]);
63 EXPECT_EQ(op
->getAttrs().size(), attrs
.size());
64 for (unsigned idx
: llvm::seq
<unsigned>(0U, attrs
.size()))
65 EXPECT_EQ(op
->getAttr(attrs
[idx
].getName().strref()),
66 attrs
[idx
].getValue());
71 // Helper method to test ops with inferred result types and single variadic
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
);
79 // Test collective params build method.
81 builder
.create
<OpTy
>(loc
, TypeRange
{i32Ty
}, ValueRange
{*cstI32
, *cstI32
});
82 verifyOp(std::move(op
), {i32Ty
}, {*cstI32
, *cstI32
}, noAttrs
);
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
);
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
);
99 OwningOpRef
<test::TableGenConstant
> cstI32
;
100 OwningOpRef
<test::TableGenConstant
> cstF32
;
102 ArrayRef
<NamedAttribute
> noAttrs
;
103 std::vector
<NamedAttribute
> attrStorage
;
104 ArrayRef
<NamedAttribute
> attrs
;
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
);
113 // Test separate args, collective results build method.
114 op
= builder
.create
<test::TableGenBuildOp0
>(loc
, TypeRange
{i32Ty
}, *cstI32
);
115 verifyOp(op
, {i32Ty
}, {*cstI32
}, noAttrs
);
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
);
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
);
128 /// The following 3 tests exercise build methods generated for operations
129 /// with a combination of:
131 /// single variadic arg x
132 /// {single variadic result, non-variadic result, multiple variadic results}
134 /// Specifically to test that that ODS framework does not generate ambiguous
135 /// build() methods that fail to compile.
137 /// Test build methods for an Op with a single varadic arg and a single
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(op
, {i32Ty
}, {*cstI32
}, noAttrs
);
145 // Test collective args, collective results method, building a unary op with
147 op
= builder
.create
<test::TableGenBuildOp1
>(loc
, TypeRange
{i32Ty
},
148 ValueRange
{*cstI32
}, attrs
);
149 verifyOp(op
, {i32Ty
}, {*cstI32
}, attrs
);
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
);
156 // Test collective args, collective results method, building a binary op with
158 op
= builder
.create
<test::TableGenBuildOp1
>(
159 loc
, TypeRange
{i32Ty
, f32Ty
}, ValueRange
{*cstI32
, *cstF32
}, attrs
);
160 verifyOp(op
, {i32Ty
, f32Ty
}, {*cstI32
, *cstF32
}, attrs
);
163 /// Test build methods for an Op with a single varadic arg and a non-variadic
165 TEST_F(OpBuildGenTest
, BuildMethodsSingleVariadicArgNonVariadicResults
) {
166 // Test separate arg, separate param build method.
168 builder
.create
<test::TableGenBuildOp1
>(loc
, i32Ty
, ValueRange
{*cstI32
});
169 verifyOp(op
, {i32Ty
}, {*cstI32
}, noAttrs
);
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
);
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
);
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
);
187 /// Test build methods for an Op with a single varadic arg and multiple variadic
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(op
, {i32Ty
, f32Ty
}, {*cstI32
}, noAttrs
);
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
);
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
);
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
>();
218 BuildMethodsSameOperandsAndResultTypeAndInferOpTypeInterfaceSuppression
) {
219 testSingleVariadicInputInferredType
<test::TableGenBuildOp5
>();
222 TEST_F(OpBuildGenTest
, BuildMethodsRegionsAndInferredType
) {
223 auto op
= builder
.create
<test::TableGenBuildOp6
>(
224 loc
, ValueRange
{*cstI32
, *cstF32
}, /*attributes=*/noAttrs
);
225 ASSERT_EQ(op
->getNumRegions(), 1u);
226 verifyOp(op
, {i32Ty
}, {*cstI32
, *cstF32
}, noAttrs
);