Skip to content

Commit 6a62707

Browse files
authored
[Flang][OpenMP][MLIR] Initial array section mapping MLIR -> LLVM-IR lowering utilising omp.bounds (#68689)
This patch seeks to add initial lowering of OpenMP array sections within target region map clauses from MLIR to LLVM IR. This patch seeks to support fixed sized contiguous (don't think OpenMP supports anything other than contiguous sections from my reading but i could be wrong) arrays initially, before looking toward assumed size and shaped arrays. The patch also currently does not include stride, it's left for future work. Although, assumed size works in some fashion (dummy arguments) with some minor alterations to the OMPEarlyOutliner, so it is possible changes made in the IsolatedFromAbove series may allow this to work with no further required patches. It utilises the generated omp.bounds to calculate the size of the mapped OpenMP array (both for sectioned and un-sectioned arrays) as well as the offset to be passed to the kernel argument structure. Alongside these changes some refactoring of how map data is handled is attempted, using a new MapData structure to keep track of information utilised in the lowering of mapped values. The initial addition of a more complex createDeviceArgumentAccessor that utilises capture kinds similarly to (and loosely based on) Clang to generate different kernel argument accesses is also added. A similar function for altering how the kernel argument is passed to the kernel argument structure on the host is also utilised (createAlteredByCaptureMap), which allows modification of the pointer/basePointer based on their capture (and bounds information). It's of note ByRef, is the default for explicit mappings and ByCopy will be the default for implicit captures, so the former is currently tested in this patch and the latter is not for the moment.
1 parent 4bbb2bc commit 6a62707

10 files changed

+710
-165
lines changed

mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp

Lines changed: 389 additions & 146 deletions
Large diffs are not rendered by default.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2+
3+
// This test checks the offload sizes provided to the OpenMP kernel argument
4+
// structure are correct when lowering to LLVM-IR from MLIR with 3-D bounds
5+
// provided for a 3-D array. One with full default size, and the other with
6+
// a user specified OpenMP array sectioning. We expect the default sized
7+
// array bounds to lower to the full size of the array and the sectioned
8+
// array to be the size of 3*3*1*element-byte-size (36 bytes in this case).
9+
10+
module attributes {omp.is_target_device = false} {
11+
llvm.func @_3d_target_array_section() {
12+
%0 = llvm.mlir.addressof @_QFEinarray : !llvm.ptr
13+
%1 = llvm.mlir.addressof @_QFEoutarray : !llvm.ptr
14+
%2 = llvm.mlir.constant(1 : index) : i64
15+
%3 = llvm.mlir.constant(0 : index) : i64
16+
%4 = llvm.mlir.constant(2 : index) : i64
17+
%5 = omp.bounds lower_bound(%3 : i64) upper_bound(%4 : i64) stride(%2 : i64) start_idx(%2 : i64)
18+
%6 = omp.bounds lower_bound(%2 : i64) upper_bound(%2 : i64) stride(%2 : i64) start_idx(%2 : i64)
19+
%7 = omp.map_info var_ptr(%0 : !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>) map_clauses(tofrom) capture(ByRef) bounds(%5, %5, %6) -> !llvm.ptr {name = "inarray(1:3,1:3,2:2)"}
20+
%8 = omp.map_info var_ptr(%1 : !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>) map_clauses(tofrom) capture(ByRef) bounds(%5, %5, %5) -> !llvm.ptr {name = "outarray(1:3,1:3,1:3)"}
21+
omp.target map_entries(%7, %8 : !llvm.ptr, !llvm.ptr) {
22+
%9 = llvm.mlir.constant(0 : i64) : i64
23+
%10 = llvm.mlir.constant(1 : i64) : i64
24+
%11 = llvm.getelementptr %0[0, %10, %9, %9] : (!llvm.ptr, i64, i64, i64) -> !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>
25+
%12 = llvm.load %11 : !llvm.ptr -> i32
26+
%13 = llvm.getelementptr %1[0, %10, %9, %9] : (!llvm.ptr, i64, i64, i64) -> !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>
27+
llvm.store %12, %13 : i32, !llvm.ptr
28+
omp.terminator
29+
}
30+
llvm.return
31+
}
32+
llvm.mlir.global internal @_QFEinarray() {addr_space = 0 : i32} : !llvm.array<3 x array<3 x array<3 x i32>>> {
33+
%0 = llvm.mlir.zero : !llvm.array<3 x array<3 x array<3 x i32>>>
34+
llvm.return %0 : !llvm.array<3 x array<3 x array<3 x i32>>>
35+
}
36+
llvm.mlir.global internal @_QFEoutarray() {addr_space = 0 : i32} : !llvm.array<3 x array<3 x array<3 x i32>>> {
37+
%0 = llvm.mlir.zero : !llvm.array<3 x array<3 x array<3 x i32>>>
38+
llvm.return %0 : !llvm.array<3 x array<3 x array<3 x i32>>>
39+
}
40+
}
41+
42+
// CHECK: @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 36, i64 108]
43+
// CHECK: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 35, i64 35]
44+
// CHECKL: @.offload_mapnames = private constant [2 x ptr] [ptr @0, ptr @1]
45+
46+
// CHECK: define void @_3d_target_array_section()
47+
48+
// CHECK: %[[OFFLOADBASEPTRS:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 0
49+
// CHECK: store ptr @_QFEinarray, ptr %[[OFFLOADBASEPTRS]], align 8
50+
// CHECK: %[[OFFLOADPTRS:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 0
51+
// CHECK: store ptr getelementptr inbounds ([3 x [3 x [3 x i32]]], ptr @_QFEinarray, i64 0, i64 1, i64 0, i64 0), ptr %[[OFFLOADPTRS]], align 8
52+
53+
// CHECK: %[[OFFLOADBASEPTRS2:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 1
54+
// CHECK: store ptr @_QFEoutarray, ptr %[[OFFLOADBASEPTRS2]], align 8
55+
// CHECK: %[[OFFLOADPTRS2:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 1
56+
// CHECK: store ptr @_QFEoutarray, ptr %[[OFFLOADPTRS2]], align 8
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2+
3+
module attributes {omp.is_target_device = true} {
4+
llvm.func @_QQmain() attributes {fir.bindc_name = "main"} {
5+
%0 = llvm.mlir.addressof @_QFEi : !llvm.ptr
6+
%1 = llvm.mlir.addressof @_QFEsp : !llvm.ptr
7+
%2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "sp"}
8+
%3 = omp.map_info var_ptr(%0 : !llvm.ptr, i32) map_clauses(to) capture(ByCopy) -> !llvm.ptr {name = "i"}
9+
omp.target map_entries(%2, %3 : !llvm.ptr, !llvm.ptr) {
10+
%4 = llvm.load %0 : !llvm.ptr -> i32
11+
llvm.store %4, %1 : i32, !llvm.ptr
12+
omp.terminator
13+
}
14+
llvm.return
15+
}
16+
llvm.mlir.global internal @_QFEi() {addr_space = 0 : i32} : i32 {
17+
%0 = llvm.mlir.constant(1 : i32) : i32
18+
llvm.return %0 : i32
19+
}
20+
llvm.mlir.global internal @_QFEsp() {addr_space = 0 : i32} : i32 {
21+
%0 = llvm.mlir.constant(0 : i32) : i32
22+
llvm.return %0 : i32
23+
}
24+
}
25+
26+
// CHECK: define {{.*}} void @__omp_offloading_{{.*}}_{{.*}}__QQmain_l{{.*}}(ptr %[[ARG_BYREF:.*]], ptr %[[ARG_BYCOPY:.*]]) {
27+
28+
// CHECK: entry:
29+
// CHECK: %[[ALLOCA_BYREF:.*]] = alloca ptr, align 8
30+
// CHECK: store ptr %[[ARG_BYREF]], ptr %[[ALLOCA_BYREF]], align 8
31+
// CHECK: %[[ALLOCA_BYCOPY:.*]] = alloca ptr, align 8
32+
// CHECK: store ptr %[[ARG_BYCOPY]], ptr %[[ALLOCA_BYCOPY]], align 8
33+
34+
// CHECK: user_code.entry: ; preds = %entry
35+
// CHECK: %[[LOAD_BYREF:.*]] = load ptr, ptr %[[ALLOCA_BYREF]], align 8
36+
// CHECK: br label %omp.target
37+
38+
// CHECK: omp.target: ; preds = %user_code.entry
39+
// CHECK: %[[VAL_LOAD_BYCOPY:.*]] = load i32, ptr %[[ALLOCA_BYCOPY]], align 4
40+
// CHECK: store i32 %[[VAL_LOAD_BYCOPY]], ptr %[[LOAD_BYREF]], align 4
41+
// CHECK: br label %omp.region.cont
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2+
3+
module attributes {omp.is_target_device = false} {
4+
llvm.func @_QQmain() attributes {fir.bindc_name = "main"} {
5+
%0 = llvm.mlir.addressof @_QFEi : !llvm.ptr
6+
%1 = llvm.mlir.addressof @_QFEsp : !llvm.ptr
7+
%2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "sp"}
8+
%3 = omp.map_info var_ptr(%0 : !llvm.ptr, i32) map_clauses(to) capture(ByCopy) -> !llvm.ptr {name = "i"}
9+
omp.target map_entries(%2, %3 : !llvm.ptr, !llvm.ptr) {
10+
%4 = llvm.load %0 : !llvm.ptr -> i32
11+
llvm.store %4, %1 : i32, !llvm.ptr
12+
omp.terminator
13+
}
14+
llvm.return
15+
}
16+
llvm.mlir.global internal @_QFEi() {addr_space = 0 : i32} : i32 {
17+
%0 = llvm.mlir.constant(1 : i32) : i32
18+
llvm.return %0 : i32
19+
}
20+
llvm.mlir.global internal @_QFEsp() {addr_space = 0 : i32} : i32 {
21+
%0 = llvm.mlir.constant(0 : i32) : i32
22+
llvm.return %0 : i32
23+
}
24+
}
25+
26+
// CHECK: define void @_QQmain() {
27+
// CHECK: %[[BYCOPY_ALLOCA:.*]] = alloca ptr, align 8
28+
29+
// CHECK: entry: ; preds = %0
30+
// CHECK: %[[LOAD_VAL:.*]] = load i32, ptr @_QFEi, align 4
31+
// CHECK: store i32 %[[LOAD_VAL]], ptr %[[BYCOPY_ALLOCA]], align 4
32+
// CHECK: %[[BYCOPY_LOAD:.*]] = load ptr, ptr %[[BYCOPY_ALLOCA]], align 8
33+
34+
// CHECK: %[[BASEPTR_BYREF:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 0
35+
// CHECK: store ptr @_QFEsp, ptr %[[BASEPTR_BYREF]], align 8
36+
// CHECK: %[[OFFLOADPTR_BYREF:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 0
37+
// CHECK: store ptr @_QFEsp, ptr %[[OFFLOADPTR_BYREF]], align 8
38+
39+
// CHECK: %[[BASEPTR_BYCOPY:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 1
40+
// CHECK: store ptr %[[BYCOPY_LOAD]], ptr %[[BASEPTR_BYCOPY]], align 8
41+
// CHECK: %[[OFFLOADPTR_BYREF:.*]] = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 1
42+
// CHECK: store ptr %[[BYCOPY_LOAD]], ptr %[[OFFLOADPTR_BYREF]], align 8

