298 changes: 261 additions & 37 deletions flang/lib/Lower/OpenMP.cpp

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion flang/lib/Optimizer/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ add_flang_library(FIRTransforms
AddDebugFoundation.cpp
PolymorphicOpConversion.cpp
LoopVersioning.cpp
OMPEarlyOutlining.cpp
OMPFunctionFiltering.cpp
OMPMarkDeclareTarget.cpp
VScaleAttr.cpp
Expand Down
303 changes: 0 additions & 303 deletions flang/lib/Optimizer/Transforms/OMPEarlyOutlining.cpp

This file was deleted.

52 changes: 52 additions & 0 deletions flang/test/Driver/OpenMP/map-types-and-sizes.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
!RUN: %flang_fc1 -emit-llvm -fopenmp %s -o - | FileCheck %s

!===============================================================================
! Check MapTypes for target implicit captures
!===============================================================================

!CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 4]
!CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 800]
subroutine mapType_scalar
integer :: a
!$omp target
a = 10
!$omp end target
end subroutine mapType_scalar

!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 4096]
!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 547]
subroutine mapType_array
integer :: a(1024)
!$omp target
a(10) = 20
!$omp end target
end subroutine mapType_array

!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 8]
!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 547]
subroutine mapType_ptr
integer, pointer :: a
!$omp target
a = 10
!$omp end target
end subroutine mapType_ptr

!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [2 x i64] [i64 544, i64 800]
subroutine mapType_c_ptr
use iso_c_binding, only : c_ptr, c_loc
type(c_ptr) :: a
integer, target :: b
!$omp target
a = c_loc(b)
!$omp end target
end subroutine mapType_c_ptr

