1//===- OpenACCOpsTest.cpp - Unit tests for OpenACC ops --------------------===//
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#include "mlir/Dialect/Arith/IR/Arith.h"
10#include "mlir/Dialect/MemRef/IR/MemRef.h"
11#include "mlir/Dialect/OpenACC/OpenACC.h"
12#include "mlir/IR/BuiltinTypes.h"
13#include "mlir/IR/Diagnostics.h"
14#include "mlir/IR/MLIRContext.h"
15#include "mlir/IR/OwningOpRef.h"
16#include "mlir/IR/Value.h"
17#include "gtest/gtest.h"
18
19using namespace mlir;
20using namespace mlir::acc;
21
22//===----------------------------------------------------------------------===//
23// Test Fixture
24//===----------------------------------------------------------------------===//
25
26class OpenACCOpsTest : public ::testing::Test {
27protected:
28 OpenACCOpsTest() : b(&context), loc(UnknownLoc::get(&context)) {
29 context.loadDialect<acc::OpenACCDialect, arith::ArithDialect,
30 memref::MemRefDialect>();
31 }
32
33 MLIRContext context;
34 OpBuilder b;
35 Location loc;
36 llvm::SmallVector<DeviceType> dtypes = {
37 DeviceType::None, DeviceType::Star, DeviceType::Multicore,
38 DeviceType::Default, DeviceType::Host, DeviceType::Nvidia,
39 DeviceType::Radeon};
40 llvm::SmallVector<DeviceType> dtypesWithoutNone = {
41 DeviceType::Star, DeviceType::Multicore, DeviceType::Default,
42 DeviceType::Host, DeviceType::Nvidia, DeviceType::Radeon};
43};
44
45template <typename Op>
46void testAsyncOnly(OpBuilder &b, MLIRContext &context, Location loc,
47 llvm::SmallVector<DeviceType> &dtypes) {
48 OwningOpRef<Op> op = b.create<Op>(loc, TypeRange{}, ValueRange{});
49 EXPECT_FALSE(op->hasAsyncOnly());
50 for (auto d : dtypes)
51 EXPECT_FALSE(op->hasAsyncOnly(d));
52
53 auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None);
54 op->setAsyncOnlyAttr(b.getArrayAttr(value: {dtypeNone}));
55 EXPECT_TRUE(op->hasAsyncOnly());
56 EXPECT_TRUE(op->hasAsyncOnly(DeviceType::None));
57 op->removeAsyncOnlyAttr();
58
59 auto dtypeHost = DeviceTypeAttr::get(&context, DeviceType::Host);
60 op->setAsyncOnlyAttr(b.getArrayAttr(value: {dtypeHost}));
61 EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Host));
62 EXPECT_FALSE(op->hasAsyncOnly());
63 op->removeAsyncOnlyAttr();
64
65 auto dtypeStar = DeviceTypeAttr::get(&context, DeviceType::Star);
66 op->setAsyncOnlyAttr(b.getArrayAttr(value: {dtypeHost, dtypeStar}));
67 EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Star));
68 EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Host));
69 EXPECT_FALSE(op->hasAsyncOnly());
70
71 op->removeAsyncOnlyAttr();
72}
73
74TEST_F(OpenACCOpsTest, asyncOnlyTest) {
75 testAsyncOnly<ParallelOp>(b, context, loc, dtypes);
76 testAsyncOnly<KernelsOp>(b, context, loc, dtypes);
77 testAsyncOnly<SerialOp>(b, context, loc, dtypes);
78}
79
80template <typename Op>
81void testAsyncOnlyDataEntry(OpBuilder &b, MLIRContext &context, Location loc,
82 llvm::SmallVector<DeviceType> &dtypes) {
83 auto memrefTy = MemRefType::get({}, b.getI32Type());
84 OwningOpRef<memref::AllocaOp> varPtrOp =
85 b.create<memref::AllocaOp>(loc, memrefTy);
86
87 TypedValue<PointerLikeType> varPtr =
88 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());
89 OwningOpRef<Op> op = b.create<Op>(loc, varPtr,
90 /*structured=*/true, /*implicit=*/true);
91
92 EXPECT_FALSE(op->hasAsyncOnly());
93 for (auto d : dtypes)
94 EXPECT_FALSE(op->hasAsyncOnly(d));
95
96 auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None);
97 op->setAsyncOnlyAttr(b.getArrayAttr(value: {dtypeNone}));
98 EXPECT_TRUE(op->hasAsyncOnly());
99 EXPECT_TRUE(op->hasAsyncOnly(DeviceType::None));
100 op->removeAsyncOnlyAttr();
101
102 auto dtypeHost = DeviceTypeAttr::get(&context, DeviceType::Host);
103 op->setAsyncOnlyAttr(b.getArrayAttr(value: {dtypeHost}));
104 EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Host));
105 EXPECT_FALSE(op->hasAsyncOnly());
106 op->removeAsyncOnlyAttr();
107
108 auto dtypeStar = DeviceTypeAttr::get(&context, DeviceType::Star);
109 op->setAsyncOnlyAttr(b.getArrayAttr(value: {dtypeHost, dtypeStar}));
110 EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Star));
111 EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Host));
112 EXPECT_FALSE(op->hasAsyncOnly());
113
114 op->removeAsyncOnlyAttr();
115}
116
117TEST_F(OpenACCOpsTest, asyncOnlyTestDataEntry) {
118 testAsyncOnlyDataEntry<DevicePtrOp>(b, context, loc, dtypes);
119 testAsyncOnlyDataEntry<PresentOp>(b, context, loc, dtypes);
120 testAsyncOnlyDataEntry<CopyinOp>(b, context, loc, dtypes);
121 testAsyncOnlyDataEntry<CreateOp>(b, context, loc, dtypes);
122 testAsyncOnlyDataEntry<NoCreateOp>(b, context, loc, dtypes);
123 testAsyncOnlyDataEntry<AttachOp>(b, context, loc, dtypes);
124 testAsyncOnlyDataEntry<UpdateDeviceOp>(b, context, loc, dtypes);
125 testAsyncOnlyDataEntry<UseDeviceOp>(b, context, loc, dtypes);
126}
127
128template <typename Op>
129void testAsyncValue(OpBuilder &b, MLIRContext &context, Location loc,
130 llvm::SmallVector<DeviceType> &dtypes) {
131 OwningOpRef<Op> op = b.create<Op>(loc, TypeRange{}, ValueRange{});
132
133 mlir::Value empty;
134 EXPECT_EQ(op->getAsyncValue(), empty);
135 for (auto d : dtypes)
136 EXPECT_EQ(op->getAsyncValue(d), empty);
137
138 OwningOpRef<arith::ConstantIndexOp> val =
139 b.create<arith::ConstantIndexOp>(location: loc, args: 1);
140 auto dtypeNvidia = DeviceTypeAttr::get(&context, DeviceType::Nvidia);
141 op->setAsyncOperandsDeviceTypeAttr(b.getArrayAttr(value: {dtypeNvidia}));
142 op->getAsyncOperandsMutable().assign(val->getResult());
143 EXPECT_EQ(op->getAsyncValue(), empty);
144 EXPECT_EQ(op->getAsyncValue(DeviceType::Nvidia), val->getResult());
145
146 op->getAsyncOperandsMutable().clear();
147 op->removeAsyncOperandsDeviceTypeAttr();
148}
149
150TEST_F(OpenACCOpsTest, asyncValueTest) {
151 testAsyncValue<ParallelOp>(b, context, loc, dtypes);
152 testAsyncValue<KernelsOp>(b, context, loc, dtypes);
153 testAsyncValue<SerialOp>(b, context, loc, dtypes);
154}
155
156template <typename Op>
157void testAsyncValueDataEntry(OpBuilder &b, MLIRContext &context, Location loc,
158 llvm::SmallVector<DeviceType> &dtypes) {
159 auto memrefTy = MemRefType::get({}, b.getI32Type());
160 OwningOpRef<memref::AllocaOp> varPtrOp =
161 b.create<memref::AllocaOp>(loc, memrefTy);
162
163 TypedValue<PointerLikeType> varPtr =
164 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());
165 OwningOpRef<Op> op = b.create<Op>(loc, varPtr,
166 /*structured=*/true, /*implicit=*/true);
167
168 mlir::Value empty;
169 EXPECT_EQ(op->getAsyncValue(), empty);
170 for (auto d : dtypes)
171 EXPECT_EQ(op->getAsyncValue(d), empty);
172
173 OwningOpRef<arith::ConstantIndexOp> val =
174 b.create<arith::ConstantIndexOp>(location: loc, args: 1);
175 auto dtypeNvidia = DeviceTypeAttr::get(&context, DeviceType::Nvidia);
176 op->setAsyncOperandsDeviceTypeAttr(b.getArrayAttr(value: {dtypeNvidia}));
177 op->getAsyncOperandsMutable().assign(val->getResult());
178 EXPECT_EQ(op->getAsyncValue(), empty);
179 EXPECT_EQ(op->getAsyncValue(DeviceType::Nvidia), val->getResult());
180
181 op->getAsyncOperandsMutable().clear();
182 op->removeAsyncOperandsDeviceTypeAttr();
183}
184
185TEST_F(OpenACCOpsTest, asyncValueTestDataEntry) {
186 testAsyncValueDataEntry<DevicePtrOp>(b, context, loc, dtypes);
187 testAsyncValueDataEntry<PresentOp>(b, context, loc, dtypes);
188 testAsyncValueDataEntry<CopyinOp>(b, context, loc, dtypes);
189 testAsyncValueDataEntry<CreateOp>(b, context, loc, dtypes);
190 testAsyncValueDataEntry<NoCreateOp>(b, context, loc, dtypes);
191 testAsyncValueDataEntry<AttachOp>(b, context, loc, dtypes);
192 testAsyncValueDataEntry<UpdateDeviceOp>(b, context, loc, dtypes);
193 testAsyncValueDataEntry<UseDeviceOp>(b, context, loc, dtypes);
194}
195
196template <typename Op>
197void testNumGangsValues(OpBuilder &b, MLIRContext &context, Location loc,
198 llvm::SmallVector<DeviceType> &dtypes,
199 llvm::SmallVector<DeviceType> &dtypesWithoutNone) {
200 OwningOpRef<Op> op = b.create<Op>(loc, TypeRange{}, ValueRange{});
201 EXPECT_EQ(op->getNumGangsValues().begin(), op->getNumGangsValues().end());
202
203 OwningOpRef<arith::ConstantIndexOp> val1 =
204 b.create<arith::ConstantIndexOp>(location: loc, args: 1);
205 OwningOpRef<arith::ConstantIndexOp> val2 =
206 b.create<arith::ConstantIndexOp>(location: loc, args: 4);
207 auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None);
208 op->getNumGangsMutable().assign(val1->getResult());
209 op->setNumGangsDeviceTypeAttr(b.getArrayAttr(value: {dtypeNone}));
210 op->setNumGangsSegments(b.getDenseI32ArrayAttr({1}));
211 EXPECT_EQ(op->getNumGangsValues().front(), val1->getResult());
212 for (auto d : dtypesWithoutNone)
213 EXPECT_EQ(op->getNumGangsValues(d).begin(), op->getNumGangsValues(d).end());
214
215 op->getNumGangsMutable().clear();
216 op->removeNumGangsDeviceTypeAttr();
217 op->removeNumGangsSegmentsAttr();
218 for (auto d : dtypes)
219 EXPECT_EQ(op->getNumGangsValues(d).begin(), op->getNumGangsValues(d).end());
220
221 op->getNumGangsMutable().append(val1->getResult());
222 op->getNumGangsMutable().append(val2->getResult());
223 op->setNumGangsDeviceTypeAttr(
224 b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Host),
225 DeviceTypeAttr::get(&context, DeviceType::Star)}));
226 op->setNumGangsSegments(b.getDenseI32ArrayAttr({1, 1}));
227 EXPECT_EQ(op->getNumGangsValues(DeviceType::None).begin(),
228 op->getNumGangsValues(DeviceType::None).end());
229 EXPECT_EQ(op->getNumGangsValues(DeviceType::Host).front(), val1->getResult());
230 EXPECT_EQ(op->getNumGangsValues(DeviceType::Star).front(), val2->getResult());
231
232 op->getNumGangsMutable().clear();
233 op->removeNumGangsDeviceTypeAttr();
234 op->removeNumGangsSegmentsAttr();
235 for (auto d : dtypes)
236 EXPECT_EQ(op->getNumGangsValues(d).begin(), op->getNumGangsValues(d).end());
237
238 op->getNumGangsMutable().append(val1->getResult());
239 op->getNumGangsMutable().append(val2->getResult());
240 op->getNumGangsMutable().append(val1->getResult());
241 op->setNumGangsDeviceTypeAttr(
242 b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Default),
243 DeviceTypeAttr::get(&context, DeviceType::Multicore)}));
244 op->setNumGangsSegments(b.getDenseI32ArrayAttr({2, 1}));
245 EXPECT_EQ(op->getNumGangsValues(DeviceType::None).begin(),
246 op->getNumGangsValues(DeviceType::None).end());
247 EXPECT_EQ(op->getNumGangsValues(DeviceType::Default).front(),
248 val1->getResult());
249 EXPECT_EQ(op->getNumGangsValues(DeviceType::Default).drop_front().front(),
250 val2->getResult());
251 EXPECT_EQ(op->getNumGangsValues(DeviceType::Multicore).front(),
252 val1->getResult());
253
254 op->getNumGangsMutable().clear();
255 op->removeNumGangsDeviceTypeAttr();
256 op->removeNumGangsSegmentsAttr();
257}
258
259TEST_F(OpenACCOpsTest, numGangsValuesTest) {
260 testNumGangsValues<ParallelOp>(b, context, loc, dtypes, dtypesWithoutNone);
261 testNumGangsValues<KernelsOp>(b, context, loc, dtypes, dtypesWithoutNone);
262}
263
264template <typename Op>
265void testVectorLength(OpBuilder &b, MLIRContext &context, Location loc,
266 llvm::SmallVector<DeviceType> &dtypes) {
267 OwningOpRef<Op> op = b.create<Op>(loc, TypeRange{}, ValueRange{});
268
269 mlir::Value empty;
270 EXPECT_EQ(op->getVectorLengthValue(), empty);
271 for (auto d : dtypes)
272 EXPECT_EQ(op->getVectorLengthValue(d), empty);
273
274 OwningOpRef<arith::ConstantIndexOp> val =
275 b.create<arith::ConstantIndexOp>(location: loc, args: 1);
276 auto dtypeNvidia = DeviceTypeAttr::get(&context, DeviceType::Nvidia);
277 op->setVectorLengthDeviceTypeAttr(b.getArrayAttr(value: {dtypeNvidia}));
278 op->getVectorLengthMutable().assign(val->getResult());
279 EXPECT_EQ(op->getVectorLengthValue(), empty);
280 EXPECT_EQ(op->getVectorLengthValue(DeviceType::Nvidia), val->getResult());
281
282 op->getVectorLengthMutable().clear();
283 op->removeVectorLengthDeviceTypeAttr();
284}
285
286TEST_F(OpenACCOpsTest, vectorLengthTest) {
287 testVectorLength<ParallelOp>(b, context, loc, dtypes);
288 testVectorLength<KernelsOp>(b, context, loc, dtypes);
289}
290
291template <typename Op>
292void testWaitOnly(OpBuilder &b, MLIRContext &context, Location loc,
293 llvm::SmallVector<DeviceType> &dtypes,
294 llvm::SmallVector<DeviceType> &dtypesWithoutNone) {
295 OwningOpRef<Op> op = b.create<Op>(loc, TypeRange{}, ValueRange{});
296 EXPECT_FALSE(op->hasWaitOnly());
297 for (auto d : dtypes)
298 EXPECT_FALSE(op->hasWaitOnly(d));
299
300 auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None);
301 op->setWaitOnlyAttr(b.getArrayAttr(value: {dtypeNone}));
302 EXPECT_TRUE(op->hasWaitOnly());
303 EXPECT_TRUE(op->hasWaitOnly(DeviceType::None));
304 for (auto d : dtypesWithoutNone)
305 EXPECT_FALSE(op->hasWaitOnly(d));
306 op->removeWaitOnlyAttr();
307
308 auto dtypeHost = DeviceTypeAttr::get(&context, DeviceType::Host);
309 op->setWaitOnlyAttr(b.getArrayAttr(value: {dtypeHost}));
310 EXPECT_TRUE(op->hasWaitOnly(DeviceType::Host));
311 EXPECT_FALSE(op->hasWaitOnly());
312 op->removeWaitOnlyAttr();
313
314 auto dtypeStar = DeviceTypeAttr::get(&context, DeviceType::Star);
315 op->setWaitOnlyAttr(b.getArrayAttr(value: {dtypeHost, dtypeStar}));
316 EXPECT_TRUE(op->hasWaitOnly(DeviceType::Star));
317 EXPECT_TRUE(op->hasWaitOnly(DeviceType::Host));
318 EXPECT_FALSE(op->hasWaitOnly());
319
320 op->removeWaitOnlyAttr();
321}
322
323TEST_F(OpenACCOpsTest, waitOnlyTest) {
324 testWaitOnly<ParallelOp>(b, context, loc, dtypes, dtypesWithoutNone);
325 testWaitOnly<KernelsOp>(b, context, loc, dtypes, dtypesWithoutNone);
326 testWaitOnly<SerialOp>(b, context, loc, dtypes, dtypesWithoutNone);
327 testWaitOnly<UpdateOp>(b, context, loc, dtypes, dtypesWithoutNone);
328 testWaitOnly<DataOp>(b, context, loc, dtypes, dtypesWithoutNone);
329}
330
331template <typename Op>
332void testWaitValues(OpBuilder &b, MLIRContext &context, Location loc,
333 llvm::SmallVector<DeviceType> &dtypes,
334 llvm::SmallVector<DeviceType> &dtypesWithoutNone) {
335 OwningOpRef<Op> op = b.create<Op>(loc, TypeRange{}, ValueRange{});
336 EXPECT_EQ(op->getWaitValues().begin(), op->getWaitValues().end());
337
338 OwningOpRef<arith::ConstantIndexOp> val1 =
339 b.create<arith::ConstantIndexOp>(location: loc, args: 1);
340 OwningOpRef<arith::ConstantIndexOp> val2 =
341 b.create<arith::ConstantIndexOp>(location: loc, args: 4);
342 OwningOpRef<arith::ConstantIndexOp> val3 =
343 b.create<arith::ConstantIndexOp>(location: loc, args: 5);
344 auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None);
345 op->getWaitOperandsMutable().assign(val1->getResult());
346 op->setWaitOperandsDeviceTypeAttr(b.getArrayAttr(value: {dtypeNone}));
347 op->setWaitOperandsSegments(b.getDenseI32ArrayAttr({1}));
348 op->setHasWaitDevnumAttr(b.getBoolArrayAttr({false}));
349 EXPECT_EQ(op->getWaitValues().front(), val1->getResult());
350 for (auto d : dtypesWithoutNone)
351 EXPECT_TRUE(op->getWaitValues(d).empty());
352
353 op->getWaitOperandsMutable().clear();
354 op->removeWaitOperandsDeviceTypeAttr();
355 op->removeWaitOperandsSegmentsAttr();
356 op->removeHasWaitDevnumAttr();
357 for (auto d : dtypes)
358 EXPECT_TRUE(op->getWaitValues(d).empty());
359
360 op->getWaitOperandsMutable().append(val1->getResult());
361 op->getWaitOperandsMutable().append(val2->getResult());
362 op->setWaitOperandsDeviceTypeAttr(
363 b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Host),
364 DeviceTypeAttr::get(&context, DeviceType::Star)}));
365 op->setWaitOperandsSegments(b.getDenseI32ArrayAttr({1, 1}));
366 op->setHasWaitDevnumAttr(b.getBoolArrayAttr({false, false}));
367 EXPECT_EQ(op->getWaitValues(DeviceType::None).begin(),
368 op->getWaitValues(DeviceType::None).end());
369 EXPECT_EQ(op->getWaitValues(DeviceType::Host).front(), val1->getResult());
370 EXPECT_EQ(op->getWaitValues(DeviceType::Star).front(), val2->getResult());
371
372 op->getWaitOperandsMutable().clear();
373 op->removeWaitOperandsDeviceTypeAttr();
374 op->removeWaitOperandsSegmentsAttr();
375 op->removeHasWaitDevnumAttr();
376 for (auto d : dtypes)
377 EXPECT_TRUE(op->getWaitValues(d).empty());
378
379 op->getWaitOperandsMutable().append(val1->getResult());
380 op->getWaitOperandsMutable().append(val2->getResult());
381 op->getWaitOperandsMutable().append(val1->getResult());
382 op->setWaitOperandsDeviceTypeAttr(
383 b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Default),
384 DeviceTypeAttr::get(&context, DeviceType::Multicore)}));
385 op->setWaitOperandsSegments(b.getDenseI32ArrayAttr({2, 1}));
386 op->setHasWaitDevnumAttr(b.getBoolArrayAttr({false, false}));
387 EXPECT_EQ(op->getWaitValues(DeviceType::None).begin(),
388 op->getWaitValues(DeviceType::None).end());
389 EXPECT_EQ(op->getWaitValues(DeviceType::Default).front(), val1->getResult());
390 EXPECT_EQ(op->getWaitValues(DeviceType::Default).drop_front().front(),
391 val2->getResult());
392 EXPECT_EQ(op->getWaitValues(DeviceType::Multicore).front(),
393 val1->getResult());
394
395 op->getWaitOperandsMutable().clear();
396 op->removeWaitOperandsDeviceTypeAttr();
397 op->removeWaitOperandsSegmentsAttr();
398
399 op->getWaitOperandsMutable().append(val3->getResult());
400 op->getWaitOperandsMutable().append(val2->getResult());
401 op->getWaitOperandsMutable().append(val1->getResult());
402 op->setWaitOperandsDeviceTypeAttr(
403 b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Multicore)}));
404 op->setHasWaitDevnumAttr(b.getBoolArrayAttr({true}));
405 op->setWaitOperandsSegments(b.getDenseI32ArrayAttr({3}));
406 EXPECT_EQ(op->getWaitValues(DeviceType::None).begin(),
407 op->getWaitValues(DeviceType::None).end());
408 EXPECT_FALSE(op->getWaitDevnum());
409
410 EXPECT_EQ(op->getWaitDevnum(DeviceType::Multicore), val3->getResult());
411 EXPECT_EQ(op->getWaitValues(DeviceType::Multicore).front(),
412 val2->getResult());
413 EXPECT_EQ(op->getWaitValues(DeviceType::Multicore).drop_front().front(),
414 val1->getResult());
415
416 op->getWaitOperandsMutable().clear();
417 op->removeWaitOperandsDeviceTypeAttr();
418 op->removeWaitOperandsSegmentsAttr();
419 op->removeHasWaitDevnumAttr();
420}
421
422TEST_F(OpenACCOpsTest, waitValuesTest) {
423 testWaitValues<KernelsOp>(b, context, loc, dtypes, dtypesWithoutNone);
424 testWaitValues<ParallelOp>(b, context, loc, dtypes, dtypesWithoutNone);
425 testWaitValues<SerialOp>(b, context, loc, dtypes, dtypesWithoutNone);
426}
427
428TEST_F(OpenACCOpsTest, loopOpGangVectorWorkerTest) {
429 OwningOpRef<LoopOp> op = b.create<LoopOp>(loc, TypeRange{}, ValueRange{});
430 EXPECT_FALSE(op->hasGang());
431 EXPECT_FALSE(op->hasVector());
432 EXPECT_FALSE(op->hasWorker());
433 for (auto d : dtypes) {
434 EXPECT_FALSE(op->hasGang(d));
435 EXPECT_FALSE(op->hasVector(d));
436 EXPECT_FALSE(op->hasWorker(d));
437 }
438
439 auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None);
440 op->setGangAttr(b.getArrayAttr(value: {dtypeNone}));
441 EXPECT_TRUE(op->hasGang());
442 EXPECT_TRUE(op->hasGang(DeviceType::None));
443 for (auto d : dtypesWithoutNone)
444 EXPECT_FALSE(op->hasGang(d));
445 for (auto d : dtypes) {
446 EXPECT_FALSE(op->hasVector(d));
447 EXPECT_FALSE(op->hasWorker(d));
448 }
449 op->removeGangAttr();
450
451 op->setWorkerAttr(b.getArrayAttr(value: {dtypeNone}));
452 EXPECT_TRUE(op->hasWorker());
453 EXPECT_TRUE(op->hasWorker(DeviceType::None));
454 for (auto d : dtypesWithoutNone)
455 EXPECT_FALSE(op->hasWorker(d));
456 for (auto d : dtypes) {
457 EXPECT_FALSE(op->hasGang(d));
458 EXPECT_FALSE(op->hasVector(d));
459 }
460 op->removeWorkerAttr();
461
462 op->setVectorAttr(b.getArrayAttr(value: {dtypeNone}));
463 EXPECT_TRUE(op->hasVector());
464 EXPECT_TRUE(op->hasVector(DeviceType::None));
465 for (auto d : dtypesWithoutNone)
466 EXPECT_FALSE(op->hasVector(d));
467 for (auto d : dtypes) {
468 EXPECT_FALSE(op->hasGang(d));
469 EXPECT_FALSE(op->hasWorker(d));
470 }
471 op->removeVectorAttr();
472}
473
474TEST_F(OpenACCOpsTest, routineOpTest) {
475 OwningOpRef<RoutineOp> op =
476 b.create<RoutineOp>(loc, TypeRange{}, ValueRange{});
477
478 EXPECT_FALSE(op->hasSeq());
479 EXPECT_FALSE(op->hasVector());
480 EXPECT_FALSE(op->hasWorker());
481
482 for (auto d : dtypes) {
483 EXPECT_FALSE(op->hasSeq(d));
484 EXPECT_FALSE(op->hasVector(d));
485 EXPECT_FALSE(op->hasWorker(d));
486 }
487
488 auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None);
489 op->setSeqAttr(b.getArrayAttr(value: {dtypeNone}));
490 EXPECT_TRUE(op->hasSeq());
491 for (auto d : dtypesWithoutNone)
492 EXPECT_FALSE(op->hasSeq(d));
493 op->removeSeqAttr();
494
495 op->setVectorAttr(b.getArrayAttr(value: {dtypeNone}));
496 EXPECT_TRUE(op->hasVector());
497 for (auto d : dtypesWithoutNone)
498 EXPECT_FALSE(op->hasVector(d));
499 op->removeVectorAttr();
500
501 op->setWorkerAttr(b.getArrayAttr(value: {dtypeNone}));
502 EXPECT_TRUE(op->hasWorker());
503 for (auto d : dtypesWithoutNone)
504 EXPECT_FALSE(op->hasWorker(d));
505 op->removeWorkerAttr();
506
507 op->setGangAttr(b.getArrayAttr(value: {dtypeNone}));
508 EXPECT_TRUE(op->hasGang());
509 for (auto d : dtypesWithoutNone)
510 EXPECT_FALSE(op->hasGang(d));
511 op->removeGangAttr();
512
513 op->setGangDimDeviceTypeAttr(b.getArrayAttr(value: {dtypeNone}));
514 op->setGangDimAttr(b.getArrayAttr({b.getIntegerAttr(b.getI64Type(), 8)}));
515 EXPECT_TRUE(op->getGangDimValue().has_value());
516 EXPECT_EQ(op->getGangDimValue().value(), 8);
517 for (auto d : dtypesWithoutNone)
518 EXPECT_FALSE(op->getGangDimValue(d).has_value());
519 op->removeGangDimDeviceTypeAttr();
520 op->removeGangDimAttr();
521
522 op->setBindNameDeviceTypeAttr(b.getArrayAttr(value: {dtypeNone}));
523 op->setBindNameAttr(b.getArrayAttr({b.getStringAttr("fname")}));
524 EXPECT_TRUE(op->getBindNameValue().has_value());
525 EXPECT_EQ(op->getBindNameValue().value(), "fname");
526 for (auto d : dtypesWithoutNone)
527 EXPECT_FALSE(op->getBindNameValue(d).has_value());
528 op->removeBindNameDeviceTypeAttr();
529 op->removeBindNameAttr();
530}
531
532template <typename Op>
533void testShortDataEntryOpBuilders(OpBuilder &b, MLIRContext &context,
534 Location loc, DataClause dataClause) {
535 auto memrefTy = MemRefType::get({}, b.getI32Type());
536 OwningOpRef<memref::AllocaOp> varPtrOp =
537 b.create<memref::AllocaOp>(loc, memrefTy);
538
539 TypedValue<PointerLikeType> varPtr =
540 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());
541 OwningOpRef<Op> op = b.create<Op>(loc, varPtr,
542 /*structured=*/true, /*implicit=*/true);
543
544 EXPECT_EQ(op->getVarPtr(), varPtr);
545 EXPECT_EQ(op->getType(), memrefTy);
546 EXPECT_EQ(op->getDataClause(), dataClause);
547 EXPECT_TRUE(op->getImplicit());
548 EXPECT_TRUE(op->getStructured());
549 EXPECT_TRUE(op->getBounds().empty());
550 EXPECT_FALSE(op->getVarPtrPtr());
551
552 OwningOpRef<Op> op2 = b.create<Op>(loc, varPtr,
553 /*structured=*/false, /*implicit=*/false);
554 EXPECT_FALSE(op2->getImplicit());
555 EXPECT_FALSE(op2->getStructured());
556
557 OwningOpRef<arith::ConstantIndexOp> extent =
558 b.create<arith::ConstantIndexOp>(location: loc, args: 1);
559 OwningOpRef<DataBoundsOp> bounds =
560 b.create<DataBoundsOp>(loc, extent->getResult());
561 OwningOpRef<Op> opWithBounds =
562 b.create<Op>(loc, varPtr,
563 /*structured=*/true, /*implicit=*/true, bounds->getResult());
564 EXPECT_FALSE(opWithBounds->getBounds().empty());
565 EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult());
566
567 OwningOpRef<Op> opWithName =
568 b.create<Op>(loc, varPtr,
569 /*structured=*/true, /*implicit=*/true, "varName");
570 EXPECT_EQ(opWithName->getNameAttr().str(), "varName");
571}
572
573TEST_F(OpenACCOpsTest, shortDataEntryOpBuilder) {
574 testShortDataEntryOpBuilders<PrivateOp>(b, context, loc,
575 DataClause::acc_private);
576 testShortDataEntryOpBuilders<FirstprivateOp>(b, context, loc,
577 DataClause::acc_firstprivate);
578 testShortDataEntryOpBuilders<ReductionOp>(b, context, loc,
579 DataClause::acc_reduction);
580 testShortDataEntryOpBuilders<DevicePtrOp>(b, context, loc,
581 DataClause::acc_deviceptr);
582 testShortDataEntryOpBuilders<PresentOp>(b, context, loc,
583 DataClause::acc_present);
584 testShortDataEntryOpBuilders<CopyinOp>(b, context, loc,
585 DataClause::acc_copyin);
586 testShortDataEntryOpBuilders<CreateOp>(b, context, loc,
587 DataClause::acc_create);
588 testShortDataEntryOpBuilders<NoCreateOp>(b, context, loc,
589 DataClause::acc_no_create);
590 testShortDataEntryOpBuilders<AttachOp>(b, context, loc,
591 DataClause::acc_attach);
592 testShortDataEntryOpBuilders<GetDevicePtrOp>(b, context, loc,
593 DataClause::acc_getdeviceptr);
594 testShortDataEntryOpBuilders<UpdateDeviceOp>(b, context, loc,
595 DataClause::acc_update_device);
596 testShortDataEntryOpBuilders<UseDeviceOp>(b, context, loc,
597 DataClause::acc_use_device);
598 testShortDataEntryOpBuilders<DeclareDeviceResidentOp>(
599 b, context, loc, DataClause::acc_declare_device_resident);
600 testShortDataEntryOpBuilders<DeclareLinkOp>(b, context, loc,
601 DataClause::acc_declare_link);
602 testShortDataEntryOpBuilders<CacheOp>(b, context, loc, DataClause::acc_cache);
603}
604
605template <typename Op>
606void testShortDataExitOpBuilders(OpBuilder &b, MLIRContext &context,
607 Location loc, DataClause dataClause) {
608 auto memrefTy = MemRefType::get({}, b.getI32Type());
609 OwningOpRef<memref::AllocaOp> varPtrOp =
610 b.create<memref::AllocaOp>(loc, memrefTy);
611 TypedValue<PointerLikeType> varPtr =
612 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());
613
614 OwningOpRef<GetDevicePtrOp> accPtrOp = b.create<GetDevicePtrOp>(
615 loc, varPtr, /*structured=*/true, /*implicit=*/true);
616 TypedValue<PointerLikeType> accPtr =
617 cast<TypedValue<PointerLikeType>>(accPtrOp->getResult());
618
619 OwningOpRef<Op> op = b.create<Op>(loc, accPtr, varPtr,
620 /*structured=*/true, /*implicit=*/true);
621
622 EXPECT_EQ(op->getVarPtr(), varPtr);
623 EXPECT_EQ(op->getAccPtr(), accPtr);
624 EXPECT_EQ(op->getDataClause(), dataClause);
625 EXPECT_TRUE(op->getImplicit());
626 EXPECT_TRUE(op->getStructured());
627 EXPECT_TRUE(op->getBounds().empty());
628
629 OwningOpRef<Op> op2 = b.create<Op>(loc, accPtr, varPtr,
630 /*structured=*/false, /*implicit=*/false);
631 EXPECT_FALSE(op2->getImplicit());
632 EXPECT_FALSE(op2->getStructured());
633
634 OwningOpRef<arith::ConstantIndexOp> extent =
635 b.create<arith::ConstantIndexOp>(location: loc, args: 1);
636 OwningOpRef<DataBoundsOp> bounds =
637 b.create<DataBoundsOp>(loc, extent->getResult());
638 OwningOpRef<Op> opWithBounds =
639 b.create<Op>(loc, accPtr, varPtr,
640 /*structured=*/true, /*implicit=*/true, bounds->getResult());
641 EXPECT_FALSE(opWithBounds->getBounds().empty());
642 EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult());
643
644 OwningOpRef<Op> opWithName =
645 b.create<Op>(loc, accPtr, varPtr,
646 /*structured=*/true, /*implicit=*/true, "varName");
647 EXPECT_EQ(opWithName->getNameAttr().str(), "varName");
648}
649
650TEST_F(OpenACCOpsTest, shortDataExitOpBuilder) {
651 testShortDataExitOpBuilders<CopyoutOp>(b, context, loc,
652 DataClause::acc_copyout);
653 testShortDataExitOpBuilders<UpdateHostOp>(b, context, loc,
654 DataClause::acc_update_host);
655}
656
657template <typename Op>
658void testShortDataExitNoVarPtrOpBuilders(OpBuilder &b, MLIRContext &context,
659 Location loc, DataClause dataClause) {
660 auto memrefTy = MemRefType::get({}, b.getI32Type());
661 OwningOpRef<memref::AllocaOp> varPtrOp =
662 b.create<memref::AllocaOp>(loc, memrefTy);
663 TypedValue<PointerLikeType> varPtr =
664 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());
665
666 OwningOpRef<GetDevicePtrOp> accPtrOp = b.create<GetDevicePtrOp>(
667 loc, varPtr, /*structured=*/true, /*implicit=*/true);
668 TypedValue<PointerLikeType> accPtr =
669 cast<TypedValue<PointerLikeType>>(accPtrOp->getResult());
670
671 OwningOpRef<Op> op = b.create<Op>(loc, accPtr,
672 /*structured=*/true, /*implicit=*/true);
673
674 EXPECT_EQ(op->getAccPtr(), accPtr);
675 EXPECT_EQ(op->getDataClause(), dataClause);
676 EXPECT_TRUE(op->getImplicit());
677 EXPECT_TRUE(op->getStructured());
678 EXPECT_TRUE(op->getBounds().empty());
679
680 OwningOpRef<Op> op2 = b.create<Op>(loc, accPtr,
681 /*structured=*/false, /*implicit=*/false);
682 EXPECT_FALSE(op2->getImplicit());
683 EXPECT_FALSE(op2->getStructured());
684
685 OwningOpRef<arith::ConstantIndexOp> extent =
686 b.create<arith::ConstantIndexOp>(location: loc, args: 1);
687 OwningOpRef<DataBoundsOp> bounds =
688 b.create<DataBoundsOp>(loc, extent->getResult());
689 OwningOpRef<Op> opWithBounds =
690 b.create<Op>(loc, accPtr,
691 /*structured=*/true, /*implicit=*/true, bounds->getResult());
692 EXPECT_FALSE(opWithBounds->getBounds().empty());
693 EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult());
694
695 OwningOpRef<Op> opWithName =
696 b.create<Op>(loc, accPtr,
697 /*structured=*/true, /*implicit=*/true, "varName");
698 EXPECT_EQ(opWithName->getNameAttr().str(), "varName");
699}
700
701TEST_F(OpenACCOpsTest, shortDataExitOpNoVarPtrBuilder) {
702 testShortDataExitNoVarPtrOpBuilders<DeleteOp>(b, context, loc,
703 DataClause::acc_delete);
704 testShortDataExitNoVarPtrOpBuilders<DetachOp>(b, context, loc,
705 DataClause::acc_detach);
706}
707
708template <typename Op>
709void testShortDataEntryOpBuildersMappableVar(OpBuilder &b, MLIRContext &context,
710 Location loc,
711 DataClause dataClause) {
712 auto int64Ty = b.getI64Type();
713 auto memrefTy = MemRefType::get({}, int64Ty);
714 OwningOpRef<memref::AllocaOp> varPtrOp =
715 b.create<memref::AllocaOp>(loc, memrefTy);
716 SmallVector<Value> indices;
717 OwningOpRef<memref::LoadOp> loadVarOp =
718 b.create<memref::LoadOp>(loc, int64Ty, varPtrOp->getResult(), indices);
719
720 EXPECT_TRUE(isMappableType(loadVarOp->getResult().getType()));
721 TypedValue<MappableType> var =
722 cast<TypedValue<MappableType>>(loadVarOp->getResult());
723 OwningOpRef<Op> op = b.create<Op>(loc, var,
724 /*structured=*/true, /*implicit=*/true);
725
726 EXPECT_EQ(op->getVar(), var);
727 EXPECT_EQ(op->getVarPtr(), nullptr);
728 EXPECT_EQ(op->getType(), int64Ty);
729 EXPECT_EQ(op->getVarType(), int64Ty);
730 EXPECT_EQ(op->getDataClause(), dataClause);
731 EXPECT_TRUE(op->getImplicit());
732 EXPECT_TRUE(op->getStructured());
733 EXPECT_TRUE(op->getBounds().empty());
734 EXPECT_FALSE(op->getVarPtrPtr());
735}
736
737struct IntegerOpenACCMappableModel
738 : public mlir::acc::MappableType::ExternalModel<IntegerOpenACCMappableModel,
739 IntegerType> {};
740
741TEST_F(OpenACCOpsTest, mappableTypeBuilderDataEntry) {
742 // First, set up the test by attaching MappableInterface to IntegerType.
743 IntegerType i64ty = IntegerType::get(&context, 8);
744 ASSERT_FALSE(isMappableType(i64ty));
745 IntegerType::attachInterface<IntegerOpenACCMappableModel>(context);
746 ASSERT_TRUE(isMappableType(i64ty));
747
748 testShortDataEntryOpBuildersMappableVar<PrivateOp>(b, context, loc,
749 DataClause::acc_private);
750 testShortDataEntryOpBuildersMappableVar<FirstprivateOp>(
751 b, context, loc, DataClause::acc_firstprivate);
752 testShortDataEntryOpBuildersMappableVar<ReductionOp>(
753 b, context, loc, DataClause::acc_reduction);
754 testShortDataEntryOpBuildersMappableVar<DevicePtrOp>(
755 b, context, loc, DataClause::acc_deviceptr);
756 testShortDataEntryOpBuildersMappableVar<PresentOp>(b, context, loc,
757 DataClause::acc_present);
758 testShortDataEntryOpBuildersMappableVar<CopyinOp>(b, context, loc,
759 DataClause::acc_copyin);
760 testShortDataEntryOpBuildersMappableVar<CreateOp>(b, context, loc,
761 DataClause::acc_create);
762 testShortDataEntryOpBuildersMappableVar<NoCreateOp>(
763 b, context, loc, DataClause::acc_no_create);
764 testShortDataEntryOpBuildersMappableVar<AttachOp>(b, context, loc,
765 DataClause::acc_attach);
766 testShortDataEntryOpBuildersMappableVar<GetDevicePtrOp>(
767 b, context, loc, DataClause::acc_getdeviceptr);
768 testShortDataEntryOpBuildersMappableVar<UpdateDeviceOp>(
769 b, context, loc, DataClause::acc_update_device);
770 testShortDataEntryOpBuildersMappableVar<UseDeviceOp>(
771 b, context, loc, DataClause::acc_use_device);
772 testShortDataEntryOpBuildersMappableVar<DeclareDeviceResidentOp>(
773 b, context, loc, DataClause::acc_declare_device_resident);
774 testShortDataEntryOpBuildersMappableVar<DeclareLinkOp>(
775 b, context, loc, DataClause::acc_declare_link);
776 testShortDataEntryOpBuildersMappableVar<CacheOp>(b, context, loc,
777 DataClause::acc_cache);
778}
779

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp