brintos

brintos / llvm-project-archived public Read only

0
0
Text · 33.5 KiB · d6203b9 Raw
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