[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