811 lines · cpp
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-exception6//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 Fixture24//===----------------------------------------------------------------------===//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 = Op::create(b, 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({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({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({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 memref::AllocaOp::create(b, loc, memrefTy);86 87 TypedValue<PointerLikeType> varPtr =88 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());89 OwningOpRef<Op> op = Op::create(b, 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({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({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({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 = Op::create(b, 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 arith::ConstantIndexOp::create(b, loc, 1);140 auto dtypeNvidia = DeviceTypeAttr::get(&context, DeviceType::Nvidia);141 op->setAsyncOperandsDeviceTypeAttr(b.getArrayAttr({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 memref::AllocaOp::create(b, loc, memrefTy);162 163 TypedValue<PointerLikeType> varPtr =164 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());165 OwningOpRef<Op> op = Op::create(b, 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 arith::ConstantIndexOp::create(b, loc, 1);175 auto dtypeNvidia = DeviceTypeAttr::get(&context, DeviceType::Nvidia);176 op->setAsyncOperandsDeviceTypeAttr(b.getArrayAttr({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 = Op::create(b, loc, TypeRange{}, ValueRange{});201 EXPECT_EQ(op->getNumGangsValues().begin(), op->getNumGangsValues().end());202 203 OwningOpRef<arith::ConstantIndexOp> val1 =204 arith::ConstantIndexOp::create(b, loc, 1);205 OwningOpRef<arith::ConstantIndexOp> val2 =206 arith::ConstantIndexOp::create(b, loc, 4);207 auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None);208 op->getNumGangsMutable().assign(val1->getResult());209 op->setNumGangsDeviceTypeAttr(b.getArrayAttr({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 = Op::create(b, 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 arith::ConstantIndexOp::create(b, loc, 1);276 auto dtypeNvidia = DeviceTypeAttr::get(&context, DeviceType::Nvidia);277 op->setVectorLengthDeviceTypeAttr(b.getArrayAttr({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 = Op::create(b, 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({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({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({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 = Op::create(b, loc, TypeRange{}, ValueRange{});336 EXPECT_EQ(op->getWaitValues().begin(), op->getWaitValues().end());337 338 OwningOpRef<arith::ConstantIndexOp> val1 =339 arith::ConstantIndexOp::create(b, loc, 1);340 OwningOpRef<arith::ConstantIndexOp> val2 =341 arith::ConstantIndexOp::create(b, loc, 4);342 OwningOpRef<arith::ConstantIndexOp> val3 =343 arith::ConstantIndexOp::create(b, loc, 5);344 auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None);345 op->getWaitOperandsMutable().assign(val1->getResult());346 op->setWaitOperandsDeviceTypeAttr(b.getArrayAttr({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 = LoopOp::create(b, 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({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({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({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 RoutineOp::create(b, 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({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({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({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({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({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->setBindIdNameDeviceTypeAttr(523 b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Host)}));524 op->setBindStrNameDeviceTypeAttr(b.getArrayAttr({dtypeNone}));525 op->setBindIdNameAttr(526 b.getArrayAttr({SymbolRefAttr::get(&context, "test_symbol")}));527 op->setBindStrNameAttr(b.getArrayAttr({b.getStringAttr("fname")}));528 EXPECT_TRUE(op->getBindNameValue().has_value());529 EXPECT_TRUE(op->getBindNameValue(DeviceType::Host).has_value());530 EXPECT_EQ(std::visit(531 [](const auto &attr) -> std::string {532 if constexpr (std::is_same_v<std::decay_t<decltype(attr)>,533 mlir::StringAttr>) {534 return attr.str();535 } else {536 return attr.getLeafReference().str();537 }538 },539 op->getBindNameValue().value()),540 "fname");541 EXPECT_EQ(std::visit(542 [](const auto &attr) -> std::string {543 if constexpr (std::is_same_v<std::decay_t<decltype(attr)>,544 mlir::StringAttr>) {545 return attr.str();546 } else {547 return attr.getLeafReference().str();548 }549 },550 op->getBindNameValue(DeviceType::Host).value()),551 "test_symbol");552 for (auto d : dtypesWithoutNone) {553 if (d != DeviceType::Host)554 EXPECT_FALSE(op->getBindNameValue(d).has_value());555 }556 op->removeBindIdNameDeviceTypeAttr();557 op->removeBindStrNameDeviceTypeAttr();558 op->removeBindIdNameAttr();559 op->removeBindStrNameAttr();560}561 562template <typename Op>563void testShortDataEntryOpBuilders(OpBuilder &b, MLIRContext &context,564 Location loc, DataClause dataClause) {565 auto memrefTy = MemRefType::get({}, b.getI32Type());566 OwningOpRef<memref::AllocaOp> varPtrOp =567 memref::AllocaOp::create(b, loc, memrefTy);568 569 TypedValue<PointerLikeType> varPtr =570 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());571 OwningOpRef<Op> op = Op::create(b, loc, varPtr,572 /*structured=*/true, /*implicit=*/true);573 574 EXPECT_EQ(op->getVarPtr(), varPtr);575 EXPECT_EQ(op->getType(), memrefTy);576 EXPECT_EQ(op->getDataClause(), dataClause);577 EXPECT_TRUE(op->getImplicit());578 EXPECT_TRUE(op->getStructured());579 EXPECT_TRUE(op->getBounds().empty());580 EXPECT_FALSE(op->getVarPtrPtr());581 582 OwningOpRef<Op> op2 = Op::create(b, loc, varPtr,583 /*structured=*/false, /*implicit=*/false);584 EXPECT_FALSE(op2->getImplicit());585 EXPECT_FALSE(op2->getStructured());586 587 OwningOpRef<arith::ConstantIndexOp> extent =588 arith::ConstantIndexOp::create(b, loc, 1);589 OwningOpRef<DataBoundsOp> bounds =590 DataBoundsOp::create(b, loc, extent->getResult());591 OwningOpRef<Op> opWithBounds =592 Op::create(b, loc, varPtr,593 /*structured=*/true, /*implicit=*/true, bounds->getResult());594 EXPECT_FALSE(opWithBounds->getBounds().empty());595 EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult());596 597 OwningOpRef<Op> opWithName =598 Op::create(b, loc, varPtr,599 /*structured=*/true, /*implicit=*/true, "varName");600 EXPECT_EQ(opWithName->getNameAttr().str(), "varName");601}602 603TEST_F(OpenACCOpsTest, shortDataEntryOpBuilder) {604 testShortDataEntryOpBuilders<PrivateOp>(b, context, loc,605 DataClause::acc_private);606 testShortDataEntryOpBuilders<FirstprivateOp>(b, context, loc,607 DataClause::acc_firstprivate);608 testShortDataEntryOpBuilders<ReductionOp>(b, context, loc,609 DataClause::acc_reduction);610 testShortDataEntryOpBuilders<DevicePtrOp>(b, context, loc,611 DataClause::acc_deviceptr);612 testShortDataEntryOpBuilders<PresentOp>(b, context, loc,613 DataClause::acc_present);614 testShortDataEntryOpBuilders<CopyinOp>(b, context, loc,615 DataClause::acc_copyin);616 testShortDataEntryOpBuilders<CreateOp>(b, context, loc,617 DataClause::acc_create);618 testShortDataEntryOpBuilders<NoCreateOp>(b, context, loc,619 DataClause::acc_no_create);620 testShortDataEntryOpBuilders<AttachOp>(b, context, loc,621 DataClause::acc_attach);622 testShortDataEntryOpBuilders<GetDevicePtrOp>(b, context, loc,623 DataClause::acc_getdeviceptr);624 testShortDataEntryOpBuilders<UpdateDeviceOp>(b, context, loc,625 DataClause::acc_update_device);626 testShortDataEntryOpBuilders<UseDeviceOp>(b, context, loc,627 DataClause::acc_use_device);628 testShortDataEntryOpBuilders<DeclareDeviceResidentOp>(629 b, context, loc, DataClause::acc_declare_device_resident);630 testShortDataEntryOpBuilders<DeclareLinkOp>(b, context, loc,631 DataClause::acc_declare_link);632 testShortDataEntryOpBuilders<CacheOp>(b, context, loc, DataClause::acc_cache);633}634 635template <typename Op>636void testShortDataExitOpBuilders(OpBuilder &b, MLIRContext &context,637 Location loc, DataClause dataClause) {638 auto memrefTy = MemRefType::get({}, b.getI32Type());639 OwningOpRef<memref::AllocaOp> varPtrOp =640 memref::AllocaOp::create(b, loc, memrefTy);641 TypedValue<PointerLikeType> varPtr =642 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());643 644 OwningOpRef<GetDevicePtrOp> accPtrOp = GetDevicePtrOp::create(645 b, loc, varPtr, /*structured=*/true, /*implicit=*/true);646 TypedValue<PointerLikeType> accPtr =647 cast<TypedValue<PointerLikeType>>(accPtrOp->getResult());648 649 OwningOpRef<Op> op = Op::create(b, loc, accPtr, varPtr,650 /*structured=*/true, /*implicit=*/true);651 652 EXPECT_EQ(op->getVarPtr(), varPtr);653 EXPECT_EQ(op->getAccPtr(), accPtr);654 EXPECT_EQ(op->getDataClause(), dataClause);655 EXPECT_TRUE(op->getImplicit());656 EXPECT_TRUE(op->getStructured());657 EXPECT_TRUE(op->getBounds().empty());658 659 OwningOpRef<Op> op2 = Op::create(b, loc, accPtr, varPtr,660 /*structured=*/false, /*implicit=*/false);661 EXPECT_FALSE(op2->getImplicit());662 EXPECT_FALSE(op2->getStructured());663 664 OwningOpRef<arith::ConstantIndexOp> extent =665 arith::ConstantIndexOp::create(b, loc, 1);666 OwningOpRef<DataBoundsOp> bounds =667 DataBoundsOp::create(b, loc, extent->getResult());668 OwningOpRef<Op> opWithBounds =669 Op::create(b, loc, accPtr, varPtr,670 /*structured=*/true, /*implicit=*/true, bounds->getResult());671 EXPECT_FALSE(opWithBounds->getBounds().empty());672 EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult());673 674 OwningOpRef<Op> opWithName =675 Op::create(b, loc, accPtr, varPtr,676 /*structured=*/true, /*implicit=*/true, "varName");677 EXPECT_EQ(opWithName->getNameAttr().str(), "varName");678}679 680TEST_F(OpenACCOpsTest, shortDataExitOpBuilder) {681 testShortDataExitOpBuilders<CopyoutOp>(b, context, loc,682 DataClause::acc_copyout);683 testShortDataExitOpBuilders<UpdateHostOp>(b, context, loc,684 DataClause::acc_update_host);685}686 687template <typename Op>688void testShortDataExitNoVarPtrOpBuilders(OpBuilder &b, MLIRContext &context,689 Location loc, DataClause dataClause) {690 auto memrefTy = MemRefType::get({}, b.getI32Type());691 OwningOpRef<memref::AllocaOp> varPtrOp =692 memref::AllocaOp::create(b, loc, memrefTy);693 TypedValue<PointerLikeType> varPtr =694 cast<TypedValue<PointerLikeType>>(varPtrOp->getResult());695 696 OwningOpRef<GetDevicePtrOp> accPtrOp = GetDevicePtrOp::create(697 b, loc, varPtr, /*structured=*/true, /*implicit=*/true);698 TypedValue<PointerLikeType> accPtr =699 cast<TypedValue<PointerLikeType>>(accPtrOp->getResult());700 701 OwningOpRef<Op> op = Op::create(b, loc, accPtr,702 /*structured=*/true, /*implicit=*/true);703 704 EXPECT_EQ(op->getAccPtr(), accPtr);705 EXPECT_EQ(op->getDataClause(), dataClause);706 EXPECT_TRUE(op->getImplicit());707 EXPECT_TRUE(op->getStructured());708 EXPECT_TRUE(op->getBounds().empty());709 710 OwningOpRef<Op> op2 = Op::create(b, loc, accPtr,711 /*structured=*/false, /*implicit=*/false);712 EXPECT_FALSE(op2->getImplicit());713 EXPECT_FALSE(op2->getStructured());714 715 OwningOpRef<arith::ConstantIndexOp> extent =716 arith::ConstantIndexOp::create(b, loc, 1);717 OwningOpRef<DataBoundsOp> bounds =718 DataBoundsOp::create(b, loc, extent->getResult());719 OwningOpRef<Op> opWithBounds =720 Op::create(b, loc, accPtr,721 /*structured=*/true, /*implicit=*/true, bounds->getResult());722 EXPECT_FALSE(opWithBounds->getBounds().empty());723 EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult());724 725 OwningOpRef<Op> opWithName =726 Op::create(b, loc, accPtr,727 /*structured=*/true, /*implicit=*/true, "varName");728 EXPECT_EQ(opWithName->getNameAttr().str(), "varName");729}730 731TEST_F(OpenACCOpsTest, shortDataExitOpNoVarPtrBuilder) {732 testShortDataExitNoVarPtrOpBuilders<DeleteOp>(b, context, loc,733 DataClause::acc_delete);734 testShortDataExitNoVarPtrOpBuilders<DetachOp>(b, context, loc,735 DataClause::acc_detach);736}737 738template <typename Op>739void testShortDataEntryOpBuildersMappableVar(OpBuilder &b, MLIRContext &context,740 Location loc,741 DataClause dataClause) {742 auto int64Ty = b.getI64Type();743 auto memrefTy = MemRefType::get({}, int64Ty);744 OwningOpRef<memref::AllocaOp> varPtrOp =745 memref::AllocaOp::create(b, loc, memrefTy);746 SmallVector<Value> indices;747 OwningOpRef<memref::LoadOp> loadVarOp =748 memref::LoadOp::create(b, loc, int64Ty, varPtrOp->getResult(), indices);749 750 EXPECT_TRUE(isMappableType(loadVarOp->getResult().getType()));751 TypedValue<MappableType> var =752 cast<TypedValue<MappableType>>(loadVarOp->getResult());753 OwningOpRef<Op> op = Op::create(b, loc, var,754 /*structured=*/true, /*implicit=*/true);755 756 EXPECT_EQ(op->getVar(), var);757 EXPECT_EQ(op->getVarPtr(), nullptr);758 EXPECT_EQ(op->getType(), int64Ty);759 EXPECT_EQ(op->getVarType(), int64Ty);760 EXPECT_EQ(op->getDataClause(), dataClause);761 EXPECT_TRUE(op->getImplicit());762 EXPECT_TRUE(op->getStructured());763 EXPECT_TRUE(op->getBounds().empty());764 EXPECT_FALSE(op->getVarPtrPtr());765}766 767struct IntegerOpenACCMappableModel768 : public mlir::acc::MappableType::ExternalModel<IntegerOpenACCMappableModel,769 IntegerType> {770 bool hasUnknownDimensions(mlir::Type type) const { return false; }771};772 773TEST_F(OpenACCOpsTest, mappableTypeBuilderDataEntry) {774 // First, set up the test by attaching MappableInterface to IntegerType.775 IntegerType i64ty = IntegerType::get(&context, 8);776 ASSERT_FALSE(isMappableType(i64ty));777 IntegerType::attachInterface<IntegerOpenACCMappableModel>(context);778 ASSERT_TRUE(isMappableType(i64ty));779 780 testShortDataEntryOpBuildersMappableVar<PrivateOp>(b, context, loc,781 DataClause::acc_private);782 testShortDataEntryOpBuildersMappableVar<FirstprivateOp>(783 b, context, loc, DataClause::acc_firstprivate);784 testShortDataEntryOpBuildersMappableVar<ReductionOp>(785 b, context, loc, DataClause::acc_reduction);786 testShortDataEntryOpBuildersMappableVar<DevicePtrOp>(787 b, context, loc, DataClause::acc_deviceptr);788 testShortDataEntryOpBuildersMappableVar<PresentOp>(b, context, loc,789 DataClause::acc_present);790 testShortDataEntryOpBuildersMappableVar<CopyinOp>(b, context, loc,791 DataClause::acc_copyin);792 testShortDataEntryOpBuildersMappableVar<CreateOp>(b, context, loc,793 DataClause::acc_create);794 testShortDataEntryOpBuildersMappableVar<NoCreateOp>(795 b, context, loc, DataClause::acc_no_create);796 testShortDataEntryOpBuildersMappableVar<AttachOp>(b, context, loc,797 DataClause::acc_attach);798 testShortDataEntryOpBuildersMappableVar<GetDevicePtrOp>(799 b, context, loc, DataClause::acc_getdeviceptr);800 testShortDataEntryOpBuildersMappableVar<UpdateDeviceOp>(801 b, context, loc, DataClause::acc_update_device);802 testShortDataEntryOpBuildersMappableVar<UseDeviceOp>(803 b, context, loc, DataClause::acc_use_device);804 testShortDataEntryOpBuildersMappableVar<DeclareDeviceResidentOp>(805 b, context, loc, DataClause::acc_declare_device_resident);806 testShortDataEntryOpBuildersMappableVar<DeclareLinkOp>(807 b, context, loc, DataClause::acc_declare_link);808 testShortDataEntryOpBuildersMappableVar<CacheOp>(b, context, loc,809 DataClause::acc_cache);810}811