mlir/test/Target/LLVMIR/omptarget-llvm.mlir

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,20 @@ llvm.func @_QPopenmp_target_data() {
3838

3939
// -----
4040

41-
llvm.func @_QPopenmp_target_data_region(%1 : !llvm.ptr) {
42-
%2 = omp.map_info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
43-
omp.target_data map_entries(%2 : !llvm.ptr) {
44-
%3 = llvm.mlir.constant(99 : i32) : i32
45-
%4 = llvm.mlir.constant(1 : i64) : i64
46-
%5 = llvm.mlir.constant(1 : i64) : i64
47-
%6 = llvm.mlir.constant(0 : i64) : i64
48-
%7 = llvm.getelementptr %1[0, %6] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<1024 x i32>
49-
llvm.store %3, %7 : i32, !llvm.ptr
41+
llvm.func @_QPopenmp_target_data_region(%0 : !llvm.ptr) {
42+
%1 = llvm.mlir.constant(1023 : index) : i64
43+
%2 = llvm.mlir.constant(0 : index) : i64
44+
%3 = llvm.mlir.constant(1024 : index) : i64
45+
%4 = llvm.mlir.constant(1 : index) : i64
46+
%5 = omp.bounds lower_bound(%2 : i64) upper_bound(%1 : i64) extent(%3 : i64) stride(%4 : i64) start_idx(%4 : i64)
47+
%6 = omp.map_info var_ptr(%0 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%5) -> !llvm.ptr {name = ""}
48+
omp.target_data map_entries(%6 : !llvm.ptr) {
49+
%7 = llvm.mlir.constant(99 : i32) : i32
50+
%8 = llvm.mlir.constant(1 : i64) : i64
51+
%9 = llvm.mlir.constant(1 : i64) : i64
52+
%10 = llvm.mlir.constant(0 : i64) : i64
53+
%11 = llvm.getelementptr %0[0, %10] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<1024 x i32>
54+
llvm.store %7, %11 : i32, !llvm.ptr
5055
omp.terminator
5156
}
5257
llvm.return
@@ -92,16 +97,36 @@ llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr, %3 : !llvm.ptr) {
9297
%11 = llvm.mlir.constant(10 : i32) : i32
9398
%12 = llvm.icmp "slt" %10, %11 : i32
9499
%13 = llvm.load %5 : !llvm.ptr -> i32
95-
%map1 = omp.map_info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
96-
%map2 = omp.map_info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""}
100+
%14 = llvm.mlir.constant(1023 : index) : i64
101+
%15 = llvm.mlir.constant(0 : index) : i64
102+
%16 = llvm.mlir.constant(1024 : index) : i64
103+
%17 = llvm.mlir.constant(1 : index) : i64
104+
%18 = omp.bounds lower_bound(%15 : i64) upper_bound(%14 : i64) extent(%16 : i64) stride(%17 : i64) start_idx(%17 : i64)
105+
%map1 = omp.map_info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(to) capture(ByRef) bounds(%18) -> !llvm.ptr {name = ""}
106+
%19 = llvm.mlir.constant(511 : index) : i64
107+
%20 = llvm.mlir.constant(0 : index) : i64
108+
%21 = llvm.mlir.constant(512 : index) : i64
109+
%22 = llvm.mlir.constant(1 : index) : i64
110+
%23 = omp.bounds lower_bound(%20 : i64) upper_bound(%19 : i64) extent(%21 : i64) stride(%22 : i64) start_idx(%22 : i64)
111+
%map2 = omp.map_info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%23) -> !llvm.ptr {name = ""}
97112
omp.target_enter_data if(%12 : i1) device(%13 : i32) map_entries(%map1, %map2 : !llvm.ptr, !llvm.ptr)
98-
%14 = llvm.load %7 : !llvm.ptr -> i32
99-
%15 = llvm.mlir.constant(10 : i32) : i32
100-
%16 = llvm.icmp "sgt" %14, %15 : i32
101-
%17 = llvm.load %5 : !llvm.ptr -> i32
102-
%map3 = omp.map_info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
103-
%map4 = omp.map_info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""}
104-
omp.target_exit_data if(%16 : i1) device(%17 : i32) map_entries(%map3, %map4 : !llvm.ptr, !llvm.ptr)
113+
%24 = llvm.load %7 : !llvm.ptr -> i32
114+
%25 = llvm.mlir.constant(10 : i32) : i32
115+
%26 = llvm.icmp "sgt" %24, %25 : i32
116+
%27 = llvm.load %5 : !llvm.ptr -> i32
117+
%28 = llvm.mlir.constant(1023 : index) : i64
118+
%29 = llvm.mlir.constant(0 : index) : i64
119+
%30 = llvm.mlir.constant(1024 : index) : i64
120+
%31 = llvm.mlir.constant(1 : index) : i64
121+
%32 = omp.bounds lower_bound(%29 : i64) upper_bound(%28 : i64) extent(%30 : i64) stride(%31 : i64) start_idx(%31 : i64)
122+
%map3 = omp.map_info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%32) -> !llvm.ptr {name = ""}
123+
%33 = llvm.mlir.constant(511 : index) : i64
124+
%34 = llvm.mlir.constant(0 : index) : i64
125+
%35 = llvm.mlir.constant(512 : index) : i64
126+
%36 = llvm.mlir.constant(1 : index) : i64
127+
%37 = omp.bounds lower_bound(%34 : i64) upper_bound(%33 : i64) extent(%35 : i64) stride(%36 : i64) start_idx(%36 : i64)
128+
%map4 = omp.map_info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%37) -> !llvm.ptr {name = ""}
129+
omp.target_exit_data if(%26 : i1) device(%27 : i32) map_entries(%map3, %map4 : !llvm.ptr, !llvm.ptr)
105130
llvm.return
106131
}
107132

