//===- OpenACCOpsTest.cpp - Unit tests for OpenACC ops --------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Diagnostics.h" #include "mlir/IR/MLIRContext.h" #include "mlir/IR/OwningOpRef.h" #include "mlir/IR/Value.h" #include "gtest/gtest.h" using namespace mlir; using namespace mlir::acc; //===----------------------------------------------------------------------===// // Test Fixture //===----------------------------------------------------------------------===// class OpenACCOpsTest : public ::testing::Test { protected: OpenACCOpsTest() : b(&context), loc(UnknownLoc::get(&context)) { context.loadDialect(); } MLIRContext context; OpBuilder b; Location loc; llvm::SmallVector dtypes = { DeviceType::None, DeviceType::Star, DeviceType::Multicore, DeviceType::Default, DeviceType::Host, DeviceType::Nvidia, DeviceType::Radeon}; llvm::SmallVector dtypesWithoutNone = { DeviceType::Star, DeviceType::Multicore, DeviceType::Default, DeviceType::Host, DeviceType::Nvidia, DeviceType::Radeon}; }; template void testAsyncOnly(OpBuilder &b, MLIRContext &context, Location loc, llvm::SmallVector &dtypes) { OwningOpRef op = Op::create(b, loc, TypeRange{}, ValueRange{}); EXPECT_FALSE(op->hasAsyncOnly()); for (auto d : dtypes) EXPECT_FALSE(op->hasAsyncOnly(d)); auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None); op->setAsyncOnlyAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasAsyncOnly()); EXPECT_TRUE(op->hasAsyncOnly(DeviceType::None)); op->removeAsyncOnlyAttr(); auto dtypeHost = DeviceTypeAttr::get(&context, DeviceType::Host); op->setAsyncOnlyAttr(b.getArrayAttr({dtypeHost})); EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Host)); EXPECT_FALSE(op->hasAsyncOnly()); op->removeAsyncOnlyAttr(); auto dtypeStar = DeviceTypeAttr::get(&context, DeviceType::Star); op->setAsyncOnlyAttr(b.getArrayAttr({dtypeHost, dtypeStar})); EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Star)); EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Host)); EXPECT_FALSE(op->hasAsyncOnly()); op->removeAsyncOnlyAttr(); } TEST_F(OpenACCOpsTest, asyncOnlyTest) { testAsyncOnly(b, context, loc, dtypes); testAsyncOnly(b, context, loc, dtypes); testAsyncOnly(b, context, loc, dtypes); } template void testAsyncOnlyDataEntry(OpBuilder &b, MLIRContext &context, Location loc, llvm::SmallVector &dtypes) { auto memrefTy = MemRefType::get({}, b.getI32Type()); OwningOpRef varPtrOp = memref::AllocaOp::create(b, loc, memrefTy); TypedValue varPtr = cast>(varPtrOp->getResult()); OwningOpRef op = Op::create(b, loc, varPtr, /*structured=*/true, /*implicit=*/true); EXPECT_FALSE(op->hasAsyncOnly()); for (auto d : dtypes) EXPECT_FALSE(op->hasAsyncOnly(d)); auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None); op->setAsyncOnlyAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasAsyncOnly()); EXPECT_TRUE(op->hasAsyncOnly(DeviceType::None)); op->removeAsyncOnlyAttr(); auto dtypeHost = DeviceTypeAttr::get(&context, DeviceType::Host); op->setAsyncOnlyAttr(b.getArrayAttr({dtypeHost})); EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Host)); EXPECT_FALSE(op->hasAsyncOnly()); op->removeAsyncOnlyAttr(); auto dtypeStar = DeviceTypeAttr::get(&context, DeviceType::Star); op->setAsyncOnlyAttr(b.getArrayAttr({dtypeHost, dtypeStar})); EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Star)); EXPECT_TRUE(op->hasAsyncOnly(DeviceType::Host)); EXPECT_FALSE(op->hasAsyncOnly()); op->removeAsyncOnlyAttr(); } TEST_F(OpenACCOpsTest, asyncOnlyTestDataEntry) { testAsyncOnlyDataEntry(b, context, loc, dtypes); testAsyncOnlyDataEntry(b, context, loc, dtypes); testAsyncOnlyDataEntry(b, context, loc, dtypes); testAsyncOnlyDataEntry(b, context, loc, dtypes); testAsyncOnlyDataEntry(b, context, loc, dtypes); testAsyncOnlyDataEntry(b, context, loc, dtypes); testAsyncOnlyDataEntry(b, context, loc, dtypes); testAsyncOnlyDataEntry(b, context, loc, dtypes); } template void testAsyncValue(OpBuilder &b, MLIRContext &context, Location loc, llvm::SmallVector &dtypes) { OwningOpRef op = Op::create(b, loc, TypeRange{}, ValueRange{}); mlir::Value empty; EXPECT_EQ(op->getAsyncValue(), empty); for (auto d : dtypes) EXPECT_EQ(op->getAsyncValue(d), empty); OwningOpRef val = arith::ConstantIndexOp::create(b, loc, 1); auto dtypeNvidia = DeviceTypeAttr::get(&context, DeviceType::Nvidia); op->setAsyncOperandsDeviceTypeAttr(b.getArrayAttr({dtypeNvidia})); op->getAsyncOperandsMutable().assign(val->getResult()); EXPECT_EQ(op->getAsyncValue(), empty); EXPECT_EQ(op->getAsyncValue(DeviceType::Nvidia), val->getResult()); op->getAsyncOperandsMutable().clear(); op->removeAsyncOperandsDeviceTypeAttr(); } TEST_F(OpenACCOpsTest, asyncValueTest) { testAsyncValue(b, context, loc, dtypes); testAsyncValue(b, context, loc, dtypes); testAsyncValue(b, context, loc, dtypes); } template void testAsyncValueDataEntry(OpBuilder &b, MLIRContext &context, Location loc, llvm::SmallVector &dtypes) { auto memrefTy = MemRefType::get({}, b.getI32Type()); OwningOpRef varPtrOp = memref::AllocaOp::create(b, loc, memrefTy); TypedValue varPtr = cast>(varPtrOp->getResult()); OwningOpRef op = Op::create(b, loc, varPtr, /*structured=*/true, /*implicit=*/true); mlir::Value empty; EXPECT_EQ(op->getAsyncValue(), empty); for (auto d : dtypes) EXPECT_EQ(op->getAsyncValue(d), empty); OwningOpRef val = arith::ConstantIndexOp::create(b, loc, 1); auto dtypeNvidia = DeviceTypeAttr::get(&context, DeviceType::Nvidia); op->setAsyncOperandsDeviceTypeAttr(b.getArrayAttr({dtypeNvidia})); op->getAsyncOperandsMutable().assign(val->getResult()); EXPECT_EQ(op->getAsyncValue(), empty); EXPECT_EQ(op->getAsyncValue(DeviceType::Nvidia), val->getResult()); op->getAsyncOperandsMutable().clear(); op->removeAsyncOperandsDeviceTypeAttr(); } TEST_F(OpenACCOpsTest, asyncValueTestDataEntry) { testAsyncValueDataEntry(b, context, loc, dtypes); testAsyncValueDataEntry(b, context, loc, dtypes); testAsyncValueDataEntry(b, context, loc, dtypes); testAsyncValueDataEntry(b, context, loc, dtypes); testAsyncValueDataEntry(b, context, loc, dtypes); testAsyncValueDataEntry(b, context, loc, dtypes); testAsyncValueDataEntry(b, context, loc, dtypes); testAsyncValueDataEntry(b, context, loc, dtypes); } template void testNumGangsValues(OpBuilder &b, MLIRContext &context, Location loc, llvm::SmallVector &dtypes, llvm::SmallVector &dtypesWithoutNone) { OwningOpRef op = Op::create(b, loc, TypeRange{}, ValueRange{}); EXPECT_EQ(op->getNumGangsValues().begin(), op->getNumGangsValues().end()); OwningOpRef val1 = arith::ConstantIndexOp::create(b, loc, 1); OwningOpRef val2 = arith::ConstantIndexOp::create(b, loc, 4); auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None); op->getNumGangsMutable().assign(val1->getResult()); op->setNumGangsDeviceTypeAttr(b.getArrayAttr({dtypeNone})); op->setNumGangsSegments(b.getDenseI32ArrayAttr({1})); EXPECT_EQ(op->getNumGangsValues().front(), val1->getResult()); for (auto d : dtypesWithoutNone) EXPECT_EQ(op->getNumGangsValues(d).begin(), op->getNumGangsValues(d).end()); op->getNumGangsMutable().clear(); op->removeNumGangsDeviceTypeAttr(); op->removeNumGangsSegmentsAttr(); for (auto d : dtypes) EXPECT_EQ(op->getNumGangsValues(d).begin(), op->getNumGangsValues(d).end()); op->getNumGangsMutable().append(val1->getResult()); op->getNumGangsMutable().append(val2->getResult()); op->setNumGangsDeviceTypeAttr( b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Host), DeviceTypeAttr::get(&context, DeviceType::Star)})); op->setNumGangsSegments(b.getDenseI32ArrayAttr({1, 1})); EXPECT_EQ(op->getNumGangsValues(DeviceType::None).begin(), op->getNumGangsValues(DeviceType::None).end()); EXPECT_EQ(op->getNumGangsValues(DeviceType::Host).front(), val1->getResult()); EXPECT_EQ(op->getNumGangsValues(DeviceType::Star).front(), val2->getResult()); op->getNumGangsMutable().clear(); op->removeNumGangsDeviceTypeAttr(); op->removeNumGangsSegmentsAttr(); for (auto d : dtypes) EXPECT_EQ(op->getNumGangsValues(d).begin(), op->getNumGangsValues(d).end()); op->getNumGangsMutable().append(val1->getResult()); op->getNumGangsMutable().append(val2->getResult()); op->getNumGangsMutable().append(val1->getResult()); op->setNumGangsDeviceTypeAttr( b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Default), DeviceTypeAttr::get(&context, DeviceType::Multicore)})); op->setNumGangsSegments(b.getDenseI32ArrayAttr({2, 1})); EXPECT_EQ(op->getNumGangsValues(DeviceType::None).begin(), op->getNumGangsValues(DeviceType::None).end()); EXPECT_EQ(op->getNumGangsValues(DeviceType::Default).front(), val1->getResult()); EXPECT_EQ(op->getNumGangsValues(DeviceType::Default).drop_front().front(), val2->getResult()); EXPECT_EQ(op->getNumGangsValues(DeviceType::Multicore).front(), val1->getResult()); op->getNumGangsMutable().clear(); op->removeNumGangsDeviceTypeAttr(); op->removeNumGangsSegmentsAttr(); } TEST_F(OpenACCOpsTest, numGangsValuesTest) { testNumGangsValues(b, context, loc, dtypes, dtypesWithoutNone); testNumGangsValues(b, context, loc, dtypes, dtypesWithoutNone); } template void testVectorLength(OpBuilder &b, MLIRContext &context, Location loc, llvm::SmallVector &dtypes) { OwningOpRef op = Op::create(b, loc, TypeRange{}, ValueRange{}); mlir::Value empty; EXPECT_EQ(op->getVectorLengthValue(), empty); for (auto d : dtypes) EXPECT_EQ(op->getVectorLengthValue(d), empty); OwningOpRef val = arith::ConstantIndexOp::create(b, loc, 1); auto dtypeNvidia = DeviceTypeAttr::get(&context, DeviceType::Nvidia); op->setVectorLengthDeviceTypeAttr(b.getArrayAttr({dtypeNvidia})); op->getVectorLengthMutable().assign(val->getResult()); EXPECT_EQ(op->getVectorLengthValue(), empty); EXPECT_EQ(op->getVectorLengthValue(DeviceType::Nvidia), val->getResult()); op->getVectorLengthMutable().clear(); op->removeVectorLengthDeviceTypeAttr(); } TEST_F(OpenACCOpsTest, vectorLengthTest) { testVectorLength(b, context, loc, dtypes); testVectorLength(b, context, loc, dtypes); } template void testWaitOnly(OpBuilder &b, MLIRContext &context, Location loc, llvm::SmallVector &dtypes, llvm::SmallVector &dtypesWithoutNone) { OwningOpRef op = Op::create(b, loc, TypeRange{}, ValueRange{}); EXPECT_FALSE(op->hasWaitOnly()); for (auto d : dtypes) EXPECT_FALSE(op->hasWaitOnly(d)); auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None); op->setWaitOnlyAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasWaitOnly()); EXPECT_TRUE(op->hasWaitOnly(DeviceType::None)); for (auto d : dtypesWithoutNone) EXPECT_FALSE(op->hasWaitOnly(d)); op->removeWaitOnlyAttr(); auto dtypeHost = DeviceTypeAttr::get(&context, DeviceType::Host); op->setWaitOnlyAttr(b.getArrayAttr({dtypeHost})); EXPECT_TRUE(op->hasWaitOnly(DeviceType::Host)); EXPECT_FALSE(op->hasWaitOnly()); op->removeWaitOnlyAttr(); auto dtypeStar = DeviceTypeAttr::get(&context, DeviceType::Star); op->setWaitOnlyAttr(b.getArrayAttr({dtypeHost, dtypeStar})); EXPECT_TRUE(op->hasWaitOnly(DeviceType::Star)); EXPECT_TRUE(op->hasWaitOnly(DeviceType::Host)); EXPECT_FALSE(op->hasWaitOnly()); op->removeWaitOnlyAttr(); } TEST_F(OpenACCOpsTest, waitOnlyTest) { testWaitOnly(b, context, loc, dtypes, dtypesWithoutNone); testWaitOnly(b, context, loc, dtypes, dtypesWithoutNone); testWaitOnly(b, context, loc, dtypes, dtypesWithoutNone); testWaitOnly(b, context, loc, dtypes, dtypesWithoutNone); testWaitOnly(b, context, loc, dtypes, dtypesWithoutNone); } template void testWaitValues(OpBuilder &b, MLIRContext &context, Location loc, llvm::SmallVector &dtypes, llvm::SmallVector &dtypesWithoutNone) { OwningOpRef op = Op::create(b, loc, TypeRange{}, ValueRange{}); EXPECT_EQ(op->getWaitValues().begin(), op->getWaitValues().end()); OwningOpRef val1 = arith::ConstantIndexOp::create(b, loc, 1); OwningOpRef val2 = arith::ConstantIndexOp::create(b, loc, 4); OwningOpRef val3 = arith::ConstantIndexOp::create(b, loc, 5); auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None); op->getWaitOperandsMutable().assign(val1->getResult()); op->setWaitOperandsDeviceTypeAttr(b.getArrayAttr({dtypeNone})); op->setWaitOperandsSegments(b.getDenseI32ArrayAttr({1})); op->setHasWaitDevnumAttr(b.getBoolArrayAttr({false})); EXPECT_EQ(op->getWaitValues().front(), val1->getResult()); for (auto d : dtypesWithoutNone) EXPECT_TRUE(op->getWaitValues(d).empty()); op->getWaitOperandsMutable().clear(); op->removeWaitOperandsDeviceTypeAttr(); op->removeWaitOperandsSegmentsAttr(); op->removeHasWaitDevnumAttr(); for (auto d : dtypes) EXPECT_TRUE(op->getWaitValues(d).empty()); op->getWaitOperandsMutable().append(val1->getResult()); op->getWaitOperandsMutable().append(val2->getResult()); op->setWaitOperandsDeviceTypeAttr( b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Host), DeviceTypeAttr::get(&context, DeviceType::Star)})); op->setWaitOperandsSegments(b.getDenseI32ArrayAttr({1, 1})); op->setHasWaitDevnumAttr(b.getBoolArrayAttr({false, false})); EXPECT_EQ(op->getWaitValues(DeviceType::None).begin(), op->getWaitValues(DeviceType::None).end()); EXPECT_EQ(op->getWaitValues(DeviceType::Host).front(), val1->getResult()); EXPECT_EQ(op->getWaitValues(DeviceType::Star).front(), val2->getResult()); op->getWaitOperandsMutable().clear(); op->removeWaitOperandsDeviceTypeAttr(); op->removeWaitOperandsSegmentsAttr(); op->removeHasWaitDevnumAttr(); for (auto d : dtypes) EXPECT_TRUE(op->getWaitValues(d).empty()); op->getWaitOperandsMutable().append(val1->getResult()); op->getWaitOperandsMutable().append(val2->getResult()); op->getWaitOperandsMutable().append(val1->getResult()); op->setWaitOperandsDeviceTypeAttr( b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Default), DeviceTypeAttr::get(&context, DeviceType::Multicore)})); op->setWaitOperandsSegments(b.getDenseI32ArrayAttr({2, 1})); op->setHasWaitDevnumAttr(b.getBoolArrayAttr({false, false})); EXPECT_EQ(op->getWaitValues(DeviceType::None).begin(), op->getWaitValues(DeviceType::None).end()); EXPECT_EQ(op->getWaitValues(DeviceType::Default).front(), val1->getResult()); EXPECT_EQ(op->getWaitValues(DeviceType::Default).drop_front().front(), val2->getResult()); EXPECT_EQ(op->getWaitValues(DeviceType::Multicore).front(), val1->getResult()); op->getWaitOperandsMutable().clear(); op->removeWaitOperandsDeviceTypeAttr(); op->removeWaitOperandsSegmentsAttr(); op->getWaitOperandsMutable().append(val3->getResult()); op->getWaitOperandsMutable().append(val2->getResult()); op->getWaitOperandsMutable().append(val1->getResult()); op->setWaitOperandsDeviceTypeAttr( b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Multicore)})); op->setHasWaitDevnumAttr(b.getBoolArrayAttr({true})); op->setWaitOperandsSegments(b.getDenseI32ArrayAttr({3})); EXPECT_EQ(op->getWaitValues(DeviceType::None).begin(), op->getWaitValues(DeviceType::None).end()); EXPECT_FALSE(op->getWaitDevnum()); EXPECT_EQ(op->getWaitDevnum(DeviceType::Multicore), val3->getResult()); EXPECT_EQ(op->getWaitValues(DeviceType::Multicore).front(), val2->getResult()); EXPECT_EQ(op->getWaitValues(DeviceType::Multicore).drop_front().front(), val1->getResult()); op->getWaitOperandsMutable().clear(); op->removeWaitOperandsDeviceTypeAttr(); op->removeWaitOperandsSegmentsAttr(); op->removeHasWaitDevnumAttr(); } TEST_F(OpenACCOpsTest, waitValuesTest) { testWaitValues(b, context, loc, dtypes, dtypesWithoutNone); testWaitValues(b, context, loc, dtypes, dtypesWithoutNone); testWaitValues(b, context, loc, dtypes, dtypesWithoutNone); } TEST_F(OpenACCOpsTest, loopOpGangVectorWorkerTest) { OwningOpRef op = LoopOp::create(b, loc, TypeRange{}, ValueRange{}); EXPECT_FALSE(op->hasGang()); EXPECT_FALSE(op->hasVector()); EXPECT_FALSE(op->hasWorker()); for (auto d : dtypes) { EXPECT_FALSE(op->hasGang(d)); EXPECT_FALSE(op->hasVector(d)); EXPECT_FALSE(op->hasWorker(d)); } auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None); op->setGangAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasGang()); EXPECT_TRUE(op->hasGang(DeviceType::None)); for (auto d : dtypesWithoutNone) EXPECT_FALSE(op->hasGang(d)); for (auto d : dtypes) { EXPECT_FALSE(op->hasVector(d)); EXPECT_FALSE(op->hasWorker(d)); } op->removeGangAttr(); op->setWorkerAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasWorker()); EXPECT_TRUE(op->hasWorker(DeviceType::None)); for (auto d : dtypesWithoutNone) EXPECT_FALSE(op->hasWorker(d)); for (auto d : dtypes) { EXPECT_FALSE(op->hasGang(d)); EXPECT_FALSE(op->hasVector(d)); } op->removeWorkerAttr(); op->setVectorAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasVector()); EXPECT_TRUE(op->hasVector(DeviceType::None)); for (auto d : dtypesWithoutNone) EXPECT_FALSE(op->hasVector(d)); for (auto d : dtypes) { EXPECT_FALSE(op->hasGang(d)); EXPECT_FALSE(op->hasWorker(d)); } op->removeVectorAttr(); } TEST_F(OpenACCOpsTest, routineOpTest) { OwningOpRef op = RoutineOp::create(b, loc, TypeRange{}, ValueRange{}); EXPECT_FALSE(op->hasSeq()); EXPECT_FALSE(op->hasVector()); EXPECT_FALSE(op->hasWorker()); for (auto d : dtypes) { EXPECT_FALSE(op->hasSeq(d)); EXPECT_FALSE(op->hasVector(d)); EXPECT_FALSE(op->hasWorker(d)); } auto dtypeNone = DeviceTypeAttr::get(&context, DeviceType::None); op->setSeqAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasSeq()); for (auto d : dtypesWithoutNone) EXPECT_FALSE(op->hasSeq(d)); op->removeSeqAttr(); op->setVectorAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasVector()); for (auto d : dtypesWithoutNone) EXPECT_FALSE(op->hasVector(d)); op->removeVectorAttr(); op->setWorkerAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasWorker()); for (auto d : dtypesWithoutNone) EXPECT_FALSE(op->hasWorker(d)); op->removeWorkerAttr(); op->setGangAttr(b.getArrayAttr({dtypeNone})); EXPECT_TRUE(op->hasGang()); for (auto d : dtypesWithoutNone) EXPECT_FALSE(op->hasGang(d)); op->removeGangAttr(); op->setGangDimDeviceTypeAttr(b.getArrayAttr({dtypeNone})); op->setGangDimAttr(b.getArrayAttr({b.getIntegerAttr(b.getI64Type(), 8)})); EXPECT_TRUE(op->getGangDimValue().has_value()); EXPECT_EQ(op->getGangDimValue().value(), 8); for (auto d : dtypesWithoutNone) EXPECT_FALSE(op->getGangDimValue(d).has_value()); op->removeGangDimDeviceTypeAttr(); op->removeGangDimAttr(); op->setBindIdNameDeviceTypeAttr( b.getArrayAttr({DeviceTypeAttr::get(&context, DeviceType::Host)})); op->setBindStrNameDeviceTypeAttr(b.getArrayAttr({dtypeNone})); op->setBindIdNameAttr( b.getArrayAttr({SymbolRefAttr::get(&context, "test_symbol")})); op->setBindStrNameAttr(b.getArrayAttr({b.getStringAttr("fname")})); EXPECT_TRUE(op->getBindNameValue().has_value()); EXPECT_TRUE(op->getBindNameValue(DeviceType::Host).has_value()); EXPECT_EQ(std::visit( [](const auto &attr) -> std::string { if constexpr (std::is_same_v, mlir::StringAttr>) { return attr.str(); } else { return attr.getLeafReference().str(); } }, op->getBindNameValue().value()), "fname"); EXPECT_EQ(std::visit( [](const auto &attr) -> std::string { if constexpr (std::is_same_v, mlir::StringAttr>) { return attr.str(); } else { return attr.getLeafReference().str(); } }, op->getBindNameValue(DeviceType::Host).value()), "test_symbol"); for (auto d : dtypesWithoutNone) { if (d != DeviceType::Host) EXPECT_FALSE(op->getBindNameValue(d).has_value()); } op->removeBindIdNameDeviceTypeAttr(); op->removeBindStrNameDeviceTypeAttr(); op->removeBindIdNameAttr(); op->removeBindStrNameAttr(); } template void testShortDataEntryOpBuilders(OpBuilder &b, MLIRContext &context, Location loc, DataClause dataClause) { auto memrefTy = MemRefType::get({}, b.getI32Type()); OwningOpRef varPtrOp = memref::AllocaOp::create(b, loc, memrefTy); TypedValue varPtr = cast>(varPtrOp->getResult()); OwningOpRef op = Op::create(b, loc, varPtr, /*structured=*/true, /*implicit=*/true); EXPECT_EQ(op->getVarPtr(), varPtr); EXPECT_EQ(op->getType(), memrefTy); EXPECT_EQ(op->getDataClause(), dataClause); EXPECT_TRUE(op->getImplicit()); EXPECT_TRUE(op->getStructured()); EXPECT_TRUE(op->getBounds().empty()); EXPECT_FALSE(op->getVarPtrPtr()); OwningOpRef op2 = Op::create(b, loc, varPtr, /*structured=*/false, /*implicit=*/false); EXPECT_FALSE(op2->getImplicit()); EXPECT_FALSE(op2->getStructured()); OwningOpRef extent = arith::ConstantIndexOp::create(b, loc, 1); OwningOpRef bounds = DataBoundsOp::create(b, loc, extent->getResult()); OwningOpRef opWithBounds = Op::create(b, loc, varPtr, /*structured=*/true, /*implicit=*/true, bounds->getResult()); EXPECT_FALSE(opWithBounds->getBounds().empty()); EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult()); OwningOpRef opWithName = Op::create(b, loc, varPtr, /*structured=*/true, /*implicit=*/true, "varName"); EXPECT_EQ(opWithName->getNameAttr().str(), "varName"); } TEST_F(OpenACCOpsTest, shortDataEntryOpBuilder) { testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_private); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_firstprivate); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_reduction); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_deviceptr); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_present); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_copyin); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_create); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_no_create); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_attach); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_getdeviceptr); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_update_device); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_use_device); testShortDataEntryOpBuilders( b, context, loc, DataClause::acc_declare_device_resident); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_declare_link); testShortDataEntryOpBuilders(b, context, loc, DataClause::acc_cache); } template void testShortDataExitOpBuilders(OpBuilder &b, MLIRContext &context, Location loc, DataClause dataClause) { auto memrefTy = MemRefType::get({}, b.getI32Type()); OwningOpRef varPtrOp = memref::AllocaOp::create(b, loc, memrefTy); TypedValue varPtr = cast>(varPtrOp->getResult()); OwningOpRef accPtrOp = GetDevicePtrOp::create( b, loc, varPtr, /*structured=*/true, /*implicit=*/true); TypedValue accPtr = cast>(accPtrOp->getResult()); OwningOpRef op = Op::create(b, loc, accPtr, varPtr, /*structured=*/true, /*implicit=*/true); EXPECT_EQ(op->getVarPtr(), varPtr); EXPECT_EQ(op->getAccPtr(), accPtr); EXPECT_EQ(op->getDataClause(), dataClause); EXPECT_TRUE(op->getImplicit()); EXPECT_TRUE(op->getStructured()); EXPECT_TRUE(op->getBounds().empty()); OwningOpRef op2 = Op::create(b, loc, accPtr, varPtr, /*structured=*/false, /*implicit=*/false); EXPECT_FALSE(op2->getImplicit()); EXPECT_FALSE(op2->getStructured()); OwningOpRef extent = arith::ConstantIndexOp::create(b, loc, 1); OwningOpRef bounds = DataBoundsOp::create(b, loc, extent->getResult()); OwningOpRef opWithBounds = Op::create(b, loc, accPtr, varPtr, /*structured=*/true, /*implicit=*/true, bounds->getResult()); EXPECT_FALSE(opWithBounds->getBounds().empty()); EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult()); OwningOpRef opWithName = Op::create(b, loc, accPtr, varPtr, /*structured=*/true, /*implicit=*/true, "varName"); EXPECT_EQ(opWithName->getNameAttr().str(), "varName"); } TEST_F(OpenACCOpsTest, shortDataExitOpBuilder) { testShortDataExitOpBuilders(b, context, loc, DataClause::acc_copyout); testShortDataExitOpBuilders(b, context, loc, DataClause::acc_update_host); } template void testShortDataExitNoVarPtrOpBuilders(OpBuilder &b, MLIRContext &context, Location loc, DataClause dataClause) { auto memrefTy = MemRefType::get({}, b.getI32Type()); OwningOpRef varPtrOp = memref::AllocaOp::create(b, loc, memrefTy); TypedValue varPtr = cast>(varPtrOp->getResult()); OwningOpRef accPtrOp = GetDevicePtrOp::create( b, loc, varPtr, /*structured=*/true, /*implicit=*/true); TypedValue accPtr = cast>(accPtrOp->getResult()); OwningOpRef op = Op::create(b, loc, accPtr, /*structured=*/true, /*implicit=*/true); EXPECT_EQ(op->getAccPtr(), accPtr); EXPECT_EQ(op->getDataClause(), dataClause); EXPECT_TRUE(op->getImplicit()); EXPECT_TRUE(op->getStructured()); EXPECT_TRUE(op->getBounds().empty()); OwningOpRef op2 = Op::create(b, loc, accPtr, /*structured=*/false, /*implicit=*/false); EXPECT_FALSE(op2->getImplicit()); EXPECT_FALSE(op2->getStructured()); OwningOpRef extent = arith::ConstantIndexOp::create(b, loc, 1); OwningOpRef bounds = DataBoundsOp::create(b, loc, extent->getResult()); OwningOpRef opWithBounds = Op::create(b, loc, accPtr, /*structured=*/true, /*implicit=*/true, bounds->getResult()); EXPECT_FALSE(opWithBounds->getBounds().empty()); EXPECT_EQ(opWithBounds->getBounds().back(), bounds->getResult()); OwningOpRef opWithName = Op::create(b, loc, accPtr, /*structured=*/true, /*implicit=*/true, "varName"); EXPECT_EQ(opWithName->getNameAttr().str(), "varName"); } TEST_F(OpenACCOpsTest, shortDataExitOpNoVarPtrBuilder) { testShortDataExitNoVarPtrOpBuilders(b, context, loc, DataClause::acc_delete); testShortDataExitNoVarPtrOpBuilders(b, context, loc, DataClause::acc_detach); } template void testShortDataEntryOpBuildersMappableVar(OpBuilder &b, MLIRContext &context, Location loc, DataClause dataClause) { auto int64Ty = b.getI64Type(); auto memrefTy = MemRefType::get({}, int64Ty); OwningOpRef varPtrOp = memref::AllocaOp::create(b, loc, memrefTy); SmallVector indices; OwningOpRef loadVarOp = memref::LoadOp::create(b, loc, int64Ty, varPtrOp->getResult(), indices); EXPECT_TRUE(isMappableType(loadVarOp->getResult().getType())); TypedValue var = cast>(loadVarOp->getResult()); OwningOpRef op = Op::create(b, loc, var, /*structured=*/true, /*implicit=*/true); EXPECT_EQ(op->getVar(), var); EXPECT_EQ(op->getVarPtr(), nullptr); EXPECT_EQ(op->getType(), int64Ty); EXPECT_EQ(op->getVarType(), int64Ty); EXPECT_EQ(op->getDataClause(), dataClause); EXPECT_TRUE(op->getImplicit()); EXPECT_TRUE(op->getStructured()); EXPECT_TRUE(op->getBounds().empty()); EXPECT_FALSE(op->getVarPtrPtr()); } struct IntegerOpenACCMappableModel : public mlir::acc::MappableType::ExternalModel {}; TEST_F(OpenACCOpsTest, mappableTypeBuilderDataEntry) { // First, set up the test by attaching MappableInterface to IntegerType. IntegerType i64ty = IntegerType::get(&context, 8); ASSERT_FALSE(isMappableType(i64ty)); IntegerType::attachInterface(context); ASSERT_TRUE(isMappableType(i64ty)); testShortDataEntryOpBuildersMappableVar(b, context, loc, DataClause::acc_private); testShortDataEntryOpBuildersMappableVar( b, context, loc, DataClause::acc_firstprivate); testShortDataEntryOpBuildersMappableVar( b, context, loc, DataClause::acc_reduction); testShortDataEntryOpBuildersMappableVar( b, context, loc, DataClause::acc_deviceptr); testShortDataEntryOpBuildersMappableVar(b, context, loc, DataClause::acc_present); testShortDataEntryOpBuildersMappableVar(b, context, loc, DataClause::acc_copyin); testShortDataEntryOpBuildersMappableVar(b, context, loc, DataClause::acc_create); testShortDataEntryOpBuildersMappableVar( b, context, loc, DataClause::acc_no_create); testShortDataEntryOpBuildersMappableVar(b, context, loc, DataClause::acc_attach); testShortDataEntryOpBuildersMappableVar( b, context, loc, DataClause::acc_getdeviceptr); testShortDataEntryOpBuildersMappableVar( b, context, loc, DataClause::acc_update_device); testShortDataEntryOpBuildersMappableVar( b, context, loc, DataClause::acc_use_device); testShortDataEntryOpBuildersMappableVar( b, context, loc, DataClause::acc_declare_device_resident); testShortDataEntryOpBuildersMappableVar( b, context, loc, DataClause::acc_declare_link); testShortDataEntryOpBuildersMappableVar(b, context, loc, DataClause::acc_cache); }