!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 1]
!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 800]
subroutine mapType_char
character :: a
!$omp target
a = 'b'
!$omp end target
end subroutine mapType_char
10 changes: 6 additions & 4 deletions flang/test/Fir/convert-to-llvm-openmp-and-fir.fir
Original file line number Diff line number Diff line change
Expand Up @@ -433,12 +433,13 @@ func.func @_QPomp_target() {
%1 = arith.subi %c512, %c1 : index
%2 = omp.bounds lower_bound(%c0 : index) upper_bound(%1 : index) extent(%c512 : index) stride(%c1 : index) start_idx(%c1 : index)
%3 = omp.map_info var_ptr(%0 : !fir.ref<!fir.array<512xi32>>, !fir.array<512xi32>) map_clauses(tofrom) capture(ByRef) bounds(%2) -> !fir.ref<!fir.array<512xi32>> {name = "a"}
omp.target thread_limit(%c64_i32 : i32) map_entries(%3 : !fir.ref<!fir.array<512xi32>>) {
omp.target thread_limit(%c64_i32 : i32) map_entries(%3 -> %arg0 : !fir.ref<!fir.array<512xi32>>) {
^bb0(%arg0: !fir.ref<!fir.array<512xi32>>):
%c10_i32 = arith.constant 10 : i32
%c1_i64 = arith.constant 1 : i64
%c1_i64_0 = arith.constant 1 : i64
%4 = arith.subi %c1_i64, %c1_i64_0 : i64
%5 = fir.coordinate_of %0, %4 : (!fir.ref<!fir.array<512xi32>>, i64) -> !fir.ref<i32>
%5 = fir.coordinate_of %arg0, %4 : (!fir.ref<!fir.array<512xi32>>, i64) -> !fir.ref<i32>
fir.store %c10_i32 to %5 : !fir.ref<i32>
omp.terminator
}
Expand All @@ -455,12 +456,13 @@ func.func @_QPomp_target() {
// CHECK: %[[UPPER:.*]] = llvm.mlir.constant(511 : index) : i64
// CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[LOWER]] : i64) upper_bound(%[[UPPER]] : i64) extent(%[[EXTENT]] : i64) stride(%[[STRIDE]] : i64) start_idx(%[[STRIDE]] : i64)
// CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%2 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !llvm.ptr {name = "a"}
// CHECK: omp.target thread_limit(%[[VAL_2]] : i32) map_entries(%[[MAP]] : !llvm.ptr) {
// CHECK: omp.target thread_limit(%[[VAL_2]] : i32) map_entries(%[[MAP]] -> %[[ARG_0:.*]] : !llvm.ptr) {
// CHECK: ^bb0(%[[ARG_0]]: !llvm.ptr):
// CHECK: %[[VAL_3:.*]] = llvm.mlir.constant(10 : i32) : i32
// CHECK: %[[VAL_4:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[VAL_5:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[VAL_6:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[VAL_7:.*]] = llvm.getelementptr %[[VAL_1]][0, %[[VAL_6]]] : (!llvm.ptr, i64) -> !llvm.ptr
// CHECK: %[[VAL_7:.*]] = llvm.getelementptr %[[ARG_0]][0, %[[VAL_6]]] : (!llvm.ptr, i64) -> !llvm.ptr
// CHECK: llvm.store %[[VAL_3]], %[[VAL_7]] : i32, !llvm.ptr
// CHECK: omp.terminator
// CHECK: }
Expand Down
119 changes: 43 additions & 76 deletions flang/test/Lower/OpenMP/FIR/array-bounds.f90
Original file line number Diff line number Diff line change
@@ -1,37 +1,22 @@
!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s --check-prefixes HOST
!RUN: %flang_fc1 -emit-fir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefixes DEVICE
!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s --check-prefixes=HOST,ALL
!RUN: %flang_fc1 -emit-fir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefixes=DEVICE,ALL

!DEVICE-LABEL: func.func @_QPread_write_section_omp_outline_0(
!DEVICE-SAME: %[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<!fir.array<10xi32>>, %[[ARG2:.*]]: !fir.ref<!fir.array<10xi32>>) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QPread_write_section"} {
!DEVICE: %[[C1:.*]] = arith.constant 1 : index
!DEVICE: %[[C2:.*]] = arith.constant 4 : index
!DEVICE: %[[C3:.*]] = arith.constant 1 : index
!DEVICE: %[[C4:.*]] = arith.constant 1 : index
!DEVICE: %[[BOUNDS0:.*]] = omp.bounds lower_bound(%[[C1]] : index) upper_bound(%[[C2]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index)
!DEVICE: %[[MAP0:.*]] = omp.map_info var_ptr(%[[ARG1]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_read(2:5)"}
!DEVICE: %[[C5:.*]] = arith.constant 1 : index
!DEVICE: %[[C6:.*]] = arith.constant 4 : index
!DEVICE: %[[C7:.*]] = arith.constant 1 : index
!DEVICE: %[[C8:.*]] = arith.constant 1 : index
!DEVICE: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) stride(%[[C8]] : index) start_idx(%[[C8]] : index)
!DEVICE: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG2]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"}
!DEVICE: omp.target map_entries(%[[MAP0]], %[[MAP1]] : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) {

!HOST-LABEL: func.func @_QPread_write_section() {
!HOST: %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFread_write_sectionEi"}
!HOST: %[[READ:.*]] = fir.address_of(@_QFread_write_sectionEsp_read) : !fir.ref<!fir.array<10xi32>>
!HOST: %[[WRITE:.*]] = fir.address_of(@_QFread_write_sectionEsp_write) : !fir.ref<!fir.array<10xi32>>
!HOST: %[[C1:.*]] = arith.constant 1 : index
!HOST: %[[C2:.*]] = arith.constant 1 : index
!HOST: %[[C3:.*]] = arith.constant 4 : index
!HOST: %[[BOUNDS0:.*]] = omp.bounds lower_bound(%[[C2]] : index) upper_bound(%[[C3]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index)
!HOST: %[[MAP0:.*]] = omp.map_info var_ptr(%[[READ]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_read(2:5)"}
!HOST: %[[C4:.*]] = arith.constant 1 : index
!HOST: %[[C5:.*]] = arith.constant 1 : index
!HOST: %[[C6:.*]] = arith.constant 4 : index
!HOST: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index)
!HOST: %[[MAP1:.*]] = omp.map_info var_ptr(%[[WRITE]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"}
!HOST: omp.target map_entries(%[[MAP0]], %[[MAP1]] : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) {
!ALL-LABEL: func.func @_QPread_write_section(
!ALL: %[[ITER:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFread_write_sectionEi"}
!ALL: %[[READ:.*]] = fir.address_of(@_QFread_write_sectionEsp_read) : !fir.ref<!fir.array<10xi32>>
!ALL: %[[WRITE:.*]] = fir.address_of(@_QFread_write_sectionEsp_write) : !fir.ref<!fir.array<10xi32>>
!ALL: %[[C1:.*]] = arith.constant 1 : index
!ALL: %[[C2:.*]] = arith.constant 1 : index
!ALL: %[[C3:.*]] = arith.constant 4 : index
!ALL: %[[BOUNDS0:.*]] = omp.bounds lower_bound(%[[C2]] : index) upper_bound(%[[C3]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index)
!ALL: %[[MAP0:.*]] = omp.map_info var_ptr(%[[READ]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_read(2:5)"}
!ALL: %[[C4:.*]] = arith.constant 1 : index
!ALL: %[[C5:.*]] = arith.constant 1 : index
!ALL: %[[C6:.*]] = arith.constant 4 : index
!ALL: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index)
!ALL: %[[MAP1:.*]] = omp.map_info var_ptr(%[[WRITE]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"}
!ALL: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ITER]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"}
!ALL: omp.target map_entries(%[[MAP0]] -> %{{.*}}, %[[MAP1]] -> %{{.*}}, %[[MAP2]] -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>, !fir.ref<i32>, index, index) {

subroutine read_write_section()
integer :: sp_read(10) = (/1,2,3,4,5,6,7,8,9,10/)
Expand All @@ -44,33 +29,22 @@ subroutine read_write_section()
!$omp end target
end subroutine read_write_section


module assumed_array_routines
contains
!DEVICE-LABEL: func.func @_QMassumed_array_routinesPassumed_shape_array_omp_outline_0(
!DEVICE-SAME: %[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG2:.*]]: !fir.ref<!fir.array<?xi32>>) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QMassumed_array_routinesPassumed_shape_array"} {
!DEVICE: %[[C0:.*]] = arith.constant 1 : index
!DEVICE: %[[C1:.*]] = arith.constant 4 : index
!DEVICE: %[[C2:.*]] = arith.constant 0 : index
!DEVICE: %[[C3:.*]]:3 = fir.box_dims %[[ARG1]], %[[C2]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
!DEVICE: %[[C4:.*]] = arith.constant 1 : index
!DEVICE: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C0]] : index) upper_bound(%[[C1]] : index) stride(%[[C3]]#2 : index) start_idx(%[[C4]] : index) {stride_in_bytes = true}
!DEVICE: %[[ARGADDR:.*]] = fir.box_addr %[[ARG1]] : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
!DEVICE: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARGADDR]] : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
!DEVICE: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
contains
!ALL-LABEL: func.func @_QMassumed_array_routinesPassumed_shape_array(
!ALL-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) {
!ALL: %[[ALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMassumed_array_routinesFassumed_shape_arrayEi"}
!ALL: %[[C0:.*]] = arith.constant 1 : index
!ALL: %[[C1:.*]] = arith.constant 0 : index
!ALL: %[[C2:.*]]:3 = fir.box_dims %arg0, %[[C1]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
!ALL: %[[C3:.*]] = arith.constant 1 : index
!ALL: %[[C4:.*]] = arith.constant 4 : index
!ALL: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) stride(%[[C2]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true}
!ALL: %[[ADDROF:.*]] = fir.box_addr %arg0 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
!ALL: %[[MAP:.*]] = omp.map_info var_ptr(%[[ADDROF]] : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
!ALL: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"}
!ALL: omp.target map_entries(%[[MAP]] -> %{{.*}}, %[[MAP2]] -> %{{.*}} : !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) {

!HOST-LABEL: func.func @_QMassumed_array_routinesPassumed_shape_array(
!HOST-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) {
!HOST: %[[ALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMassumed_array_routinesFassumed_shape_arrayEi"}
!HOST: %[[C0:.*]] = arith.constant 1 : index
!HOST: %[[C1:.*]] = arith.constant 0 : index
!HOST: %[[C2:.*]]:3 = fir.box_dims %arg0, %[[C1]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
!HOST: %[[C3:.*]] = arith.constant 1 : index
!HOST: %[[C4:.*]] = arith.constant 4 : index
!HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) stride(%[[C2]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true}
!HOST: %[[ADDROF:.*]] = fir.box_addr %arg0 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
!HOST: %[[MAP:.*]] = omp.map_info var_ptr(%[[ADDROF]] : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
!HOST: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
subroutine assumed_shape_array(arr_read_write)
integer, intent(inout) :: arr_read_write(:)

Expand All @@ -81,25 +55,17 @@ subroutine assumed_shape_array(arr_read_write)
!$omp end target
end subroutine assumed_shape_array

!DEVICE-LABEL: func.func @_QMassumed_array_routinesPassumed_size_array_omp_outline_0(
!DEVICE-SAME: %[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<!fir.array<?xi32>>) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QMassumed_array_routinesPassumed_size_array"} {
!DEVICE: %[[C0:.*]] = arith.constant 1 : index
!DEVICE: %[[C1:.*]] = arith.constant 4 : index
!DEVICE: %[[C2:.*]] = arith.constant 1 : index
!DEVICE: %[[C3:.*]] = arith.constant 1 : index
!DEVICE: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C0]] : index) upper_bound(%[[C1]] : index) stride(%[[C3]] : index) start_idx(%[[C3]] : index)
!DEVICE: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARG1]] : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
!DEVICE: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
!ALL-LABEL: func.func @_QMassumed_array_routinesPassumed_size_array(
!ALL-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) {
!ALL: %[[ALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEi"}
!ALL: %[[C0:.*]] = arith.constant 1 : index
!ALL: %[[C1:.*]] = arith.constant 1 : index
!ALL: %[[C2:.*]] = arith.constant 4 : index
!ALL: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C1]] : index) upper_bound(%[[C2]] : index) stride(%[[C0]] : index) start_idx(%[[C0]] : index)
!ALL: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARG0]] : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
!ALL: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"}
!ALL: omp.target map_entries(%[[MAP]] -> %{{.*}}, %[[MAP2]] -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, index) {

!HOST-LABEL: func.func @_QMassumed_array_routinesPassumed_size_array(
!HOST-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) {
!HOST: %[[ALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEi"}
!HOST: %[[C0:.*]] = arith.constant 1 : index
!HOST: %[[C1:.*]] = arith.constant 1 : index
!HOST: %[[C2:.*]] = arith.constant 4 : index
!HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C1]] : index) upper_bound(%[[C2]] : index) stride(%[[C0]] : index) start_idx(%[[C0]] : index)
!HOST: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARG0]] : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
!HOST: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
subroutine assumed_size_array(arr_read_write)
integer, intent(inout) :: arr_read_write(*)

Expand All @@ -111,6 +77,7 @@ subroutine assumed_size_array(arr_read_write)
end subroutine assumed_size_array
end module assumed_array_routines

!DEVICE-NOT:func.func @_QPcall_assumed_shape_and_size_array() {

!HOST-LABEL:func.func @_QPcall_assumed_shape_and_size_array() {
!HOST:%{{.*}} = arith.constant 20 : index
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/FIR/location.f90
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ subroutine sub_parallel()
!CHECK-LABEL: sub_target
subroutine sub_target()
print *, x
!CHECK: omp.target {
!CHECK: omp.target {{.*}} {
!$omp target
print *, x
!CHECK: omp.terminator loc(#[[TAR_LOC:.*]])
Expand Down
89 changes: 0 additions & 89 deletions flang/test/Lower/OpenMP/FIR/omp-target-early-outlining.f90

This file was deleted.

106 changes: 88 additions & 18 deletions flang/test/Lower/OpenMP/FIR/target.f90
Original file line number Diff line number Diff line change
Expand Up @@ -189,20 +189,87 @@ subroutine omp_target
integer :: a(1024)
!CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}})
!CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
!CHECK: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) {
!CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]], %{{.*}} -> %{{.*}} : !fir.ref<!fir.array<1024xi32>>, index) {
!CHECK: ^bb0(%[[ARG_0]]: !fir.ref<!fir.array<1024xi32>>, %{{.*}}: index):
!$omp target map(tofrom: a)
!CHECK: %[[VAL_1:.*]] = arith.constant 10 : i32
!CHECK: %[[VAL_2:.*]] = arith.constant 1 : i64
!CHECK: %[[VAL_3:.*]] = arith.constant 1 : i64
!CHECK: %[[VAL_4:.*]] = arith.subi %[[VAL_2]], %[[VAL_3]] : i64
!CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_4]] : (!fir.ref<!fir.array<1024xi32>>, i64) -> !fir.ref<i32>
!CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[ARG_0]], %[[VAL_4]] : (!fir.ref<!fir.array<1024xi32>>, i64) -> !fir.ref<i32>
!CHECK: fir.store %[[VAL_1]] to %[[VAL_5]] : !fir.ref<i32>
a(1) = 10
!CHECK: omp.terminator
!$omp end target
!CHECK: }
end subroutine omp_target

!===============================================================================
! Target implicit capture
!===============================================================================

!CHECK-LABEL: func.func @_QPomp_target_implicit() {
subroutine omp_target_implicit
!CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_implicitEa"}
integer :: a(1024)
!CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
!CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]], %{{.*}} -> %{{.*}} : !fir.ref<!fir.array<1024xi32>>, index) {
!CHECK: ^bb0(%[[ARG_0]]: !fir.ref<!fir.array<1024xi32>>, %{{.*}}: index):
!$omp target
!CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[ARG_0]], %{{.*}} : (!fir.ref<!fir.array<1024xi32>>, i64) -> !fir.ref<i32>
a(1) = 10
!CHECK: omp.terminator
!$omp end target
!CHECK: }
end subroutine omp_target_implicit

!===============================================================================
! Target implicit capture nested
!===============================================================================

!CHECK-LABEL: func.func @_QPomp_target_implicit_nested() {
subroutine omp_target_implicit_nested
integer::a, b
!CHECK: omp.target map_entries(%{{.*}} -> %[[ARG0:.*]], %{{.*}} -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
!CHECK: ^bb0(%[[ARG0]]: !fir.ref<i32>, %[[ARG1]]: !fir.ref<i32>):
!$omp target
!CHECK: fir.store %{{.*}} to %[[ARG0]] : !fir.ref<i32>
a = 10
!$omp parallel
!CHECK: fir.store %{{.*}} to %[[ARG1]] : !fir.ref<i32>
b = 20
!CHECK: omp.terminator
!$omp end parallel
!CHECK: omp.terminator
!$omp end target
!CHECK: }
end subroutine omp_target_implicit_nested

!===============================================================================
! Target implicit capture with bounds
!===============================================================================

!CHECK-LABEL: func.func @_QPomp_target_implicit_bounds(%{{.*}}: !fir.ref<i32> {fir.bindc_name = "n"}) {
subroutine omp_target_implicit_bounds(n)
!CHECK: %[[VAL_1:.*]] = arith.select %{{.*}}, %{{.*}}, %{{.*}} : index
!CHECK: %[[VAL_2:.*]] = arith.select %{{.*}}, %{{.*}}, %{{.*}} : index
!CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<?x1024xi32>, %[[VAL_1]] {bindc_name = "a", uniq_name = "_QFomp_target_implicit_boundsEa"}
integer :: n
integer :: a(n, 1024)
!CHECK: %[[VAL_4:.*]] = omp.map_info var_ptr(%[[VAL_3]] : !fir.ref<!fir.array<?x1024xi32>>, !fir.array<?x1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.ref<!fir.array<?x1024xi32>> {name = "a"}
!CHECK: %[[VAL_5:.*]] = omp.map_info val(%[[VAL_1]] : index) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> index {name = ""}
!CHECK: %[[VAL_6:.*]] = omp.map_info val(%[[VAL_2]] : index) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> index {name = ""}
!CHECK: omp.target map_entries(%[[VAL_4]] -> %[[ARG_1:.*]], %[[VAL_5]] -> %[[ARG_2:.*]], %[[VAL_6]] -> %[[ARG_3:.*]] : !fir.ref<!fir.array<?x1024xi32>>, index, index) {
!CHECK: ^bb0(%[[ARG_1]]: !fir.ref<!fir.array<?x1024xi32>>, %[[ARG_2]]: index, %[[ARG_3]]: index):
!$omp target
!CHECK: %{{.*}} = fir.convert %[[ARG_1]] : (!fir.ref<!fir.array<?x1024xi32>>) -> !fir.ref<!fir.array<?xi32>>
!CHECK: %{{.*}} = arith.muli %{{.*}}, %[[ARG_2]] : index
a(11,22) = 33
!CHECK: omp.terminator
!$omp end target
!CHECK: }
end subroutine omp_target_implicit_bounds

!===============================================================================
! Target `thread_limit` clause
!===============================================================================
Expand All @@ -212,7 +279,8 @@ subroutine omp_target_thread_limit
integer :: a
!CHECK: %[[VAL_1:.*]] = arith.constant 64 : i32
!CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a"}
!CHECK: omp.target thread_limit(%[[VAL_1]] : i32) map_entries(%[[MAP]] : !fir.ref<i32>) {
!CHECK: omp.target thread_limit(%[[VAL_1]] : i32) map_entries(%[[MAP]] -> %[[ARG_0:.*]] : !fir.ref<i32>) {
!CHECK: ^bb0(%[[ARG_0]]: !fir.ref<i32>):
!$omp target map(tofrom: a) thread_limit(64)
a = 10
!CHECK: omp.terminator
Expand Down Expand Up @@ -274,23 +342,25 @@ subroutine omp_target_parallel_do
!CHECK: %[[C0:.*]] = arith.constant 0 : index
!CHECK: %[[SUB:.*]] = arith.subi %[[C1024]], %[[C1]] : index
!CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C0]] : index) upper_bound(%[[SUB]] : index) extent(%[[C1024]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index)
!CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
!CHECK: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) {
!CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
!CHECK: %[[MAP2:.*]] = omp.map_info var_ptr(%[[VAL_1]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"}
!CHECK: omp.target map_entries(%[[MAP1]] -> %[[VAL_2:.*]], %[[MAP2]] -> %[[VAL_3:.*]], %{{.*}} -> %{{.*}} : !fir.ref<!fir.array<1024xi32>>, !fir.ref<i32>, index) {
!CHECK: ^bb0(%[[VAL_2]]: !fir.ref<!fir.array<1024xi32>>, %[[VAL_3]]: !fir.ref<i32>, %{{.*}}: index):
!CHECK-NEXT: omp.parallel
!$omp target parallel do map(tofrom: a)
!CHECK: %[[VAL_2:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
!CHECK: %[[VAL_3:.*]] = arith.constant 1 : i32
!CHECK: %[[VAL_4:.*]] = arith.constant 1024 : i32
!CHECK: %[[VAL_4:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
!CHECK: %[[VAL_5:.*]] = arith.constant 1 : i32
!CHECK: omp.wsloop for (%[[VAL_6:.*]]) : i32 = (%[[VAL_3]]) to (%[[VAL_4]]) inclusive step (%[[VAL_5]]) {
!CHECK: fir.store %[[VAL_6]] to %[[VAL_2]] : !fir.ref<i32>
!CHECK: %[[VAL_7:.*]] = arith.constant 10 : i32
!CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_2]] : !fir.ref<i32>
!CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i32) -> i64
!CHECK: %[[VAL_10:.*]] = arith.constant 1 : i64
!CHECK: %[[VAL_11:.*]] = arith.subi %[[VAL_9]], %[[VAL_10]] : i64
!CHECK: %[[VAL_12:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_11]] : (!fir.ref<!fir.array<1024xi32>>, i64) -> !fir.ref<i32>
!CHECK: fir.store %[[VAL_7]] to %[[VAL_12]] : !fir.ref<i32>
!CHECK: %[[VAL_6:.*]] = arith.constant 1024 : i32
!CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
!CHECK: omp.wsloop for (%[[VAL_8:.*]]) : i32 = (%[[VAL_5]]) to (%[[VAL_6]]) inclusive step (%[[VAL_7]]) {
!CHECK: fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ref<i32>
!CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32
!CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_4]] : !fir.ref<i32>
!CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i32) -> i64
!CHECK: %[[VAL_12:.*]] = arith.constant 1 : i64
!CHECK: %[[VAL_13:.*]] = arith.subi %[[VAL_11]], %[[VAL_12]] : i64
!CHECK: %[[VAL_14:.*]] = fir.coordinate_of %[[VAL_2]], %[[VAL_13]] : (!fir.ref<!fir.array<1024xi32>>, i64) -> !fir.ref<i32>
!CHECK: fir.store %[[VAL_9]] to %[[VAL_14]] : !fir.ref<i32>
do i = 1, 1024
a(i) = 10
end do
Expand All @@ -301,4 +371,4 @@ subroutine omp_target_parallel_do
!CHECK: omp.terminator
!CHECK: }
!$omp end target parallel do
end subroutine omp_target_parallel_do
end subroutine omp_target_parallel_do
6 changes: 3 additions & 3 deletions flang/test/Lower/OpenMP/array-bounds.f90
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
!HOST: %[[C6:.*]] = arith.constant 4 : index
!HOST: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index)
!HOST: %[[MAP1:.*]] = omp.map_info var_ptr(%[[WRITE_DECL]]#1 : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"}
!HOST: omp.target map_entries(%[[MAP0]], %[[MAP1]] : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) {
!HOST: omp.target map_entries(%[[MAP0]] -> %{{.*}}, %[[MAP1]] -> %{{.*}}, {{.*}} -> {{.*}}, {{.*}} -> {{.*}}, {{.*}} -> {{.*}} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>, !fir.ref<i32>, index, index) {

subroutine read_write_section()
integer :: sp_read(10) = (/1,2,3,4,5,6,7,8,9,10/)
Expand Down Expand Up @@ -50,7 +50,7 @@ module assumed_array_routines
!HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) stride(%[[C2]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true}
!HOST: %[[ADDROF:.*]] = fir.box_addr %[[ARG0_DECL]]#1 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
!HOST: %[[MAP:.*]] = omp.map_info var_ptr(%[[ADDROF]] : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
!HOST: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
!HOST: omp.target map_entries(%[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}} : !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) {
subroutine assumed_shape_array(arr_read_write)
integer, intent(inout) :: arr_read_write(:)

Expand All @@ -73,7 +73,7 @@ end subroutine assumed_shape_array
!HOST: %[[C2:.*]] = arith.constant 4 : index
!HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C1]] : index) upper_bound(%[[C2]] : index) stride(%[[C0]] : index) start_idx(%[[C0]] : index)
!HOST: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARG0_DECL]]#1 : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
!HOST: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
!HOST: omp.target map_entries(%[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}}, {{.*}} -> {{.*}} : !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>, index) {
subroutine assumed_size_array(arr_read_write)
integer, intent(inout) :: arr_read_write(*)

Expand Down
2 changes: 0 additions & 2 deletions flang/test/Lower/OpenMP/function-filtering-2.f90
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ subroutine no_declaretarget()
end subroutine no_declaretarget

! MLIR-HOST: func.func @{{.*}}main(
! MLIR-HOST-NOT: func.func @{{.*}}main_omp_outline{{.*}}()
! MLIR-DEVICE-NOT: func.func @{{.*}}main(
! MLIR-DEVICE: func.func @{{.*}}main_omp_outline{{.*}}() attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QQmain"}
! MLIR-ALL: return

! LLVM-HOST: define {{.*}} @{{.*}}main{{.*}}(
Expand Down
5 changes: 0 additions & 5 deletions flang/test/Lower/OpenMP/function-filtering.f90
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,9 @@ end function host_fn

! MLIR-HOST: func.func @{{.*}}target_subr(
! MLIR-HOST: return
! MLIR-HOST-NOT: func.func @{{.*}}target_subr_omp_outline_0(
! MLIR-DEVICE-NOT: func.func @{{.*}}target_subr(
! MLIR-DEVICE: func.func @{{.*}}target_subr_omp_outline_0(
! MLIR-DEVICE: return

! LLVM-ALL-NOT: define {{.*}} @{{.*}}target_subr_omp_outline_0{{.*}}(
! LLVM-HOST: define {{.*}} @{{.*}}target_subr{{.*}}(
! LLVM-DEVICE-NOT: {{.*}} @{{.*}}target_subr{{.*}}(
! LLVM-ALL: define {{.*}} @__omp_offloading_{{.*}}_{{.*}}_target_subr__{{.*}}(
subroutine target_subr(x)
integer, intent(out) :: x
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/location.f90
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ subroutine sub_parallel()
!CHECK-LABEL: sub_target
subroutine sub_target()
print *, x
!CHECK: omp.target {
!CHECK: omp.target {{.*}} {
!$omp target
print *, x
!CHECK: omp.terminator loc(#[[TAR_LOC:.*]])
Expand Down
144 changes: 132 additions & 12 deletions flang/test/Lower/OpenMP/target.f90
Original file line number Diff line number Diff line change
Expand Up @@ -187,23 +187,112 @@ end subroutine omp_target_data_mt

!CHECK-LABEL: func.func @_QPomp_target() {
subroutine omp_target
!CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_targetEa"}
!CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]](%{{.*}}) {uniq_name = "_QFomp_targetEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
!CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFomp_targetEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
integer :: a(1024)
!CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}})
!CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_0_DECL]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
!CHECK: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) {
!CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_1]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
!CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]], %{{.*}} -> %[[ARG_1:.*]] : !fir.ref<!fir.array<1024xi32>>, index) {
!CHECK: ^bb0(%[[ARG_0]]: !fir.ref<!fir.array<1024xi32>>, %[[ARG_1]]: index):
!$omp target map(tofrom: a)
!CHECK: %[[C10:.*]] = arith.constant 10 : i32
!CHECK: %[[C1:.*]] = arith.constant 1 : index
!CHECK: %[[A_1:.*]] = hlfir.designate %[[VAL_0_DECL]]#0 (%[[C1]]) : (!fir.ref<!fir.array<1024xi32>>, index) -> !fir.ref<i32>
!CHECK: hlfir.assign %[[C10]] to %[[A_1]] : i32, !fir.ref<i32>
!CHECK: %[[VAL_2:.*]] = fir.shape %[[ARG_1]] : (index) -> !fir.shape<1>
!CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG_0]](%[[VAL_2]]) {uniq_name = "_QFomp_targetEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
!CHECK: %[[VAL_4:.*]] = arith.constant 10 : i32
!CHECK: %[[VAL_5:.*]] = arith.constant 1 : index
!CHECK: %[[VAL_6:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_5]]) : (!fir.ref<!fir.array<1024xi32>>, index) -> !fir.ref<i32>
!CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_6]] : i32, !fir.ref<i32>
a(1) = 10
!CHECK: omp.terminator
!CHECK: omp.terminator
!$omp end target
!CHECK: }
end subroutine omp_target

!===============================================================================
! Target implicit capture
!===============================================================================

!CHECK-LABEL: func.func @_QPomp_target_implicit() {
subroutine omp_target_implicit
!CHECK: %[[VAL_0:.*]] = arith.constant 1024 : index
!CHECK: %[[VAL_1:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_implicitEa"}
!CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_0]] : (index) -> !fir.shape<1>
!CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_2]]) {uniq_name = "_QFomp_target_implicitEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
integer :: a(1024)
!CHECK: %[[VAL_4:.*]] = omp.map_info var_ptr(%[[VAL_3]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
!CHECK: %[[VAL_5:.*]] = omp.map_info val(%[[VAL_0]] : index) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> index {name = ""}
!CHECK: omp.target map_entries(%[[VAL_4]] -> %[[VAL_6:.*]], %[[VAL_5]] -> %[[VAL_7:.*]] : !fir.ref<!fir.array<1024xi32>>, index) {
!CHECK: ^bb0(%[[VAL_6]]: !fir.ref<!fir.array<1024xi32>>, %[[VAL_7]]: index):
!$omp target
!CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1>
!CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_6]](%[[VAL_8]]) {uniq_name = "_QFomp_target_implicitEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
!CHECK: %[[VAL_10:.*]] = arith.constant 10 : i32
!CHECK: %[[VAL_11:.*]] = arith.constant 1 : index
!CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_9]]#0 (%[[VAL_11]]) : (!fir.ref<!fir.array<1024xi32>>, index) -> !fir.ref<i32>
!CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_12]] : i32, !fir.ref<i32>
a(1) = 10
!CHECK: omp.terminator
!$omp end target
!CHECK: }
end subroutine omp_target_implicit

!===============================================================================
! Target implicit capture nested
!===============================================================================

!CHECK-LABEL: func.func @_QPomp_target_implicit_nested() {
subroutine omp_target_implicit_nested
integer::a, b
!CHECK: omp.target map_entries(%{{.*}} -> %[[ARG0:.*]], %{{.*}} -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
!CHECK: ^bb0(%[[ARG0]]: !fir.ref<i32>, %[[ARG1]]: !fir.ref<i32>):
!$omp target
!CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFomp_target_implicit_nestedEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG1]] {uniq_name = "_QFomp_target_implicit_nestedEb"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[VAL_10:.*]] = arith.constant 10 : i32
!CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_8]]#0 : i32, !fir.ref<i32>
a = 10
!CHECK: omp.parallel
!$omp parallel
!CHECK: %[[VAL_11:.*]] = arith.constant 20 : i32
!CHECK: hlfir.assign %[[VAL_11]] to %[[VAL_9]]#0 : i32, !fir.ref<i32>
b = 20
!CHECK: omp.terminator
!$omp end parallel
!CHECK: omp.terminator
!$omp end target
!CHECK: }
end subroutine omp_target_implicit_nested

!===============================================================================
! Target implicit capture with bounds
!===============================================================================

!CHECK-LABEL: func.func @_QPomp_target_implicit_bounds(%{{.*}}: !fir.ref<i32> {fir.bindc_name = "n"}) {
subroutine omp_target_implicit_bounds(n)
!CHECK: %[[VAL_1:.*]] = arith.select %{{.*}}, %{{.*}}, %{{.*}} : index
!CHECK: %[[VAL_2:.*]] = arith.select %{{.*}}, %{{.*}}, %{{.*}} : index
!CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<?x1024xi32>, %[[VAL_1]] {bindc_name = "a", uniq_name = "_QFomp_target_implicit_boundsEa"}
!CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2>
!CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_4]]) {uniq_name = "_QFomp_target_implicit_boundsEa"} : (!fir.ref<!fir.array<?x1024xi32>>, !fir.shape<2>) -> (!fir.box<!fir.array<?x1024xi32>>, !fir.ref<!fir.array<?x1024xi32>>)
integer :: n
integer :: a(n, 1024)
!CHECK: %[[VAL_6:.*]] = omp.map_info var_ptr(%[[VAL_5]]#1 : !fir.ref<!fir.array<?x1024xi32>>, !fir.array<?x1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.ref<!fir.array<?x1024xi32>> {name = "a"}
!CHECK: %[[VAL_7:.*]] = omp.map_info val(%[[VAL_1]] : index) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> index {name = ""}
!CHECK: %[[VAL_8:.*]] = omp.map_info val(%[[VAL_2]] : index) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> index {name = ""}
!CHECK: omp.target map_entries(%[[VAL_6]] -> %[[ARG_1:.*]], %[[VAL_7]] -> %[[ARG_2:.*]], %[[VAL_8]] -> %[[ARG_3:.*]] : !fir.ref<!fir.array<?x1024xi32>>, index, index) {
!CHECK: ^bb0(%[[ARG_1]]: !fir.ref<!fir.array<?x1024xi32>>, %[[ARG_2]]: index, %[[ARG_3]]: index):
!$omp target
!CHECK: %[[VAL_9:.*]] = fir.shape %[[ARG_2]], %[[ARG_3]] : (index, index) -> !fir.shape<2>
!CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[ARG_1]](%[[VAL_9]]) {uniq_name = "_QFomp_target_implicit_boundsEa"} : (!fir.ref<!fir.array<?x1024xi32>>, !fir.shape<2>) -> (!fir.box<!fir.array<?x1024xi32>>, !fir.ref<!fir.array<?x1024xi32>>)
!CHECK: %[[VAL_11:.*]] = arith.constant 33 : i32
!CHECK: %[[VAL_12:.*]] = arith.constant 11 : index
!CHECK: %[[VAL_13:.*]] = arith.constant 22 : index
!CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_10]]#0 (%[[VAL_12]], %[[VAL_13]]) : (!fir.box<!fir.array<?x1024xi32>>, index, index) -> !fir.ref<i32>
!CHECK: hlfir.assign %[[VAL_11]] to %[[VAL_14]] : i32, !fir.ref<i32>
a(11, 22) = 33
!CHECK: omp.terminator
!$omp end target
!CHECK: }
end subroutine omp_target_implicit_bounds

!===============================================================================
! Target `thread_limit` clause
!===============================================================================
Expand All @@ -213,7 +302,8 @@ subroutine omp_target_thread_limit
integer :: a
!CHECK: %[[VAL_1:.*]] = arith.constant 64 : i32
!CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a"}
!CHECK: omp.target thread_limit(%[[VAL_1]] : i32) map_entries(%[[MAP]] : !fir.ref<i32>) {
!CHECK: omp.target thread_limit(%[[VAL_1]] : i32) map_entries(%[[MAP]] -> %{{.*}} : !fir.ref<i32>) {
!CHECK: ^bb0(%{{.*}}: !fir.ref<i32>):
!$omp target map(tofrom: a) thread_limit(64)
a = 10
!CHECK: omp.terminator
Expand Down Expand Up @@ -306,8 +396,10 @@ subroutine omp_target_parallel_do
!CHECK: %[[SUB:.*]] = arith.subi %[[C1024]], %[[C1]] : index
!CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C0]] : index) upper_bound(%[[SUB]] : index) extent(%[[C1024]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index)
!CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_0_DECL]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
!CHECK: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) {
!CHECK-NEXT: omp.parallel
!CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]], %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.ref<!fir.array<1024xi32>>, !fir.ref<i32>, index) {
!CHECK: ^bb0(%[[ARG_0]]: !fir.ref<!fir.array<1024xi32>>, %{{.*}}: !fir.ref<i32>, %{{.*}}: index):
!CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[ARG_0]](%{{.*}}) {uniq_name = "_QFomp_target_parallel_doEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
!CHECK: omp.parallel
!$omp target parallel do map(tofrom: a)
!CHECK: %[[I_PVT_ALLOCA:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
!CHECK: %[[I_PVT_DECL:.*]]:2 = hlfir.declare %[[I_PVT_ALLOCA]] {uniq_name = "_QFomp_target_parallel_doEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
Expand All @@ -329,3 +421,31 @@ subroutine omp_target_parallel_do
!CHECK: }
!$omp end target parallel do
end subroutine omp_target_parallel_do

!===============================================================================
! Target with unstructured code
!===============================================================================

!CHECK-LABEL: func.func @_QPtarget_unstructured() {
subroutine target_unstructured
!CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtarget_unstructuredEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
integer :: i = 1
!CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtarget_unstructuredEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
integer :: j = 11
!CHECK: %[[VAL_4:.*]] = omp.map_info var_ptr(%[[VAL_1]]#1 : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"}
!CHECK: %[[VAL_5:.*]] = omp.map_info var_ptr(%[[VAL_3]]#1 : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "j"}
!CHECK: omp.target map_entries(%[[VAL_4]] -> %[[VAL_6:.*]], %[[VAL_5]] -> %[[VAL_7:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
!CHECK: ^bb0(%[[VAL_6]]: !fir.ref<i32>, %[[VAL_7]]: !fir.ref<i32>):
!$omp target
!CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFtarget_unstructuredEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFtarget_unstructuredEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: ^bb1:
do while (i <= j)
!CHECK: ^bb2:
i = i + 1
end do
!CHECK: ^bb3:
!CHECK: omp.terminator
!$omp end target
!CHECK: }
end subroutine target_unstructured
33 changes: 16 additions & 17 deletions mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -1144,15 +1144,15 @@ def DataBoundsOp : OpenMP_Op<"bounds",
}

def MapInfoOp : OpenMP_Op<"map_info", [AttrSizedOperandSegments]> {
let arguments = (ins OpenMP_PointerLikeType:$var_ptr,
TypeAttr:$var_type,
let arguments = (ins Optional<AnyType>:$val,
Optional<OpenMP_PointerLikeType>:$var_ptr,
OptionalAttr<TypeAttr>:$var_type,
Optional<OpenMP_PointerLikeType>:$var_ptr_ptr,
Variadic<DataBoundsType>:$bounds, /* rank-0 to rank-{n-1} */
OptionalAttr<UI64Attr>:$map_type,
OptionalAttr<VariableCaptureKindAttr>:$map_capture_type,
DefaultValuedAttr<BoolAttr, "false">:$implicit,
OptionalAttr<StrAttr>:$name);
let results = (outs OpenMP_PointerLikeType:$omp_ptr);
let results = (outs AnyType:$omp_ptr);

let description = [{
The MapInfoOp captures information relating to individual OpenMP map clauses
Expand All @@ -1178,22 +1178,20 @@ def MapInfoOp : OpenMP_Op<"map_info", [AttrSizedOperandSegments]> {
```
=>
```mlir
omp.map_info var_ptr(%index_ssa) map_type(to) map_capture_type(ByRef) implicit(false)
omp.map_info var_ptr(%index_ssa) map_type(to) map_capture_type(ByRef)
name(index)
```

Description of arguments:
- `val`: The value to copy.
- `var_ptr`: The address of variable to copy.
- `var_type`: The type of the variable to copy.
- `var_type`: The type of the variable/value to copy.
- `var_ptr_ptr`: Used when the variable copied is a member of a class, structure
or derived type and refers to the originating struct.
- `bounds`: Used when copying slices of array's, pointers or pointer members of
objects (e.g. derived types or classes), indicates the bounds to be copied
of the variable. When it's an array slice it is in rank order where rank 0
is the inner-most dimension.
- `implicit`: indicates where the map item has been specified explicitly in a
map clause or captured implicitly by being used in a target region with no
map or other data mapping construct.
- 'map_clauses': OpenMP map type for this map capture, for example: from, to and
always. It's a bitfield composed of the OpenMP runtime flags stored in
OpenMPOffloadMappingFlags.
Expand All @@ -1203,9 +1201,10 @@ def MapInfoOp : OpenMP_Op<"map_info", [AttrSizedOperandSegments]> {
}];

let assemblyFormat = [{
`var_ptr` `(` $var_ptr `:` type($var_ptr) `,` $var_type`)`
oilist(
`var_ptr_ptr` `(` $var_ptr_ptr `:` type($var_ptr_ptr) `)`
`val` `(` $val `:` type($val) `)`
| `var_ptr` `(` $var_ptr `:` type($var_ptr) `,` $var_type `)`
| `var_ptr_ptr` `(` $var_ptr_ptr `:` type($var_ptr_ptr) `)`
| `map_clauses` `(` custom<MapClause>($map_type) `)`
| `capture` `(` custom<CaptureType>($map_capture_type) `)`
| `bounds` `(` $bounds `)`
Expand Down Expand Up @@ -1265,7 +1264,7 @@ def Target_DataOp: OpenMP_Op<"target_data", [AttrSizedOperandSegments]>{
Optional<AnyInteger>:$device,
Variadic<OpenMP_PointerLikeType>:$use_device_ptr,
Variadic<OpenMP_PointerLikeType>:$use_device_addr,
Variadic<OpenMP_PointerLikeType>:$map_operands);
Variadic<AnyType>:$map_operands);

let regions = (region AnyRegion:$region);

Expand Down Expand Up @@ -1314,7 +1313,7 @@ def Target_EnterDataOp: OpenMP_Op<"target_enter_data",
let arguments = (ins Optional<I1>:$if_expr,
Optional<AnyInteger>:$device,
UnitAttr:$nowait,
Variadic<OpenMP_PointerLikeType>:$map_operands);
Variadic<AnyType>:$map_operands);

let assemblyFormat = [{
oilist(`if` `(` $if_expr `:` type($if_expr) `)`
Expand Down Expand Up @@ -1360,7 +1359,7 @@ def Target_ExitDataOp: OpenMP_Op<"target_exit_data",
let arguments = (ins Optional<I1>:$if_expr,
Optional<AnyInteger>:$device,
UnitAttr:$nowait,
Variadic<OpenMP_PointerLikeType>:$map_operands);
Variadic<AnyType>:$map_operands);

let assemblyFormat = [{
oilist(`if` `(` $if_expr `:` type($if_expr) `)`
Expand All @@ -1377,7 +1376,7 @@ def Target_ExitDataOp: OpenMP_Op<"target_exit_data",
// 2.14.5 target construct
//===----------------------------------------------------------------------===//

def TargetOp : OpenMP_Op<"target",[OutlineableOpenMPOpInterface, AttrSizedOperandSegments]> {
def TargetOp : OpenMP_Op<"target",[IsolatedFromAbove, OutlineableOpenMPOpInterface, AttrSizedOperandSegments]> {
let summary = "target construct";
let description = [{
The target construct includes a region of code which is to be executed
Expand All @@ -1403,7 +1402,7 @@ def TargetOp : OpenMP_Op<"target",[OutlineableOpenMPOpInterface, AttrSizedOperan
Optional<AnyInteger>:$device,
Optional<AnyInteger>:$thread_limit,
UnitAttr:$nowait,
Variadic<OpenMP_PointerLikeType>:$map_operands);
Variadic<AnyType>:$map_operands);

let regions = (region AnyRegion:$region);

Expand All @@ -1412,7 +1411,7 @@ def TargetOp : OpenMP_Op<"target",[OutlineableOpenMPOpInterface, AttrSizedOperan
| `device` `(` $device `:` type($device) `)`
| `thread_limit` `(` $thread_limit `:` type($thread_limit) `)`
| `nowait` $nowait
| `map_entries` `(` $map_operands `:` type($map_operands) `)`
| `map_entries` `(` custom<MapEntries>($map_operands, type($map_operands)) `)`
) $region attr-dict
}];

Expand Down
73 changes: 73 additions & 0 deletions mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,9 @@ static ParseResult parseMapClause(OpAsmParser &parser, IntegerAttr &mapType) {
if (mapTypeMod == "always")
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;

if (mapTypeMod == "implicit")
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;

if (mapTypeMod == "close")
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;

Expand Down Expand Up @@ -737,6 +740,9 @@ static void printMapClause(OpAsmPrinter &p, Operation *op,
if (mapTypeToBitFlag(mapTypeBits,
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS))
mapTypeStrs.push_back("always");
if (mapTypeToBitFlag(mapTypeBits,
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
mapTypeStrs.push_back("implicit");
if (mapTypeToBitFlag(mapTypeBits,
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE))
mapTypeStrs.push_back("close");
Expand Down Expand Up @@ -777,6 +783,64 @@ static void printMapClause(OpAsmPrinter &p, Operation *op,
}
}

static ParseResult
parseMapEntries(OpAsmParser &parser,
SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapOperands,
SmallVectorImpl<Type> &mapOperandTypes) {
OpAsmParser::UnresolvedOperand arg;
OpAsmParser::UnresolvedOperand blockArg;
Type argType;
auto parseEntries = [&]() -> ParseResult {
if (parser.parseOperand(arg) || parser.parseArrow() ||
parser.parseOperand(blockArg))
return failure();
mapOperands.push_back(arg);
return success();
};

auto parseTypes = [&]() -> ParseResult {
if (parser.parseType(argType))
return failure();
mapOperandTypes.push_back(argType);
return success();
};

if (parser.parseCommaSeparatedList(parseEntries))
return failure();

if (parser.parseColon())
return failure();

if (parser.parseCommaSeparatedList(parseTypes))
return failure();

return success();
}

static void printMapEntries(OpAsmPrinter &p, Operation *op,
OperandRange mapOperands,
TypeRange mapOperandTypes) {
auto &region = op->getRegion(0);
unsigned argIndex = 0;

for (const auto &mapOp : mapOperands) {
const auto &blockArg = region.front().getArgument(argIndex);
p << mapOp << " -> " << blockArg;
argIndex++;
if (argIndex < mapOperands.size())
p << ", ";
}
p << " : ";

argIndex = 0;
for (const auto &mapType : mapOperandTypes) {
p << mapType;
argIndex++;
if (argIndex < mapOperands.size())
p << ", ";
}
}

static void printCaptureType(OpAsmPrinter &p, Operation *op,
VariableCaptureKindAttr mapCaptureType) {
std::string typeCapStr;
Expand Down Expand Up @@ -823,6 +887,15 @@ static LogicalResult verifyMapClause(Operation *op, OperandRange mapOperands) {
if (auto MapInfoOp =
mlir::dyn_cast<mlir::omp::MapInfoOp>(mapOp.getDefiningOp())) {

if (MapInfoOp.getVal() && MapInfoOp.getVarPtr())
emitError(op->getLoc(), "only one of val or var_ptr must be used");

if (!MapInfoOp.getVal() && !MapInfoOp.getVarPtr())
emitError(op->getLoc(), "missing val or var_ptr");

if (!MapInfoOp.getVarPtr() && MapInfoOp.getVarType().has_value())
emitError(op->getLoc(), "var_type supplied without var_ptr");

if (!MapInfoOp.getMapType().has_value())
emitError(op->getLoc(), "missing map type for map operand");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1733,23 +1733,28 @@ void collectMapDataFromMapOperands(MapInfoData &mapData,
"missing map info operation or incorrect map info operation type");
if (auto mapOp = mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(
mapValue.getDefiningOp())) {
mapData.OriginalValue.push_back(
moduleTranslation.lookupValue(mapOp.getVarPtr()));
mapData.OriginalValue.push_back(moduleTranslation.lookupValue(
mapOp.getVarPtr() ? mapOp.getVarPtr() : mapOp.getVal()));
mapData.Pointers.push_back(mapData.OriginalValue.back());

if (llvm::Value *refPtr = getRefPtrIfDeclareTarget(
mapOp.getVarPtr(), moduleTranslation)) { // declare target
mapOp.getVarPtr() ? mapOp.getVarPtr() : mapOp.getVal(),
moduleTranslation)) { // declare target
mapData.IsDeclareTarget.push_back(true);
mapData.BasePointers.push_back(refPtr);
} else { // regular mapped variable
mapData.IsDeclareTarget.push_back(false);
mapData.BasePointers.push_back(mapData.OriginalValue.back());
}

mapData.Sizes.push_back(getSizeInBytes(dl, mapOp.getVarType(), mapOp,
builder, moduleTranslation));
mapData.BaseType.push_back(
moduleTranslation.convertType(mapOp.getVarType()));
mapData.Sizes.push_back(
getSizeInBytes(dl,
mapOp.getVal() ? mapOp.getVal().getType()
: mapOp.getVarType().value(),
mapOp, builder, moduleTranslation));
mapData.BaseType.push_back(moduleTranslation.convertType(
mapOp.getVal() ? mapOp.getVal().getType()
: mapOp.getVarType().value()));
mapData.MapClause.push_back(mapOp.getOperation());
mapData.Types.push_back(
llvm::omp::OpenMPOffloadMappingFlags(mapOp.getMapType().value()));
Expand Down Expand Up @@ -1796,6 +1801,13 @@ static void genMapInfos(llvm::IRBuilderBase &builder,
else if (isTargetParams)
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;

if (auto mapInfoOp = dyn_cast<mlir::omp::MapInfoOp>(mapData.MapClause[i]))
if (mapInfoOp.getMapCaptureType().value() ==
mlir::omp::VariableCaptureKind::ByCopy &&
!(mapInfoOp.getVarType().has_value() &&
mapInfoOp.getVarType()->isa<LLVM::LLVMPointerType>()))
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL;

combinedInfo.BasePointers.emplace_back(mapData.BasePointers[i]);
combinedInfo.Pointers.emplace_back(mapData.Pointers[i]);
combinedInfo.DevicePointers.emplace_back(mapData.DevicePointers[i]);
Expand Down Expand Up @@ -2318,13 +2330,36 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,

auto targetOp = cast<omp::TargetOp>(opInst);
auto &targetRegion = targetOp.getRegion();
DataLayout dl = DataLayout(opInst.getParentOfType<ModuleOp>());
SmallVector<Value> mapOperands = targetOp.getMapOperands();

// Remove mapOperands/blockArgs that have no use inside the region.
assert(mapOperands.size() == targetRegion.getNumArguments() &&
"Number of mapOperands must be same as block_arguments");
for (size_t i = 0; i < mapOperands.size(); i++) {
if (targetRegion.getArgument(i).use_empty()) {
targetRegion.eraseArgument(i);
mapOperands.erase(&mapOperands[i]);
i--;
}
}

LogicalResult bodyGenStatus = success();

using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
auto bodyCB = [&](InsertPointTy allocaIP,
InsertPointTy codeGenIP) -> InsertPointTy {
builder.restoreIP(codeGenIP);
unsigned argIndex = 0;
for (auto &mapOp : mapOperands) {
auto mapInfoOp =
mlir::dyn_cast<mlir::omp::MapInfoOp>(mapOp.getDefiningOp());
llvm::Value *mapOpValue = moduleTranslation.lookupValue(
mapInfoOp.getVarPtr() ? mapInfoOp.getVarPtr() : mapInfoOp.getVal());
const auto &arg = targetRegion.front().getArgument(argIndex);
moduleTranslation.mapValue(arg, mapOpValue);
argIndex++;
}
llvm::BasicBlock *exitBlock = convertOmpOpRegions(
targetRegion, "omp.target", builder, moduleTranslation, bodyGenStatus);
builder.SetInsertPoint(exitBlock);
Expand Down Expand Up @@ -2352,8 +2387,6 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
findAllocaInsertPoint(builder, moduleTranslation);

DataLayout dl = DataLayout(opInst.getParentOfType<ModuleOp>());
llvm::SmallVector<Value> mapOperands = targetOp.getMapOperands();
MapInfoData mapData;
collectMapDataFromMapOperands(mapData, mapOperands, moduleTranslation, dl,
builder);
Expand Down Expand Up @@ -2459,6 +2492,8 @@ convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute,
if (declareType == omp::DeclareTargetDeviceType::host) {
llvm::Function *llvmFunc =
moduleTranslation.lookupFunction(funcOp.getName());
llvmFunc->replaceAllUsesWith(
llvm::UndefValue::get(llvmFunc->getType()));
llvmFunc->dropAllReferences();
llvmFunc->eraseFromParent();
}
Expand Down
20 changes: 13 additions & 7 deletions mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,12 @@ llvm.func @_QPomp_target_data_region(%a : !llvm.ptr, %i : !llvm.ptr) {
// CHECK: %[[ARG_0:.*]]: !llvm.ptr,
// CHECK: %[[ARG_1:.*]]: !llvm.ptr) {
// CHECK: %[[VAL_0:.*]] = llvm.mlir.constant(64 : i32) : i32
// CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARG_0]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
// CHECK: omp.target thread_limit(%[[VAL_0]] : i32) map_entries(%[[MAP]] : !llvm.ptr) {
// CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG_0]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
// CHECK: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ARG_1]] : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = ""}
// CHECK: omp.target thread_limit(%[[VAL_0]] : i32) map_entries(%[[MAP1]] -> %[[BB_ARG0:.*]], %[[MAP2]] -> %[[BB_ARG1:.*]] : !llvm.ptr, !llvm.ptr) {
// CHECK: ^bb0(%[[BB_ARG0]]: !llvm.ptr, %[[BB_ARG1]]: !llvm.ptr):
// CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(10 : i32) : i32
// CHECK: llvm.store %[[VAL_1]], %[[ARG_1]] : i32, !llvm.ptr
// CHECK: llvm.store %[[VAL_1]], %[[BB_ARG1]] : i32, !llvm.ptr
// CHECK: omp.terminator
// CHECK: }
// CHECK: llvm.return
Expand All @@ -256,9 +258,11 @@ llvm.func @_QPomp_target_data_region(%a : !llvm.ptr, %i : !llvm.ptr) {
llvm.func @_QPomp_target(%a : !llvm.ptr, %i : !llvm.ptr) {
%0 = llvm.mlir.constant(64 : i32) : i32
%1 = omp.map_info var_ptr(%a : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
omp.target thread_limit(%0 : i32) map_entries(%1 : !llvm.ptr) {
%3 = omp.map_info var_ptr(%i : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = ""}
omp.target thread_limit(%0 : i32) map_entries(%1 -> %arg0, %3 -> %arg1 : !llvm.ptr, !llvm.ptr) {
^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
%2 = llvm.mlir.constant(10 : i32) : i32
llvm.store %2, %i : i32, !llvm.ptr
llvm.store %2, %arg1 : i32, !llvm.ptr
omp.terminator
}
llvm.return
Expand Down Expand Up @@ -449,7 +453,8 @@ llvm.func @sub_() {
// CHECK: %[[C_14:.*]] = llvm.mlir.constant(1 : index) : i64
// CHECK: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C_12]] : i64) upper_bound(%[[C_11]] : i64) stride(%[[C_14]] : i64) start_idx(%[[C_14]] : i64)
// CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG_2]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""}
// CHECK: omp.target map_entries(%[[MAP0]], %[[MAP1]] : !llvm.ptr, !llvm.ptr) {
// CHECK: omp.target map_entries(%[[MAP0]] -> %[[BB_ARG0:.*]], %[[MAP1]] -> %[[BB_ARG1:.*]] : !llvm.ptr, !llvm.ptr) {
// CHECK: ^bb0(%[[BB_ARG0]]: !llvm.ptr, %[[BB_ARG1]]: !llvm.ptr):
// CHECK: omp.terminator
// CHECK: }
// CHECK: llvm.return
Expand All @@ -468,7 +473,8 @@ llvm.func @_QPtarget_map_with_bounds(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2:
%9 = llvm.mlir.constant(1 : index) : i64
%10 = omp.bounds lower_bound(%7 : i64) upper_bound(%6 : i64) stride(%9 : i64) start_idx(%9 : i64)
%11 = omp.map_info var_ptr(%arg2 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%10) -> !llvm.ptr {name = ""}
omp.target map_entries(%5, %11 : !llvm.ptr, !llvm.ptr) {
omp.target map_entries(%5 -> %arg3, %11 -> %arg4: !llvm.ptr, !llvm.ptr) {
^bb0(%arg3: !llvm.ptr, %arg4: !llvm.ptr):
omp.terminator
}
llvm.return
Expand Down
5 changes: 3 additions & 2 deletions mlir/test/Dialect/OpenMP/canonicalize.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,9 @@ func.func private @foo() -> ()

func.func @constant_hoisting_target(%x : !llvm.ptr) {
omp.target {
^bb0(%arg0: !llvm.ptr):
%c1 = arith.constant 10 : i32
llvm.store %c1, %x : i32, !llvm.ptr
llvm.store %c1, %arg0 : i32, !llvm.ptr
omp.terminator
}
return
Expand All @@ -141,4 +142,4 @@ func.func @constant_hoisting_target(%x : !llvm.ptr) {
// CHECK-LABEL: func.func @constant_hoisting_target
// CHECK-NOT: arith.constant
// CHECK: omp.target
// CHECK-NEXT: arith.constant
// CHECK: arith.constant
40 changes: 39 additions & 1 deletion mlir/test/Dialect/OpenMP/invalid.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,9 @@ func.func @omp_threadprivate() {
func.func @omp_target(%map1: memref<?xi32>) {
%mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""}
// expected-error @below {{to, from, tofrom and alloc map types are permitted}}
omp.target map_entries(%mapv : memref<?xi32>){}
omp.target map_entries(%mapv -> %arg0: memref<?xi32>) {
^bb0(%arg0: memref<?xi32>):
}
return
}

Expand Down Expand Up @@ -1656,4 +1658,40 @@ func.func @omp_target_exit_data(%map1: memref<?xi32>) {
return
}

// -----

func.func @omp_map1(%map1: memref<?xi32>, %map2: i32) {
%mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) val(%map2 : i32) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
// expected-error @below {{only one of val or var_ptr must be used}}
omp.target map_entries(%mapv -> %arg0: memref<?xi32>) {
^bb0(%arg0: memref<?xi32>):
omp.terminator
}
return
}

// -----

func.func @omp_map2(%map1: memref<?xi32>, %map2: i32) {
%mapv = omp.map_info var_ptr( : , tensor<?xi32>) val(%map2 : i32) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
// expected-error @below {{var_type supplied without var_ptr}}
omp.target map_entries(%mapv -> %arg0: memref<?xi32>) {
^bb0(%arg0: memref<?xi32>):
omp.terminator
}
return
}

// -----

func.func @omp_map3(%map1: memref<?xi32>, %map2: i32) {
%mapv = omp.map_info map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
// expected-error @below {{missing val or var_ptr}}
omp.target map_entries(%mapv -> %arg0: memref<?xi32>) {
^bb0(%arg0: memref<?xi32>):
omp.terminator
}
return
}

llvm.mlir.global internal @_QFsubEx() : i32
21 changes: 15 additions & 6 deletions mlir/test/Dialect/OpenMP/ops.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -492,16 +492,22 @@ func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32, %map1:
// Test with optional map clause.
// CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
// CHECK: %[[MAP_B:.*]] = omp.map_info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
// CHECK: omp.target map_entries(%[[MAP_A]], %[[MAP_B]] : memref<?xi32>, memref<?xi32>) {
// CHECK: omp.target map_entries(%[[MAP_A]] -> {{.*}}, %[[MAP_B]] -> {{.*}} : memref<?xi32>, memref<?xi32>) {
%mapv1 = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
%mapv2 = omp.map_info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
omp.target map_entries(%mapv1, %mapv2 : memref<?xi32>, memref<?xi32>){}
omp.target map_entries(%mapv1 -> %arg0, %mapv2 -> %arg1 : memref<?xi32>, memref<?xi32>) {
^bb0(%arg0: memref<?xi32>, %arg1: memref<?xi32>):
omp.terminator
}
// CHECK: %[[MAP_C:.*]] = omp.map_info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""}
// CHECK: %[[MAP_D:.*]] = omp.map_info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
// CHECK: omp.target map_entries(%[[MAP_C]], %[[MAP_D]] : memref<?xi32>, memref<?xi32>) {
// CHECK: omp.target map_entries(%[[MAP_C]] -> {{.*}}, %[[MAP_D]] -> {{.*}} : memref<?xi32>, memref<?xi32>) {
%mapv3 = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""}
%mapv4 = omp.map_info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
omp.target map_entries(%mapv3, %mapv4 : memref<?xi32>, memref<?xi32>) {}
omp.target map_entries(%mapv3 -> %arg0, %mapv4 -> %arg1 : memref<?xi32>, memref<?xi32>) {
^bb0(%arg0: memref<?xi32>, %arg1: memref<?xi32>):
omp.terminator
}
// CHECK: omp.barrier
omp.barrier

Expand Down Expand Up @@ -2055,8 +2061,11 @@ func.func @omp_targets_with_map_bounds(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> ()
%10 = omp.bounds lower_bound(%7 : i64) upper_bound(%6 : i64) stride(%8 : i64) start_idx(%9 : i64)
%mapv2 = omp.map_info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByCopy) bounds(%10) -> !llvm.ptr {name = ""}

// CHECK: omp.target map_entries(%[[MAP0]], %[[MAP1]] : !llvm.ptr, !llvm.ptr)
omp.target map_entries(%mapv1, %mapv2 : !llvm.ptr, !llvm.ptr){}
// CHECK: omp.target map_entries(%[[MAP0]] -> {{.*}}, %[[MAP1]] -> {{.*}} : !llvm.ptr, !llvm.ptr)
omp.target map_entries(%mapv1 -> %arg2, %mapv2 -> %arg3 : !llvm.ptr, !llvm.ptr) {
^bb0(%arg2: !llvm.ptr, %arg3: !llvm.ptr):
omp.terminator
}

// CHECK: omp.target_data map_entries(%[[MAP0]], %[[MAP1]] : !llvm.ptr, !llvm.ptr)
omp.target_data map_entries(%mapv1, %mapv2 : !llvm.ptr, !llvm.ptr){}
Expand Down
15 changes: 8 additions & 7 deletions mlir/test/Target/LLVMIR/omptarget-array-sectioning-host.mlir
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s

// This test checks the offload sizes provided to the OpenMP kernel argument
// structure are correct when lowering to LLVM-IR from MLIR with 3-D bounds
// provided for a 3-D array. One with full default size, and the other with
// a user specified OpenMP array sectioning. We expect the default sized
// array bounds to lower to the full size of the array and the sectioned
// structure are correct when lowering to LLVM-IR from MLIR with 3-D bounds
// provided for a 3-D array. One with full default size, and the other with
// a user specified OpenMP array sectioning. We expect the default sized
// array bounds to lower to the full size of the array and the sectioned
// array to be the size of 3*3*1*element-byte-size (36 bytes in this case).

module attributes {omp.is_target_device = false} {
Expand All @@ -18,12 +18,13 @@ module attributes {omp.is_target_device = false} {
%6 = omp.bounds lower_bound(%2 : i64) upper_bound(%2 : i64) stride(%2 : i64) start_idx(%2 : i64)
%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)"}
%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)"}
omp.target map_entries(%7, %8 : !llvm.ptr, !llvm.ptr) {
omp.target map_entries(%7 -> %arg0, %8 -> %arg1 : !llvm.ptr, !llvm.ptr) {
^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
%9 = llvm.mlir.constant(0 : i64) : i64
%10 = llvm.mlir.constant(1 : i64) : i64
%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>>>
%11 = llvm.getelementptr %arg0[0, %10, %9, %9] : (!llvm.ptr, i64, i64, i64) -> !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>
%12 = llvm.load %11 : !llvm.ptr -> i32
%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>>>
%13 = llvm.getelementptr %arg1[0, %10, %9, %9] : (!llvm.ptr, i64, i64, i64) -> !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>
llvm.store %12, %13 : i32, !llvm.ptr
omp.terminator
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ module attributes {omp.is_target_device = true} {
%1 = llvm.mlir.addressof @_QFEsp : !llvm.ptr
%2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "sp"}
%3 = omp.map_info var_ptr(%0 : !llvm.ptr, i32) map_clauses(to) capture(ByCopy) -> !llvm.ptr {name = "i"}
omp.target map_entries(%2, %3 : !llvm.ptr, !llvm.ptr) {
%4 = llvm.load %0 : !llvm.ptr -> i32
llvm.store %4, %1 : i32, !llvm.ptr
omp.target map_entries(%2 -> %arg0, %3 -> %arg1 : !llvm.ptr, !llvm.ptr) {
^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
%4 = llvm.load %arg1 : !llvm.ptr -> i32
llvm.store %4, %arg0 : i32, !llvm.ptr
omp.terminator
}
llvm.return
Expand All @@ -32,7 +33,7 @@ module attributes {omp.is_target_device = true} {
// CHECK: store ptr %[[ARG_BYCOPY]], ptr %[[ALLOCA_BYCOPY]], align 8

// CHECK: user_code.entry: ; preds = %entry
// CHECK: %[[LOAD_BYREF:.*]] = load ptr, ptr %[[ALLOCA_BYREF]], align 8
// CHECK: %[[LOAD_BYREF:.*]] = load ptr, ptr %[[ALLOCA_BYREF]], align 8
// CHECK: br label %omp.target

// CHECK: omp.target: ; preds = %user_code.entry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ module attributes {omp.is_target_device = false} {
%1 = llvm.mlir.addressof @_QFEsp : !llvm.ptr
%2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "sp"}
%3 = omp.map_info var_ptr(%0 : !llvm.ptr, i32) map_clauses(to) capture(ByCopy) -> !llvm.ptr {name = "i"}
omp.target map_entries(%2, %3 : !llvm.ptr, !llvm.ptr) {
%4 = llvm.load %0 : !llvm.ptr -> i32
llvm.store %4, %1 : i32, !llvm.ptr
omp.target map_entries(%2 -> %arg0, %3 -> %arg1 : !llvm.ptr, !llvm.ptr) {
^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
%4 = llvm.load %arg1 : !llvm.ptr -> i32
llvm.store %4, %arg0 : i32, !llvm.ptr
omp.terminator
}
llvm.return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s

// This test the generation of additional load operations for declare target link variables
// inside of target op regions when lowering to IR for device. Unfortunately as the host file is not
// inside of target op regions when lowering to IR for device. Unfortunately as the host file is not
// passed as a module attribute, we miss out on the metadata and entryinfo.
//
// Unfortunately, only so much can be tested as the device side is dependent on a *.bc
// Unfortunately, only so much can be tested as the device side is dependent on a *.bc
// file created by the host and appended as an attribute to the module.

module attributes {omp.is_target_device = true} {
Expand All @@ -13,18 +13,19 @@ module attributes {omp.is_target_device = true} {
%0 = llvm.mlir.constant(0 : i32) : i32
llvm.return %0 : i32
}

llvm.func @_QQmain() attributes {} {
%0 = llvm.mlir.addressof @_QMtest_0Esp : !llvm.ptr

// CHECK-DAG: omp.target: ; preds = %user_code.entry
// CHECK-DAG: %[[V:.*]] = load ptr, ptr @_QMtest_0Esp_decl_tgt_ref_ptr, align 8
// CHECK-DAG: store i32 1, ptr %[[V]], align 4
// CHECK-DAG: br label %omp.region.cont
%map = omp.map_info var_ptr(%0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
omp.target map_entries(%map : !llvm.ptr) {
omp.target map_entries(%map -> %arg0 : !llvm.ptr) {
^bb0(%arg0: !llvm.ptr):
%1 = llvm.mlir.constant(1 : i32) : i32
llvm.store %1, %0 : i32, !llvm.ptr
llvm.store %1, %arg0 : i32, !llvm.ptr
omp.terminator
}

Expand Down
9 changes: 5 additions & 4 deletions mlir/test/Target/LLVMIR/omptarget-region-device-llvm.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ module attributes {omp.is_target_device = true} {
%map1 = omp.map_info var_ptr(%3 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
%map2 = omp.map_info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
%map3 = omp.map_info var_ptr(%7 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
omp.target map_entries(%map1, %map2, %map3 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {
%8 = llvm.load %3 : !llvm.ptr -> i32
%9 = llvm.load %5 : !llvm.ptr -> i32
omp.target map_entries(%map1 -> %arg0, %map2 -> %arg1, %map3 -> %arg2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {
^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr):
%8 = llvm.load %arg0 : !llvm.ptr -> i32
%9 = llvm.load %arg1 : !llvm.ptr -> i32
%10 = llvm.add %8, %9 : i32
llvm.store %10, %7 : i32, !llvm.ptr
llvm.store %10, %arg2 : i32, !llvm.ptr
omp.terminator
}
llvm.return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s

module attributes {omp.is_target_device = true} {
llvm.func @writeindex_omp_outline_0_(%arg0: !llvm.ptr, %arg1: !llvm.ptr) attributes {omp.outline_parent_name = "writeindex_"} {
%0 = omp.map_info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
%1 = omp.map_info var_ptr(%arg1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
omp.target map_entries(%0, %1 : !llvm.ptr, !llvm.ptr) {
llvm.func @writeindex_omp_outline_0_(%val0: !llvm.ptr, %val1: !llvm.ptr) attributes {omp.outline_parent_name = "writeindex_"} {
%0 = omp.map_info var_ptr(%val0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
%1 = omp.map_info var_ptr(%val1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
omp.target map_entries(%0 -> %arg0, %1 -> %arg1 : !llvm.ptr, !llvm.ptr) {
^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
%2 = llvm.mlir.constant(20 : i32) : i32
%3 = llvm.mlir.constant(10 : i32) : i32
llvm.store %3, %arg0 : i32, !llvm.ptr
Expand Down
9 changes: 5 additions & 4 deletions mlir/test/Target/LLVMIR/omptarget-region-llvm.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ module attributes {omp.is_target_device = false} {
%map1 = omp.map_info var_ptr(%3 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
%map2 = omp.map_info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
%map3 = omp.map_info var_ptr(%7 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
omp.target map_entries(%map1, %map2, %map3 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {
%8 = llvm.load %3 : !llvm.ptr -> i32
%9 = llvm.load %5 : !llvm.ptr -> i32
omp.target map_entries(%map1 -> %arg0, %map2 -> %arg1, %map3 -> %arg2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {
^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr):
%8 = llvm.load %arg0 : !llvm.ptr -> i32
%9 = llvm.load %arg1 : !llvm.ptr -> i32
%10 = llvm.add %8, %9 : i32
llvm.store %10, %7 : i32, !llvm.ptr
llvm.store %10, %arg2 : i32, !llvm.ptr
omp.terminator
}
llvm.return
Expand Down
9 changes: 5 additions & 4 deletions mlir/test/Target/LLVMIR/omptarget-region-parallel-llvm.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ module attributes {omp.is_target_device = false} {
%map1 = omp.map_info var_ptr(%3 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
%map2 = omp.map_info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
%map3 = omp.map_info var_ptr(%7 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
omp.target map_entries( %map1, %map2, %map3 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {
omp.target map_entries( %map1 -> %arg0, %map2 -> %arg1, %map3 -> %arg2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {
^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr):
omp.parallel {
%8 = llvm.load %3 : !llvm.ptr -> i32
%9 = llvm.load %5 : !llvm.ptr -> i32
%8 = llvm.load %arg0 : !llvm.ptr -> i32
%9 = llvm.load %arg1 : !llvm.ptr -> i32
%10 = llvm.add %8, %9 : i32
llvm.store %10, %7 : i32, !llvm.ptr
llvm.store %10, %arg2 : i32, !llvm.ptr
omp.terminator
}
omp.terminator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ program main
end do

i = 1
j = 1
j = 1
k = 1

!$omp target map(tofrom:x, counter) map(to: i, j, k, i2, j2, k2)
Expand All @@ -50,5 +50,12 @@ program main
end do
end do
end program main

! CHECK: 1 2 3 4 5 6 7 8

! CHECK: 1
! CHECK: 2
! CHECK: 3
! CHECK: 4
! CHECK: 5
! CHECK: 6
! CHECK: 7
! CHECK: 8
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,18 @@
! UNSUPPORTED: x86_64-pc-linux-gnu-LTO

! RUN: %libomptarget-compile-fortran-run-and-check-generic
! XFAIL: *

program main
use omp_lib
integer :: tmp, var4
common var4
var4 = 24
tmp = 12
print *, "var4 before target = ", var4
print *, "var4 before target =", var4
!$omp target map(tofrom:var4)
var4 = tmp
!$omp end target
print *, "var4 after target = ", var4
print *, "var4 after target =", var4
end program

! CHECK: var4 before target = 24
Expand Down