[Mlir-commits] [mlir] 6110b66 - [mlir][openacc] Conversion of data operand to LLVM IR dialect
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Wed May 12 08:34:42 PDT 2021
Author: Valentin Clement
Date: 2021-05-12T11:34:15-04:00
New Revision: 6110b667b0537104ee139a5c6efc726f902db4de
URL: https://github.com/llvm/llvm-project/commit/6110b667b0537104ee139a5c6efc726f902db4de
DIFF: https://github.com/llvm/llvm-project/commit/6110b667b0537104ee139a5c6efc726f902db4de.diff
LOG: [mlir][openacc] Conversion of data operand to LLVM IR dialect
Add a conversion pass to convert higher-level type before translation.
This conversion extract meangingful information and pack it into a struct that
the translation (D101504) will be able to understand.
Reviewed By: ftynse
Differential Revision: https://reviews.llvm.org/D102170
Added:
mlir/include/mlir/Conversion/OpenACCToLLVM/ConvertOpenACCToLLVM.h
mlir/lib/Conversion/OpenACCToLLVM/CMakeLists.txt
mlir/lib/Conversion/OpenACCToLLVM/OpenACCToLLVM.cpp
mlir/test/Conversion/OpenACCToLLVM/convert-standalone-data-to-llvmir.mlir
Modified:
mlir/include/mlir/Conversion/Passes.h
mlir/include/mlir/Conversion/Passes.td
mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
mlir/lib/Conversion/CMakeLists.txt
mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/Conversion/OpenACCToLLVM/ConvertOpenACCToLLVM.h b/mlir/include/mlir/Conversion/OpenACCToLLVM/ConvertOpenACCToLLVM.h
new file mode 100644
index 0000000000000..ef55f45d3d7f4
--- /dev/null
+++ b/mlir/include/mlir/Conversion/OpenACCToLLVM/ConvertOpenACCToLLVM.h
@@ -0,0 +1,75 @@
+//===- ConvertOpenACCToLLVM.h - OpenACC conversion pass entrypoint --------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+#ifndef MLIR_CONVERSION_OPENACCTOLLVM_CONVERTOPENACCTOLLVM_H
+#define MLIR_CONVERSION_OPENACCTOLLVM_CONVERTOPENACCTOLLVM_H
+
+#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
+#include <memory>
+
+namespace mlir {
+class LLVMTypeConverter;
+class ModuleOp;
+template <typename T>
+class OperationPass;
+class RewritePatternSet;
+
+static constexpr unsigned kPtrBasePosInDataDescriptor = 0;
+static constexpr unsigned kPtrPosInDataDescriptor = 1;
+static constexpr unsigned kSizePosInDataDescriptor = 2;
+
+/// Helper class to produce LLVM dialect operations inserting
+/// elements to a Data descriptor. Wraps a Value pointing to the descriptor.
+/// The Value may be null, in which case none of the operations are valid.
+///
+/// The data descriptor holds information needed to perform data operations
+/// and movments with the runtime.
+/// `BasePointer`: base of the pointer being mapped.
+/// `Pointer`: actual pointer of the data being mapped.
+/// `Size`: size of the data being mapped.
+///
+/// Example:
+///
+/// ```c
+/// struct S {
+/// int x;
+/// int y;
+/// };
+/// ```
+///
+/// Mapping `s.y` will result if the following information in the data
+/// descriptor:
+/// - `BasePointer`: address of `s`
+/// - `Pointer`: address of `s.y`
+/// - `Size`: size of `s.y`
+///
+/// For a scalar variable BasePointer and Pointer will be the same.
+class DataDescriptor : public StructBuilder {
+public:
+ /// Construct a helper for the given descriptor value.
+ explicit DataDescriptor(Value descriptor);
+ /// Builds IR creating an `undef` value of the descriptor type.
+ static DataDescriptor undef(OpBuilder &builder, Location loc, Type basePtrTy,
+ Type ptrTy);
+
+ static bool isValid(Value descriptor);
+
+ void setPointer(OpBuilder &builder, Location loc, Value ptr);
+ void setBasePointer(OpBuilder &builder, Location loc, Value basePtr);
+ void setSize(OpBuilder &builder, Location loc, Value size);
+};
+
+/// Collect the patterns to convert from the OpenACC dialect LLVMIR dialect.
+void populateOpenACCToLLVMConversionPatterns(LLVMTypeConverter &converter,
+ RewritePatternSet &patterns);
+
+/// Create a pass to convert the OpenACC dialect into the LLVMIR dialect.
+std::unique_ptr<OperationPass<ModuleOp>> createConvertOpenACCToLLVMPass();
+
+} // namespace mlir
+
+#endif // MLIR_CONVERSION_OPENACCTOLLVM_CONVERTOPENACCTOLLVM_H
diff --git a/mlir/include/mlir/Conversion/Passes.h b/mlir/include/mlir/Conversion/Passes.h
index c8f8baa87863e..0fd7fdd131b90 100644
--- a/mlir/include/mlir/Conversion/Passes.h
+++ b/mlir/include/mlir/Conversion/Passes.h
@@ -22,6 +22,7 @@
#include "mlir/Conversion/LinalgToSPIRV/LinalgToSPIRVPass.h"
#include "mlir/Conversion/LinalgToStandard/LinalgToStandard.h"
#include "mlir/Conversion/MathToLibm/MathToLibm.h"
+#include "mlir/Conversion/OpenACCToLLVM/ConvertOpenACCToLLVM.h"
#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
#include "mlir/Conversion/PDLToPDLInterp/PDLToPDLInterp.h"
#include "mlir/Conversion/SCFToGPU/SCFToGPUPass.h"
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 9ca99e9171392..b26b708c06fb6 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -255,6 +255,16 @@ def ConvertMathToLibm : Pass<"convert-math-to-libm", "ModuleOp"> {
let dependentDialects = ["StandardOpsDialect", "vector::VectorDialect"];
}
+//===----------------------------------------------------------------------===//
+// OpenACCToLLVM
+//===----------------------------------------------------------------------===//
+
+def ConvertOpenACCToLLVM : Pass<"convert-openacc-to-llvm", "ModuleOp"> {
+ let summary = "Convert the OpenACC ops to LLVM dialect";
+ let constructor = "mlir::createConvertOpenACCToLLVMPass()";
+ let dependentDialects = ["LLVM::LLVMDialect"];
+}
+
//===----------------------------------------------------------------------===//
// OpenMPToLLVM
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index 586cee41edcb1..74f53c5030c75 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -249,6 +249,14 @@ def OpenACC_EnterDataOp : OpenACC_Op<"enter_data", [AttrSizedOperandSegments]> {
Variadic<AnyType>:$createZeroOperands,
Variadic<AnyType>:$attachOperands);
+ let extraClassDeclaration = [{
+ /// The number of data operands.
+ unsigned getNumDataOperands();
+
+ /// The i-th data operand passed.
+ Value getDataOperand(unsigned i);
+ }];
+
let assemblyFormat = [{
( `if` `(` $ifCond^ `)` )?
( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
@@ -291,6 +299,14 @@ def OpenACC_ExitDataOp : OpenACC_Op<"exit_data", [AttrSizedOperandSegments]> {
Variadic<AnyType>:$detachOperands,
UnitAttr:$finalize);
+ let extraClassDeclaration = [{
+ /// The number of data operands.
+ unsigned getNumDataOperands();
+
+ /// The i-th data operand passed.
+ Value getDataOperand(unsigned i);
+ }];
+
let assemblyFormat = [{
( `if` `(` $ifCond^ `)` )?
( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
@@ -480,6 +496,14 @@ def OpenACC_UpdateOp : OpenACC_Op<"update", [AttrSizedOperandSegments]> {
Variadic<AnyType>:$deviceOperands,
UnitAttr:$ifPresent);
+ let extraClassDeclaration = [{
+ /// The number of data operands.
+ unsigned getNumDataOperands();
+
+ /// The i-th data operand passed.
+ Value getDataOperand(unsigned i);
+ }];
+
let assemblyFormat = [{
( `if` `(` $ifCond^ `)` )?
( `async` `(` $asyncOperand^ `:` type($asyncOperand) `)` )?
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index 1cf9d304151e0..e61e80423bcd9 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -11,6 +11,7 @@ add_subdirectory(LinalgToLLVM)
add_subdirectory(LinalgToSPIRV)
add_subdirectory(LinalgToStandard)
add_subdirectory(MathToLibm)
+add_subdirectory(OpenACCToLLVM)
add_subdirectory(OpenMPToLLVM)
add_subdirectory(PDLToPDLInterp)
add_subdirectory(SCFToGPU)
diff --git a/mlir/lib/Conversion/OpenACCToLLVM/CMakeLists.txt b/mlir/lib/Conversion/OpenACCToLLVM/CMakeLists.txt
new file mode 100644
index 0000000000000..83693c1eda668
--- /dev/null
+++ b/mlir/lib/Conversion/OpenACCToLLVM/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_mlir_conversion_library(MLIROpenACCToLLVM
+ OpenACCToLLVM.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/OpenACCToLLVM
+
+ DEPENDS
+ MLIRConversionPassIncGen
+
+ LINK_LIBS PUBLIC
+ MLIRIR
+ MLIRLLVMIR
+ MLIROpenACC
+ MLIRStandardToLLVM
+ MLIRTransforms
+ )
diff --git a/mlir/lib/Conversion/OpenACCToLLVM/OpenACCToLLVM.cpp b/mlir/lib/Conversion/OpenACCToLLVM/OpenACCToLLVM.cpp
new file mode 100644
index 0000000000000..75b2c4033a5ba
--- /dev/null
+++ b/mlir/lib/Conversion/OpenACCToLLVM/OpenACCToLLVM.cpp
@@ -0,0 +1,198 @@
+//===- OpenACCToLLVM.cpp - Prepare OpenACC data for LLVM translation ------===//
+//
+// 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 "../PassDetail.h"
+#include "mlir/Conversion/OpenACCToLLVM/ConvertOpenACCToLLVM.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+
+using namespace mlir;
+
+//===----------------------------------------------------------------------===//
+// DataDescriptor implementation
+//===----------------------------------------------------------------------===//
+
+constexpr StringRef getStructName() { return "openacc_data"; }
+
+/// Construct a helper for the given descriptor value.
+DataDescriptor::DataDescriptor(Value descriptor) : StructBuilder(descriptor) {
+ assert(value != nullptr && "value cannot be null");
+}
+
+/// Builds IR creating an `undef` value of the data descriptor.
+DataDescriptor DataDescriptor::undef(OpBuilder &builder, Location loc,
+ Type basePtrTy, Type ptrTy) {
+ Type descriptorType = LLVM::LLVMStructType::getNewIdentified(
+ builder.getContext(), getStructName(),
+ {basePtrTy, ptrTy, builder.getI64Type()});
+ Value descriptor = builder.create<LLVM::UndefOp>(loc, descriptorType);
+ return DataDescriptor(descriptor);
+}
+
+/// Check whether the type is a valid data descriptor.
+bool DataDescriptor::isValid(Value descriptor) {
+ if (auto type = descriptor.getType().dyn_cast<LLVM::LLVMStructType>()) {
+ if (type.isIdentified() && type.getName().startswith(getStructName()) &&
+ type.getBody().size() == 3 &&
+ (type.getBody()[kPtrBasePosInDataDescriptor]
+ .isa<LLVM::LLVMPointerType>() ||
+ type.getBody()[kPtrBasePosInDataDescriptor]
+ .isa<LLVM::LLVMStructType>()) &&
+ type.getBody()[kPtrPosInDataDescriptor].isa<LLVM::LLVMPointerType>() &&
+ type.getBody()[kSizePosInDataDescriptor].isInteger(64))
+ return true;
+ }
+ return false;
+}
+
+/// Builds IR inserting the base pointer value into the descriptor.
+void DataDescriptor::setBasePointer(OpBuilder &builder, Location loc,
+ Value basePtr) {
+ setPtr(builder, loc, kPtrBasePosInDataDescriptor, basePtr);
+}
+
+/// Builds IR inserting the pointer value into the descriptor.
+void DataDescriptor::setPointer(OpBuilder &builder, Location loc, Value ptr) {
+ setPtr(builder, loc, kPtrPosInDataDescriptor, ptr);
+}
+
+/// Builds IR inserting the size value into the descriptor.
+void DataDescriptor::setSize(OpBuilder &builder, Location loc, Value size) {
+ setPtr(builder, loc, kSizePosInDataDescriptor, size);
+}
+
+//===----------------------------------------------------------------------===//
+// Conversion patterns
+//===----------------------------------------------------------------------===//
+
+template <typename Op>
+class LegalizeDataOpForLLVMTranslation : public ConvertOpToLLVMPattern<Op> {
+ using ConvertOpToLLVMPattern<Op>::ConvertOpToLLVMPattern;
+
+ LogicalResult
+ matchAndRewrite(Op op, ArrayRef<Value> operands,
+ ConversionPatternRewriter &builder) const override {
+ Location loc = op.getLoc();
+ TypeConverter *converter = ConvertToLLVMPattern::getTypeConverter();
+
+ unsigned numDataOperand = op.getNumDataOperands();
+
+ // Keep the non data operands without modification.
+ auto nonDataOperands =
+ operands.take_front(operands.size() - numDataOperand);
+ SmallVector<Value> convertedOperands;
+ convertedOperands.append(nonDataOperands.begin(), nonDataOperands.end());
+
+ // Go over the data operand and legalize them for translation.
+ for (unsigned idx = 0; idx < numDataOperand; ++idx) {
+ Value originalDataOperand = op.getDataOperand(idx);
+
+ // Traverse operands that were converted to MemRefDescriptors.
+ if (auto memRefType =
+ originalDataOperand.getType().dyn_cast<MemRefType>()) {
+ Type structType = converter->convertType(memRefType);
+ Value memRefDescriptor = builder
+ .create<LLVM::DialectCastOp>(
+ loc, structType, originalDataOperand)
+ .getResult();
+
+ // Calculate the size of the memref and get the pointer to the allocated
+ // buffer.
+ SmallVector<Value> sizes;
+ SmallVector<Value> strides;
+ Value sizeBytes;
+ ConvertToLLVMPattern::getMemRefDescriptorSizes(
+ loc, memRefType, {}, builder, sizes, strides, sizeBytes);
+ MemRefDescriptor descriptor(memRefDescriptor);
+ Value dataPtr = descriptor.alignedPtr(builder, loc);
+ auto ptrType = descriptor.getElementPtrType();
+
+ auto descr = DataDescriptor::undef(builder, loc, structType, ptrType);
+ descr.setBasePointer(builder, loc, memRefDescriptor);
+ descr.setPointer(builder, loc, dataPtr);
+ descr.setSize(builder, loc, sizeBytes);
+ convertedOperands.push_back(descr);
+ } else if (originalDataOperand.getType().isa<LLVM::LLVMPointerType>()) {
+ convertedOperands.push_back(originalDataOperand);
+ } else {
+ // Type not supported.
+ return builder.notifyMatchFailure(op, "unsupported type");
+ }
+ }
+
+ builder.replaceOpWithNewOp<Op>(op, TypeRange(), convertedOperands,
+ op.getOperation()->getAttrs());
+
+ return success();
+ }
+};
+
+void mlir::populateOpenACCToLLVMConversionPatterns(
+ LLVMTypeConverter &converter, OwningRewritePatternList &patterns) {
+ patterns.add<LegalizeDataOpForLLVMTranslation<acc::EnterDataOp>>(converter);
+ patterns.add<LegalizeDataOpForLLVMTranslation<acc::ExitDataOp>>(converter);
+ patterns.add<LegalizeDataOpForLLVMTranslation<acc::UpdateOp>>(converter);
+}
+
+namespace {
+struct ConvertOpenACCToLLVMPass
+ : public ConvertOpenACCToLLVMBase<ConvertOpenACCToLLVMPass> {
+ void runOnOperation() override;
+};
+} // namespace
+
+void ConvertOpenACCToLLVMPass::runOnOperation() {
+ auto op = getOperation();
+ auto *context = op.getContext();
+
+ // Convert to OpenACC operations with LLVM IR dialect
+ RewritePatternSet patterns(context);
+ LLVMTypeConverter converter(context);
+ populateOpenACCToLLVMConversionPatterns(converter, patterns);
+
+ ConversionTarget target(*context);
+ target.addLegalDialect<LLVM::LLVMDialect>();
+
+ auto allDataOperandsAreConverted = [](ValueRange operands) {
+ for (Value operand : operands) {
+ if (!DataDescriptor::isValid(operand) &&
+ !operand.getType().isa<LLVM::LLVMPointerType>())
+ return false;
+ }
+ return true;
+ };
+
+ target.addDynamicallyLegalOp<acc::EnterDataOp>(
+ [allDataOperandsAreConverted](acc::EnterDataOp op) {
+ return allDataOperandsAreConverted(op.copyinOperands()) &&
+ allDataOperandsAreConverted(op.createOperands()) &&
+ allDataOperandsAreConverted(op.createZeroOperands()) &&
+ allDataOperandsAreConverted(op.attachOperands());
+ });
+
+ target.addDynamicallyLegalOp<acc::ExitDataOp>(
+ [allDataOperandsAreConverted](acc::ExitDataOp op) {
+ return allDataOperandsAreConverted(op.copyoutOperands()) &&
+ allDataOperandsAreConverted(op.deleteOperands()) &&
+ allDataOperandsAreConverted(op.detachOperands());
+ });
+
+ target.addDynamicallyLegalOp<acc::UpdateOp>(
+ [allDataOperandsAreConverted](acc::UpdateOp op) {
+ return allDataOperandsAreConverted(op.hostOperands()) &&
+ allDataOperandsAreConverted(op.deviceOperands());
+ });
+
+ if (failed(applyPartialConversion(op, target, std::move(patterns))))
+ signalPassFailure();
+}
+
+std::unique_ptr<OperationPass<ModuleOp>>
+mlir::createConvertOpenACCToLLVMPass() {
+ return std::make_unique<ConvertOpenACCToLLVMPass>();
+}
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index fecc921c9042e..33d6c237b0548 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -682,8 +682,20 @@ static LogicalResult verify(acc::ExitDataOp op) {
return success();
}
+unsigned ExitDataOp::getNumDataOperands() {
+ return copyoutOperands().size() + deleteOperands().size() +
+ detachOperands().size();
+}
+
+Value ExitDataOp::getDataOperand(unsigned i) {
+ unsigned numOptional = ifCond() ? 1 : 0;
+ numOptional += asyncOperand() ? 1 : 0;
+ numOptional += waitDevnum() ? 1 : 0;
+ return getOperand(waitOperands().size() + numOptional + i);
+}
+
//===----------------------------------------------------------------------===//
-// DataEnterOp
+// EnterDataOp
//===----------------------------------------------------------------------===//
static LogicalResult verify(acc::EnterDataOp op) {
@@ -712,6 +724,18 @@ static LogicalResult verify(acc::EnterDataOp op) {
return success();
}
+unsigned EnterDataOp::getNumDataOperands() {
+ return copyinOperands().size() + createOperands().size() +
+ createZeroOperands().size() + attachOperands().size();
+}
+
+Value EnterDataOp::getDataOperand(unsigned i) {
+ unsigned numOptional = ifCond() ? 1 : 0;
+ numOptional += asyncOperand() ? 1 : 0;
+ numOptional += waitDevnum() ? 1 : 0;
+ return getOperand(waitOperands().size() + numOptional + i);
+}
+
//===----------------------------------------------------------------------===//
// InitOp
//===----------------------------------------------------------------------===//
@@ -766,6 +790,18 @@ static LogicalResult verify(acc::UpdateOp updateOp) {
return success();
}
+unsigned UpdateOp::getNumDataOperands() {
+ return hostOperands().size() + deviceOperands().size();
+}
+
+Value UpdateOp::getDataOperand(unsigned i) {
+ unsigned numOptional = asyncOperand() ? 1 : 0;
+ numOptional += waitDevnum() ? 1 : 0;
+ numOptional += ifCond() ? 1 : 0;
+ return getOperand(waitOperands().size() + deviceTypeOperands().size() +
+ numOptional + i);
+}
+
//===----------------------------------------------------------------------===//
// WaitOp
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Conversion/OpenACCToLLVM/convert-standalone-data-to-llvmir.mlir b/mlir/test/Conversion/OpenACCToLLVM/convert-standalone-data-to-llvmir.mlir
new file mode 100644
index 0000000000000..0bc3493fc819b
--- /dev/null
+++ b/mlir/test/Conversion/OpenACCToLLVM/convert-standalone-data-to-llvmir.mlir
@@ -0,0 +1,110 @@
+// RUN: mlir-opt -convert-openacc-to-llvm -split-input-file %s | FileCheck %s
+
+func @testenterdataop(%a: memref<10xf32>, %b: memref<10xf32>) -> () {
+ acc.enter_data copyin(%b : memref<10xf32>) create(%a : memref<10xf32>)
+ return
+}
+
+// CHECK: acc.enter_data copyin(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) create(%{{.*}} : !llvm.struct<"openacc_data.1", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>)
+
+// -----
+
+func @testenterdataop(%a: !llvm.ptr<f32>, %b: memref<10xf32>) -> () {
+ acc.enter_data copyin(%b : memref<10xf32>) create(%a : !llvm.ptr<f32>)
+ return
+}
+
+// CHECK: acc.enter_data copyin(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) create(%{{.*}} : !llvm.ptr<f32>)
+
+// -----
+
+func @testenterdataop(%a: memref<10xi64>, %b: memref<10xf32>) -> () {
+ acc.enter_data copyin(%b : memref<10xf32>) create_zero(%a : memref<10xi64>) attributes {async}
+ return
+}
+
+// CHECK: acc.enter_data copyin(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) create_zero(%{{.*}} : !llvm.struct<"openacc_data.1", (struct<(ptr<i64>, ptr<i64>, i64, array<1 x i64>, array<1 x i64>)>, ptr<i64>, i64)>) attributes {async}
+
+// -----
+
+func @testenterdataop(%a: memref<10xf32>, %b: memref<10xf32>) -> () {
+ %ifCond = constant true
+ acc.enter_data if(%ifCond) copyin(%b : memref<10xf32>) create(%a : memref<10xf32>)
+ return
+}
+
+// CHECK: acc.enter_data if(%{{.*}}) copyin(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) create(%{{.*}} : !llvm.struct<"openacc_data.1", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>)
+
+// -----
+
+func @testexitdataop(%a: memref<10xf32>, %b: memref<10xf32>) -> () {
+ acc.exit_data copyout(%b : memref<10xf32>) delete(%a : memref<10xf32>)
+ return
+}
+
+// CHECK: acc.exit_data copyout(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) delete(%{{.*}} : !llvm.struct<"openacc_data.1", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>)
+
+// -----
+
+func @testexitdataop(%a: !llvm.ptr<f32>, %b: memref<10xf32>) -> () {
+ acc.exit_data copyout(%b : memref<10xf32>) delete(%a : !llvm.ptr<f32>)
+ return
+}
+
+// CHECK: acc.exit_data copyout(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) delete(%{{.*}} : !llvm.ptr<f32>)
+
+// -----
+
+func @testexitdataop(%a: memref<10xi64>, %b: memref<10xf32>) -> () {
+ acc.exit_data copyout(%b : memref<10xf32>) delete(%a : memref<10xi64>) attributes {async}
+ return
+}
+
+// CHECK: acc.exit_data copyout(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) delete(%{{.*}} : !llvm.struct<"openacc_data.1", (struct<(ptr<i64>, ptr<i64>, i64, array<1 x i64>, array<1 x i64>)>, ptr<i64>, i64)>) attributes {async}
+
+// -----
+
+func @testexitdataop(%a: memref<10xf32>, %b: memref<10xf32>) -> () {
+ %ifCond = constant true
+ acc.exit_data if(%ifCond) copyout(%b : memref<10xf32>) delete(%a : memref<10xf32>)
+ return
+}
+
+// CHECK: acc.exit_data if(%{{.*}}) copyout(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) delete(%{{.*}} : !llvm.struct<"openacc_data.1", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>)
+
+// -----
+
+func @testupdateop(%a: memref<10xf32>, %b: memref<10xf32>) -> () {
+ acc.update host(%b : memref<10xf32>) device(%a : memref<10xf32>)
+ return
+}
+
+// CHECK: acc.update host(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) device(%{{.*}} : !llvm.struct<"openacc_data.1", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>)
+
+// -----
+
+func @testupdateop(%a: !llvm.ptr<f32>, %b: memref<10xf32>) -> () {
+ acc.update host(%b : memref<10xf32>) device(%a : !llvm.ptr<f32>)
+ return
+}
+
+// CHECK: acc.update host(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) device(%{{.*}} : !llvm.ptr<f32>)
+
+// -----
+
+func @testupdateop(%a: memref<10xi64>, %b: memref<10xf32>) -> () {
+ acc.update host(%b : memref<10xf32>) device(%a : memref<10xi64>) attributes {async}
+ return
+}
+
+// CHECK: acc.update host(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) device(%{{.*}} : !llvm.struct<"openacc_data.1", (struct<(ptr<i64>, ptr<i64>, i64, array<1 x i64>, array<1 x i64>)>, ptr<i64>, i64)>) attributes {async}
+
+// -----
+
+func @testupdateop(%a: memref<10xf32>, %b: memref<10xf32>) -> () {
+ %ifCond = constant true
+ acc.update if(%ifCond) host(%b : memref<10xf32>) device(%a : memref<10xf32>)
+ return
+}
+
+// CHECK: acc.update if(%{{.*}}) host(%{{.*}} : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>) device(%{{.*}} : !llvm.struct<"openacc_data.1", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>)
More information about the Mlir-commits
mailing list