blob: 4bb188c8464803f31e781e533fd21adc3d002929 [file] [edit]
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
// This test checks that the begin-pointer offset for a map of a single element
// of a multi-dimensional Fortran array (accessed through a descriptor, so the
// map has a non-array base type and carries per-dimension bounds) is linearized
// using the per-dimension strides carried on the omp.map.bounds operations,
// rather than the section extents. For a single-element section all extents are
// 1, so an extent-based fold would collapse every element onto the same begin
// pointer. The offset must instead be:
//
// sum_d lower_bound[d] * stride[d]
//
// Here the strides are provided in bytes (stride_in_bytes(true)) with distinct
// values 8 and 256, so the offset is lb0*8 + lb1*256 applied through a byte
// (i8) GEP.
module attributes {omp.is_target_device = false, omp.target_triples = ["amdgcn-amd-amdhsa"]} {
llvm.func @single_element_2d_map(%arg0: !llvm.ptr, %lb0: i64, %lb1: i64) {
%c1 = llvm.mlir.constant(1 : i64) : i64
%stride0 = llvm.mlir.constant(8 : i64) : i64
%stride1 = llvm.mlir.constant(256 : i64) : i64
%baddr = llvm.getelementptr %arg0[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>
%b0 = omp.map.bounds lower_bound(%lb0 : i64) upper_bound(%lb0 : i64) extent(%c1 : i64) stride(%stride0 : i64) start_idx(%c1 : i64) stride_in_bytes(true)
%b1 = omp.map.bounds lower_bound(%lb1 : i64) upper_bound(%lb1 : i64) extent(%c1 : i64) stride(%stride1 : i64) start_idx(%c1 : i64) stride_in_bytes(true)
%m0 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%baddr : !llvm.ptr, f64) bounds(%b0, %b1) name("arr(i,j)") -> !llvm.ptr
%m1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<2 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) members(%m0 : [0] : !llvm.ptr) name("arr(i,j)") -> !llvm.ptr
omp.target kernel_type(generic) map_entries(%m0 -> %a0, %m1 -> %a1 : !llvm.ptr, !llvm.ptr) {
omp.terminator
}
llvm.return
}
}
// CHECK: define void @single_element_2d_map(ptr %[[ARG0:.*]], i64 %[[LB0:.*]], i64 %[[LB1:.*]])
// CHECK: %[[T0:.*]] = mul i64 %[[LB0]], 8
// CHECK: %[[OFF0:.*]] = add i64 0, %[[T0]]
// CHECK: %[[T1:.*]] = mul i64 %[[LB1]], 256
// CHECK: %[[OFF:.*]] = add i64 %[[OFF0]], %[[T1]]
// CHECK: %[[BASE:.*]] = load ptr, ptr %{{.*}}, align 8
// CHECK: %[[ARR_OFFSET:.*]] = getelementptr inbounds i8, ptr %[[BASE]], i64 %[[OFF]]