blob: 4b3952a250c9b83509c8b3f630e8dff6e1b5c9e9 [file] [edit]
// RUN: mlir-opt %s -acc-to-llvm -split-input-file | FileCheck %s
// Data runtime argument emission preserves every dialect map flag.
// CHECK-LABEL: llvm.func @all_map_flags
// CHECK: %[[FLAGS:.*]] = llvm.mlir.constant(8384411 : i64) : i64
// CHECK: llvm.store %[[FLAGS]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_enter
func.func @all_map_flags(%arg0: !llvm.ptr) {
%size = arith.constant 4 : i64
%map = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(i32)
size(%size : i64) elementSize(4)
descKind(none)
mapFlags(to, from, delete, ptr_and_obj, private, literal, implicit,
devptr, managed_devptr, no_create, gang_private,
worker_private, vector_private, init_zero, device_resident,
if_present, present, descriptor, reduction) -> !llvm.ptr
acc.enter_data dataOperands(%map : !llvm.ptr)
return
}
// -----
// A normal delete decrements the dynamic reference count and therefore does
// not force unmapping. Finalize adds DELETE while retaining FROM for copyout.
// CHECK-LABEL: llvm.func @delete_and_finalize
// CHECK: %[[SIZE0:.*]] = llvm.mlir.constant(4 : i64) : i64
// CHECK-NEXT: %[[NONE:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: llvm.store %[[NONE]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_exit
// CHECK: %[[SIZE1:.*]] = llvm.mlir.constant(4 : i64) : i64
// CHECK-NEXT: %[[FROM_DELETE:.*]] = llvm.mlir.constant(10 : i64) : i64
// CHECK: llvm.store %[[FROM_DELETE]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_exit
func.func @delete_and_finalize(%arg0: !llvm.ptr) {
%delete = acc.getdeviceptr varPtr(%arg0 : !llvm.ptr) varType(i32)
dataClause(acc_delete) structured(false) -> !llvm.ptr
acc.exit_data dataOperands(%delete : !llvm.ptr)
acc.delete accPtr(%delete : !llvm.ptr) dataClause(acc_delete)
structured(false)
%copyout = acc.getdeviceptr varPtr(%arg0 : !llvm.ptr) varType(i32)
dataClause(acc_copyout) structured(false) -> !llvm.ptr
acc.exit_data dataOperands(%copyout : !llvm.ptr) finalize
acc.copyout accPtr(%copyout : !llvm.ptr) to varPtr(%arg0 : !llvm.ptr)
varType(i32) dataClause(acc_copyout) structured(false)
return
}
// -----
// Clause operations derive the same map flags as prepared map_info operations.
// A zero-initialized create carries INIT_ZERO, and reduction carries TO, FROM,
// IMPLICIT, and REDUCTION through both calls of a structured data region.
// CHECK-LABEL: llvm.func @clause_map_flags
// CHECK-DAG: %[[ZERO:.*]] = llvm.mlir.constant(131072 : i64) : i64
// CHECK-DAG: llvm.store %[[ZERO]], %{{.*}} : i64, !llvm.ptr
// CHECK-DAG: %[[REDUCTION:.*]] = llvm.mlir.constant(4194819 : i64) : i64
// CHECK-DAG: llvm.store %[[REDUCTION]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_begin
// CHECK: %[[REDUCTION_END:.*]] = llvm.mlir.constant(4194819 : i64) : i64
// CHECK: llvm.store %[[REDUCTION_END]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_end
func.func @clause_map_flags(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {
%zero = acc.create varPtr(%arg0 : !llvm.ptr) varType(i32)
dataClause(acc_create_zero) -> !llvm.ptr
%reduction = acc.copyin varPtr(%arg1 : !llvm.ptr) varType(i32)
dataClause(acc_reduction) implicit(true) -> !llvm.ptr
acc.data dataOperands(%zero, %reduction : !llvm.ptr, !llvm.ptr) {
acc.terminator
}
acc.delete accPtr(%zero : !llvm.ptr) dataClause(acc_create_zero)
acc.copyout accPtr(%reduction : !llvm.ptr) to varPtr(%arg1 : !llvm.ptr)
varType(i32) dataClause(acc_reduction) implicit(true)
return
}
// -----
// ifPresent is a property of the update construct and applies to each of its
// mappings in addition to the direction stated by its clause.
// CHECK-LABEL: llvm.func @update_if_present
// CHECK: %[[TO_PRESENT:.*]] = llvm.mlir.constant(524289 : i64) : i64
// CHECK: llvm.store %[[TO_PRESENT]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_update
// CHECK: %[[FROM_PRESENT:.*]] = llvm.mlir.constant(524290 : i64) : i64
// CHECK: llvm.store %[[FROM_PRESENT]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_update
func.func @update_if_present(%arg0: !llvm.ptr) {
%to = acc.update_device varPtr(%arg0 : !llvm.ptr) varType(i32)
structured(false) -> !llvm.ptr
acc.update dataOperands(%to : !llvm.ptr) ifPresent
%from = acc.getdeviceptr varPtr(%arg0 : !llvm.ptr) varType(i32)
dataClause(acc_update_host) structured(false) -> !llvm.ptr
acc.update dataOperands(%from : !llvm.ptr) ifPresent
acc.update_host accPtr(%from : !llvm.ptr) to varPtr(%arg0 : !llvm.ptr)
varType(i32) structured(false)
return
}
// -----
// Bounds are packed in source order. sourceExtent describes the whole source
// object, and an element stride is converted to bytes.
// CHECK-LABEL: llvm.func @bounded_map
// CHECK-DAG: %[[LB:.*]] = llvm.mlir.constant(2 : i64) : i64
// CHECK-DAG: %[[UB:.*]] = llvm.mlir.constant(6 : i64) : i64
// CHECK-DAG: %[[SOURCE_EXTENT:.*]] = llvm.mlir.constant(20 : i64) : i64
// CHECK-DAG: %[[STRIDE:.*]] = llvm.mlir.constant(3 : i64) : i64
// CHECK-DAG: %[[ELEMENT_SIZE:.*]] = llvm.mlir.constant(4 : i64) : i64
// CHECK-DAG: %[[BYTE_STRIDE:.*]] = llvm.mul %[[STRIDE]], %[[ELEMENT_SIZE]] : i64
// CHECK-DAG: llvm.store %[[LB]], %{{.*}} : i64, !llvm.ptr
// CHECK-DAG: llvm.store %[[UB]], %{{.*}} : i64, !llvm.ptr
// CHECK-DAG: llvm.store %[[SOURCE_EXTENT]], %{{.*}} : i64, !llvm.ptr
// CHECK-DAG: llvm.store %[[BYTE_STRIDE]], %{{.*}} : i64, !llvm.ptr
// CHECK-DAG: %[[RANK:.*]] = llvm.mlir.constant(1 : i8) : i8
// CHECK-DAG: llvm.insertvalue %[[RANK]], %{{.*}}[1]
// CHECK-DAG: llvm.call @__tgt_acc_data_begin
func.func @bounded_map(%arg0: !llvm.ptr) {
%c1 = arith.constant 1 : index
%c2 = arith.constant 2 : index
%c3 = arith.constant 3 : index
%c5 = arith.constant 5 : index
%c6 = arith.constant 6 : index
%c20 = arith.constant 20 : index
%bound = acc.bounds lowerbound(%c2 : index) upperbound(%c6 : index)
extent(%c5 : index) sourceExtent(%c20 : index)
stride(%c3 : index) startIdx(%c1 : index)
%map = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(tensor<?xi32>)
bounds(%bound) elementSize(4) descKind(openacc)
mapFlags(to, from) -> !llvm.ptr
acc.data dataOperands(%map : !llvm.ptr) {
acc.terminator
}
return
}
// -----
// A CFI-backed mapping records the CFI descriptor pointer. With OpenACC
// bounds, the base descriptor version contains both descriptor-kind bits.
// CHECK-LABEL: llvm.func @cfi_descriptor
// CHECK: %[[CFI:.*]] = llvm.mlir.zero : !llvm.struct<(i32, ptr)>
// CHECK: %[[DESC_PTR:.*]] = llvm.insertvalue %arg1, %[[CFI]][1]
// cfi | openacc = 1 | 4096.
// CHECK: %[[VERSION:.*]] = llvm.mlir.constant(4097 : i32) : i32
// CHECK: %[[VERSIONED:.*]] = llvm.insertvalue %[[VERSION]], %[[DESC_PTR]][0]
// CHECK: llvm.insertvalue %[[VERSIONED]], %{{.*}}[0]
// CHECK: llvm.call @__tgt_acc_data_begin
func.func @cfi_descriptor(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c7 = arith.constant 7 : index
%c8 = arith.constant 8 : index
%bound = acc.bounds lowerbound(%c0 : index) upperbound(%c7 : index)
extent(%c8 : index) stride(%c1 : index) startIdx(%c1 : index)
%map = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(tensor<?xf64>)
desc(%arg1 : !llvm.ptr) bounds(%bound) elementSize(8)
descKind(cfi, openacc) mapFlags(to, from, descriptor) -> !llvm.ptr
acc.data dataOperands(%map : !llvm.ptr) {
acc.terminator
}
return
}
// -----
// varPtrPtr is the attachment address and therefore supplies ArgBasePtrs.
// The descriptor itself is used as the base for PTR_AND_OBJ when there is no
// attachment address.
// A CFI descriptor without bounds keeps the CFI-only version, unlike the
// combined version a mapping with OpenACC bounds states.
// CHECK-LABEL: llvm.func @mapping_bases
// CHECK: %[[CFI:.*]] = llvm.mlir.zero : !llvm.struct<(i32, ptr)>
// CHECK: %[[CFI_PTR:.*]] = llvm.insertvalue %arg2, %[[CFI]][1]
// CHECK: %[[CFI_VERSION:.*]] = llvm.mlir.constant(1 : i32) : i32
// CHECK: llvm.insertvalue %[[CFI_VERSION]], %[[CFI_PTR]][0]
// CHECK: llvm.store %arg1, %{{.*}} : !llvm.ptr, !llvm.ptr
// CHECK: llvm.store %arg4, %{{.*}} : !llvm.ptr, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_begin
func.func @mapping_bases(%arg0: !llvm.ptr, %arg1: !llvm.ptr,
%arg2: !llvm.ptr, %arg3: !llvm.ptr, %arg4: !llvm.ptr) {
%size = arith.constant 8 : i64
%attached = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(i64)
varPtrPtr(%arg1 : !llvm.ptr) desc(%arg2 : !llvm.ptr)
size(%size : i64) descKind(cfi)
mapFlags(to, ptr_and_obj) -> !llvm.ptr
%descriptor = acc.map_info varPtr(%arg3 : !llvm.ptr) varType(i64)
desc(%arg4 : !llvm.ptr) size(%size : i64) descKind(cfi)
mapFlags(to, ptr_and_obj) -> !llvm.ptr
acc.data dataOperands(%attached, %descriptor : !llvm.ptr, !llvm.ptr) {
acc.terminator
}
return
}
// -----
// A local device-resident object has no host base and is forcibly removed when
// its structured lifetime ends.
// CHECK-LABEL: llvm.func @device_resident_exit
// CHECK: %[[RESIDENT:.*]] = llvm.mlir.constant(262144 : i64) : i64
// CHECK: llvm.call @__tgt_acc_data_begin
// CHECK: %[[LOCAL_DELETE:.*]] = llvm.mlir.constant(262152 : i64) : i64
// CHECK: llvm.store %[[LOCAL_DELETE]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_end
func.func @device_resident_exit(%local: !llvm.ptr) {
%size = arith.constant 4 : i64
%localMap = acc.map_info varPtr(%local : !llvm.ptr) varType(i32)
size(%size : i64) elementSize(4) descKind(none)
mapFlags(device_resident) -> !llvm.ptr
acc.data dataOperands(%localMap : !llvm.ptr) {
acc.terminator
}
return
}
// -----
// Runtime variable-name globals disambiguate names that sanitize to the same
// symbol while reusing a global for repeated names with the same contents.
// CHECK-DAG: llvm.mlir.global internal constant @acc.var_name.a_b("a-b\00")
// CHECK-DAG: llvm.mlir.global internal constant @acc.var_name.a_b.0("a_b\00")
// CHECK-NOT: @acc.var_name.a_b.1
// CHECK-LABEL: llvm.func @mapping_name_collisions
// CHECK: llvm.call @__tgt_acc_data_enter
func.func @mapping_name_collisions(%arg0: !llvm.ptr, %arg1: !llvm.ptr,
%arg2: !llvm.ptr) {
%size = arith.constant 4 : i64
%first = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(i32)
size(%size : i64) name("a-b") descKind(none)
mapFlags(to) -> !llvm.ptr
%second = acc.map_info varPtr(%arg1 : !llvm.ptr) varType(i32)
size(%size : i64) name("a_b") descKind(none)
mapFlags(to) -> !llvm.ptr
%repeat = acc.map_info varPtr(%arg2 : !llvm.ptr) varType(i32)
size(%size : i64) name("a-b") descKind(none)
mapFlags(to) -> !llvm.ptr
acc.enter_data dataOperands(%first, %second, %repeat
: !llvm.ptr, !llvm.ptr, !llvm.ptr)
return
}
// -----
// A structured mapping reports the entry operation at data_begin and its
// exitLoc at data_end.
// CHECK-DAG: llvm.mlir.global internal constant @acc.loc.3.2.{{[0-9]+}}(";begin.mlir;mapping_exit_location;3;2;;\00")
// CHECK-DAG: llvm.mlir.global internal constant @acc.loc.9.4.{{[0-9]+}}(";end.mlir;mapping_exit_location;9;4;;\00")
// CHECK-LABEL: llvm.func @mapping_exit_location
// CHECK: llvm.mlir.addressof @acc.ident.3.2.{{[0-9]+}}
// CHECK: llvm.call @__tgt_acc_data_begin
// CHECK: llvm.mlir.addressof @acc.ident.9.4.{{[0-9]+}}
// CHECK: llvm.call @__tgt_acc_data_end
func.func @mapping_exit_location(%arg0: !llvm.ptr) {
%size = arith.constant 4 : i64
%map = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(i32)
size(%size : i64) exitLoc(loc("end.mlir":9:4)) descKind(none)
mapFlags(to, from) -> !llvm.ptr loc("begin.mlir":3:2)
acc.data dataOperands(%map : !llvm.ptr) {
acc.terminator
}
return
}
// -----
// An empty data region is only a lifetime/control-flow scope. It needs no
// runtime mapping call, but its body still executes.
// CHECK-LABEL: llvm.func @empty_data
// CHECK-NOT: __tgt_acc_data_
// CHECK: llvm.return
func.func @empty_data() {
acc.data {
acc.terminator
} defaultAttr(none)
return
}
// -----
// A memref is converted to a multi-field LLVM aggregate. The lowering emits
// one mapped object per field, so the mapping arrays have that many entries.
// CHECK-LABEL: llvm.func @memref_fields
// CHECK-COUNT-5: llvm.extractvalue
// CHECK: %[[FIVE:.*]] = llvm.mlir.constant(5 : i32) : i32
// CHECK: %[[ELEMENT_SIZE:.*]] = llvm.mlir.constant(8 : i64) : i64
// CHECK: %[[MEMREF_DESC:.*]] = llvm.mlir.zero : !llvm.struct<(i32, i8, i64, ptr)>
// CHECK: %[[RANK:.*]] = llvm.mlir.constant(1 : i8) : i8
// CHECK: %[[WITH_RANK:.*]] = llvm.insertvalue %[[RANK]], %[[MEMREF_DESC]][1]
// CHECK: %[[WITH_SIZE:.*]] = llvm.insertvalue %[[ELEMENT_SIZE]], %[[WITH_RANK]][2]
// CHECK: %[[MEMREF_VERSION:.*]] = llvm.mlir.constant(2 : i32) : i32
// CHECK: llvm.insertvalue %[[MEMREF_VERSION]], %{{.*}}[0]
// CHECK: llvm.call @__tgt_acc_data_begin
func.func @memref_fields(%arg0: memref<?xf64>) {
%map = acc.copyin varPtr(%arg0 : memref<?xf64>)
dataClause(acc_copyin) -> memref<?xf64>
acc.data dataOperands(%map : memref<?xf64>) {
acc.terminator
}
acc.delete accPtr(%map : memref<?xf64>) dataClause(acc_copyin)
return
}
// -----
// Every acc.terminator in a multi-block structured region branches to the
// continuation after the data-end call.
// CHECK-LABEL: llvm.func @multiblock_data
// CHECK: llvm.call @__tgt_acc_data_begin
// CHECK: llvm.br ^[[BODY:bb[0-9]+]]
// CHECK: ^[[BODY]]:
// CHECK: llvm.cond_br %arg1, ^[[LEFT:bb[0-9]+]], ^[[RIGHT:bb[0-9]+]]
// CHECK: ^[[LEFT]]:
// CHECK: llvm.br ^[[CONT:bb[0-9]+]]
// CHECK: ^[[RIGHT]]:
// CHECK: llvm.br ^[[CONT]]
// CHECK: ^[[CONT]]:
// CHECK: llvm.call @__tgt_acc_data_end
func.func @multiblock_data(%arg0: !llvm.ptr, %cond: i1) {
%size = arith.constant 4 : i64
%map = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(i32)
size(%size : i64) elementSize(4)
descKind(none)
mapFlags(to, from) -> !llvm.ptr
acc.data dataOperands(%map : !llvm.ptr) {
cf.cond_br %cond, ^left, ^right
^left:
acc.terminator
^right:
acc.terminator
}
return
}
// -----
// An object mapped by value is sized from what is passed to the runtime rather
// than from the stated size of the object it was read from.
// CHECK-LABEL: llvm.func @literal_size
// CHECK: %[[SIZE:.*]] = llvm.mlir.constant(8 : i64) : i64
// CHECK: llvm.store %[[SIZE]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_enter
func.func @literal_size(%arg0: !llvm.ptr) {
%size = arith.constant 4 : i64
%map = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(i32)
size(%size : i64) elementSize(4) descKind(none)
mapFlags(to, literal) -> !llvm.ptr
acc.enter_data dataOperands(%map : !llvm.ptr)
return
}
// -----
// A stride already expressed in bytes is copied directly into the descriptor.
// CHECK-LABEL: llvm.func @byte_stride
// CHECK: %[[STRIDE:.*]] = llvm.mlir.constant(16 : i64) : i64
// CHECK-NOT: llvm.mul
// CHECK: llvm.store %[[STRIDE]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_enter
func.func @byte_stride(%arg0: !llvm.ptr) {
%c0 = arith.constant 0 : index
%c3 = arith.constant 3 : index
%c4 = arith.constant 4 : index
%c16 = arith.constant 16 : index
%bound = acc.bounds lowerbound(%c0 : index) upperbound(%c3 : index)
extent(%c4 : index) stride(%c16 : index) startIdx(%c0 : index)
strideInBytes(true)
%map = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(tensor<?xi32>)
bounds(%bound) elementSize(4) descKind(openacc)
mapFlags(to) -> !llvm.ptr
acc.enter_data dataOperands(%map : !llvm.ptr)
return
}
// -----
// Extents retain every full source dimension for a multidimensional section.
// CHECK-LABEL: llvm.func @multidimensional_extents
// CHECK-DAG: %[[E5:.*]] = llvm.mlir.constant(5 : i64) : i64
// CHECK-DAG: %[[E12:.*]] = llvm.mlir.constant(12 : i64) : i64
// CHECK-DAG: %[[E13:.*]] = llvm.mlir.constant(13 : i64) : i64
// CHECK: %[[RANK:.*]] = llvm.mlir.constant(4 : i8) : i8
// CHECK: llvm.store %[[E13]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.store %[[E13]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.store %[[E12]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.store %[[E5]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.insertvalue %[[RANK]], %{{.*}}[1]
// CHECK: llvm.call @__tgt_acc_data_enter
func.func @multidimensional_extents(%arg0: !llvm.ptr) {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c4 = arith.constant 4 : index
%c5 = arith.constant 5 : index
%c11 = arith.constant 11 : index
%c12 = arith.constant 12 : index
%c13 = arith.constant 13 : index
%b0 = acc.bounds lowerbound(%c0 : index) upperbound(%c4 : index)
extent(%c5 : index) sourceExtent(%c13 : index)
stride(%c1 : index) startIdx(%c0 : index)
%b1 = acc.bounds lowerbound(%c0 : index) upperbound(%c4 : index)
extent(%c5 : index) sourceExtent(%c13 : index)
stride(%c1 : index) startIdx(%c0 : index)
%b2 = acc.bounds lowerbound(%c0 : index) upperbound(%c11 : index)
extent(%c12 : index) sourceExtent(%c12 : index)
stride(%c1 : index) startIdx(%c0 : index)
%b3 = acc.bounds lowerbound(%c0 : index) upperbound(%c4 : index)
extent(%c5 : index) sourceExtent(%c5 : index)
stride(%c1 : index) startIdx(%c0 : index)
%map = acc.map_info varPtr(%arg0 : !llvm.ptr)
varType(tensor<?x?x?x?xf32>) bounds(%b0, %b1, %b2, %b3)
elementSize(4) descKind(openacc) mapFlags(to) -> !llvm.ptr
acc.enter_data dataOperands(%map : !llvm.ptr)
return
}
// -----
memref.global @device_global : memref<4xf32> = uninitialized
// A device-resident object reached through a global symbol outlives the region
// that states it, so its mapping is not turned into a deletion the way the
// mapping of a local one is.
// CHECK-LABEL: llvm.func @global_device_resident
// CHECK: %[[ENTER:.*]] = llvm.mlir.constant(262144 : i64) : i64
// CHECK: llvm.store %[[ENTER]], %{{.*}} : i64, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_begin
// CHECK: %[[EXIT:.*]] = llvm.mlir.constant(262144 : i64) : i64
// CHECK: llvm.store %[[EXIT]], %{{.*}} : i64, !llvm.ptr
// CHECK-NOT: llvm.mlir.constant(262152 : i64) : i64
// CHECK: llvm.call @__tgt_acc_data_end
func.func @global_device_resident() {
%global = memref.get_global @device_global : memref<4xf32>
%map = acc.map_info varPtr(%global : memref<4xf32>) varType(f32)
elementSize(4) descKind(none)
mapFlags(device_resident) -> memref<4xf32>
acc.data dataOperands(%map : memref<4xf32>) {
acc.terminator
}
return
}
// -----
// Named mappings become string globals whose addresses fill ArgNames; a mapping
// that states no name leaves a null slot instead, so no second name global is
// created.
// CHECK: llvm.mlir.global internal constant @acc.var_name.x("x\00")
// CHECK-NOT: @acc.var_name.
// CHECK-LABEL: llvm.func @mapping_names
// CHECK: %[[NAME:.*]] = llvm.mlir.addressof @acc.var_name.x
// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NAME]]
// CHECK: llvm.store %[[GEP]], %{{.*}} : !llvm.ptr, !llvm.ptr
// CHECK: llvm.call @__tgt_acc_data_enter
func.func @mapping_names(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {
%size = arith.constant 4 : i64
%named = acc.map_info varPtr(%arg0 : !llvm.ptr) varType(i32)
size(%size : i64) name("x") descKind(none)
mapFlags(to) -> !llvm.ptr
%unnamed = acc.map_info varPtr(%arg1 : !llvm.ptr) varType(i32)
size(%size : i64) descKind(none)
mapFlags(to) -> !llvm.ptr
acc.enter_data dataOperands(%named, %unnamed : !llvm.ptr, !llvm.ptr)
return
}
// -----
// create allocates without a copy, copyin_readonly copies to the device, and
// attach/detach state the attachment address, and the attach clause.
// CHECK-LABEL: llvm.func @create_readonly_detach
// CHECK-DAG: %[[TO:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK-DAG: %[[ATTACH:.*]] = llvm.mlir.constant(8388624 : i64) : i64
// CHECK-DAG: llvm.store %[[TO]], %{{.*}} : i64, !llvm.ptr
// CHECK-DAG: llvm.store %[[ATTACH]], %{{.*}} : i64, !llvm.ptr
// CHECK-NOT: llvm.mlir.constant(3 : i64)
// CHECK: llvm.call @__tgt_acc_data_begin
func.func @create_readonly_detach(%arg0: !llvm.ptr, %arg1: !llvm.ptr,
%arg2: !llvm.ptr) {
%create = acc.create varPtr(%arg0 : !llvm.ptr) varType(i32) -> !llvm.ptr
%readonly = acc.copyin varPtr(%arg1 : !llvm.ptr) varType(i32)
dataClause(acc_copyin_readonly) -> !llvm.ptr
%attach = acc.attach varPtr(%arg2 : !llvm.ptr) varType(i32) -> !llvm.ptr
acc.data dataOperands(%create, %readonly, %attach
: !llvm.ptr, !llvm.ptr, !llvm.ptr) {
acc.terminator
}
acc.delete accPtr(%create : !llvm.ptr)
acc.delete accPtr(%readonly : !llvm.ptr) dataClause(acc_copyin_readonly)
acc.detach accPtr(%attach : !llvm.ptr)
return
}
// -----
// Bounds on a memref wrap the memref descriptor in the OpenACC overlay, so the
// version carries both kinds.
// CHECK-LABEL: llvm.func @memref_bounded
// CHECK-COUNT-5: llvm.extractvalue
// CHECK: %[[ELEMENT_SIZE:.*]] = llvm.mlir.constant(4 : i64) : i64
// CHECK: %[[MEMREF_DESC:.*]] = llvm.mlir.zero : !llvm.struct<(i32, i8, i64, ptr)>
// CHECK: %[[RANK:.*]] = llvm.mlir.constant(1 : i8) : i8
// CHECK: %[[WITH_RANK:.*]] = llvm.insertvalue %[[RANK]], %[[MEMREF_DESC]][1]
// CHECK: llvm.insertvalue %[[ELEMENT_SIZE]], %[[WITH_RANK]][2]
// memref | openacc = 2 | 4096.
// CHECK: %[[VERSION:.*]] = llvm.mlir.constant(4098 : i32) : i32
// CHECK: llvm.insertvalue %[[VERSION]], %{{.*}}[0]
// CHECK: llvm.call @__tgt_acc_data_begin
func.func @memref_bounded(%arg0: memref<?xf32>) {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%c3 = arith.constant 3 : index
%c4 = arith.constant 4 : index
%bound = acc.bounds lowerbound(%c0 : index) upperbound(%c3 : index)
extent(%c4 : index) stride(%c1 : index) startIdx(%c0 : index)
%map = acc.copyin varPtr(%arg0 : memref<?xf32>) varType(tensor<?xf32>)
bounds(%bound) dataClause(acc_copyin) -> memref<?xf32>
acc.data dataOperands(%map : memref<?xf32>) {
acc.terminator
}
acc.delete accPtr(%map : memref<?xf32>) dataClause(acc_copyin)
return
}