mlir/test/Target/LLVMIR/omptarget-region-parallel-llvm.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ module attributes {omp.is_target_device = false} {
3838
// CHECK: store ptr %[[ADDR_B]], ptr %[[GEP2]], align 8
3939
// CHECK: %[[GEP3:.*]] = getelementptr { ptr, ptr, ptr }, ptr %[[STRUCTARG]], i32 0, i32 2
4040
// CHECK: store ptr %[[ADDR_C]], ptr %[[GEP3]], align 8
41-
// CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @1, i32 1, ptr @__omp_offloading_[[DEV]]_[[FIL]]_omp_target_region__l[[LINE]]..omp_par, ptr %[[STRUCTARG]])
41+
// CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @{{.*}}, i32 1, ptr @__omp_offloading_[[DEV]]_[[FIL]]_omp_target_region__l[[LINE]]..omp_par, ptr %[[STRUCTARG]])
4242

4343

4444
// CHECK: define internal void @__omp_offloading_[[DEV]]_[[FIL]]_omp_target_region__l[[LINE]]..omp_par(ptr noalias %tid.addr, ptr noalias %zero.addr, ptr %[[STRUCTARG2:.*]]) #0 {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
! Basic offloading test of arrays with provided lower
2+
! and upper bounds as specified by OpenMP's sectioning
3+
! REQUIRES: flang, amdgcn-amd-amdhsa
4+
! UNSUPPORTED: nvptx64-nvidia-cuda
5+
! UNSUPPORTED: nvptx64-nvidia-cuda-LTO
6+
! UNSUPPORTED: aarch64-unknown-linux-gnu
7+
! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO
8+
! UNSUPPORTED: x86_64-pc-linux-gnu
9+
! UNSUPPORTED: x86_64-pc-linux-gnu-LTO
10+
11+
! RUN: %libomptarget-compile-fortran-run-and-check-generic
12+
program main
13+
implicit none
14+
integer :: write_arr(10) = (/0,0,0,0,0,0,0,0,0,0/)
15+
integer :: read_arr(10) = (/1,2,3,4,5,6,7,8,9,10/)
16+
integer :: i = 2
17+
18+
!$omp target map(to:read_arr(2:5)) map(from:write_arr(2:5)) map(tofrom:i)
19+
do i = 2, 5
20+
write_arr(i) = read_arr(i)
21+
end do
22+
!$omp end target
23+
24+
print *, write_arr(:)
25+
end program
26+
27+
! CHECK: 0 2 3 4 5 0 0 0 0 0
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
! Basic offloading test of a regular array explicitly
2+
! passed within a target region
3+
! REQUIRES: flang, amdgcn-amd-amdhsa
4+
! UNSUPPORTED: nvptx64-nvidia-cuda
5+
! UNSUPPORTED: nvptx64-nvidia-cuda-LTO
6+
! UNSUPPORTED: aarch64-unknown-linux-gnu
7+
! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO
8+
! UNSUPPORTED: x86_64-pc-linux-gnu
9+
! UNSUPPORTED: x86_64-pc-linux-gnu-LTO
10+
11+
! RUN: %libomptarget-compile-fortran-run-and-check-generic
12+
program main
13+
implicit none
14+
integer :: inArray(3,3,3)
15+
integer :: outArray(3,3,3)
16+
integer :: i, j, k
17+
18+
do i = 1, 3
19+
do j = 1, 3
20+
do k = 1, 3
21+
inArray(i, j, k) = 42
22+
outArray(i, j, k) = 0
23+
end do
24+
end do
25+
end do
26+
27+
!$omp target map(tofrom:inArray(1:3, 1:3, 2:2), outArray(1:3, 1:3, 1:3), j, k)
28+
do j = 1, 3
29+
do k = 1, 3
30+
outArray(k, j, 2) = inArray(k, j, 2)
31+
end do
32+
end do
33+
!$omp end target
34+
35+
print *, outArray
36+
37+
end program
38+
39+
! CHECK: 0 0 0 0 0 0 0 0 0 42 42 42 42 42 42 42 42 42 0 0 0 0 0 0 0 0 0
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
! Basic offloading test of a regular array explicitly
2+
! passed within a target region
3+
! REQUIRES: flang, amdgcn-amd-amdhsa
4+
! UNSUPPORTED: nvptx64-nvidia-cuda
5+
! UNSUPPORTED: nvptx64-nvidia-cuda-LTO
6+
! UNSUPPORTED: aarch64-unknown-linux-gnu
7+
! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO
8+
! UNSUPPORTED: x86_64-pc-linux-gnu
9+
! UNSUPPORTED: x86_64-pc-linux-gnu-LTO
10+
11+
! RUN: %libomptarget-compile-fortran-run-and-check-generic
12+
program main
13+
implicit none
14+
integer :: x(2,2,2)
15+
integer :: i = 1, j = 1, k = 1
16+
integer :: counter = 1
17+
do i = 1, 2
18+
do j = 1, 2
19+
do k = 1, 2
20+
x(i, j, k) = 0
21+
end do
22+
end do
23+
end do
24+
25+
!$omp target map(tofrom:x, i, j, k, counter)
26+
do i = 1, 2
27+
do j = 1, 2
28+
do k = 1, 2
29+
x(i, j, k) = counter
30+
counter = counter + 1
31+
end do
32+
end do
33+
end do
34+
!$omp end target
35+
36+
do i = 1, 2
37+
do j = 1, 2
38+
do k = 1, 2
39+
print *, x(i, j, k)
40+
end do
41+
end do
42+
end do
43+
end program main
44+
45+
! CHECK: 1 2 3 4 5 6 7 8
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
! Basic offloading test of a regular array explicitly
2+
! passed within a target region
3+
! REQUIRES: flang, amdgcn-amd-amdhsa
4+
! UNSUPPORTED: nvptx64-nvidia-cuda
5+
! UNSUPPORTED: nvptx64-nvidia-cuda-LTO
6+
! UNSUPPORTED: aarch64-unknown-linux-gnu
7+
! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO
8+
! UNSUPPORTED: x86_64-pc-linux-gnu
9+
! UNSUPPORTED: x86_64-pc-linux-gnu-LTO
10+
11+
! RUN: %libomptarget-compile-fortran-run-and-check-generic
12+
program main
13+
integer :: x(10) = (/0,0,0,0,0,0,0,0,0,0/)
14+
integer :: i = 1
15+
integer :: j = 11
16+
17+
!$omp target map(tofrom:x, i, j)
18+
do while (i <= j)
19+
x(i) = i;
20+
i = i + 1
21+
end do
22+
!$omp end target
23+
24+
PRINT *, x(:)
25+
end program main
26+
27+
! CHECK: 1 2 3 4 5 6 7 8 9 10

0 commit comments

Comments
 (0)