!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s !=============================================================================== ! Target_Enter Simple !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_enter_simple() { subroutine omp_target_enter_simple integer :: a(1024) !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_enter_data map_entries(%[[MAP]] : !fir.ref>) !$omp target enter data map(to: a) return end subroutine omp_target_enter_simple !=============================================================================== ! Target_Enter `depend` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_enter_depend() { subroutine omp_target_enter_depend !CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFomp_target_enter_dependEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: omp.task depend(taskdependout -> %[[A]]#1 : !fir.ref>) { !$omp task depend(out: a) call foo(a) !$omp end task !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_enter_data map_entries(%[[MAP]] : !fir.ref>) depend(taskdependin -> %[[A]]#1 : !fir.ref>) !$omp target enter data map(to: a) depend(in: a) return end subroutine omp_target_enter_depend !=============================================================================== ! Target_Enter Map types !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_enter_mt() { subroutine omp_target_enter_mt integer :: a(1024) integer :: b(1024) integer :: c(1024) integer :: d(1024) !CHECK: %[[BOUNDS_0:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_0:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref> {name = "a"} !CHECK: %[[BOUNDS_1:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_1:.*]] = omp.map.info var_ptr(%{{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref> {name = "b"} !CHECK: %[[BOUNDS_2:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref> {name = "c"} !CHECK: %[[BOUNDS_3:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref> {name = "d"} !CHECK: omp.target_enter_data map_entries(%[[MAP_0]], %[[MAP_1]], %[[MAP_2]], %[[MAP_3]] : !fir.ref>, !fir.ref>, !fir.ref>, !fir.ref>) !$omp target enter data map(to: a, b) map(always, alloc: c) map(to: d) end subroutine omp_target_enter_mt !=============================================================================== ! `Nowait` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_enter_nowait() { subroutine omp_target_enter_nowait integer :: a(1024) !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_enter_data nowait map_entries(%[[MAP]] : !fir.ref>) !$omp target enter data map(to: a) nowait end subroutine omp_target_enter_nowait !=============================================================================== ! `if` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_enter_if() { subroutine omp_target_enter_if integer :: a(1024) integer :: i i = 5 !CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1:.*]] : !fir.ref !CHECK: %[[VAL_4:.*]] = arith.constant 10 : i32 !CHECK: %[[VAL_5:.*]] = arith.cmpi slt, %[[VAL_3]], %[[VAL_4]] : i32 !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_enter_data if(%[[VAL_5]] : i1) map_entries(%[[MAP]] : !fir.ref>) !$omp target enter data if(i<10) map(to: a) end subroutine omp_target_enter_if !=============================================================================== ! `device` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_enter_device() { subroutine omp_target_enter_device integer :: a(1024) !CHECK: %[[VAL_1:.*]] = arith.constant 2 : i32 !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_enter_data device(%[[VAL_1]] : i32) map_entries(%[[MAP]] : !fir.ref>) !$omp target enter data map(to: a) device(2) end subroutine omp_target_enter_device !=============================================================================== ! Target_Exit Simple !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_exit_simple() { subroutine omp_target_exit_simple integer :: a(1024) !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_exit_data map_entries(%[[MAP]] : !fir.ref>) !$omp target exit data map(from: a) end subroutine omp_target_exit_simple !=============================================================================== ! Target_Exit Map types !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_exit_mt() { subroutine omp_target_exit_mt integer :: a(1024) integer :: b(1024) integer :: c(1024) integer :: d(1024) integer :: e(1024) !CHECK: %[[BOUNDS_0:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_0:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref> {name = "a"} !CHECK: %[[BOUNDS_1:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_1:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref> {name = "b"} !CHECK: %[[BOUNDS_2:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref> {name = "c"} !CHECK: %[[BOUNDS_3:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(always, delete) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref> {name = "d"} !CHECK: %[[BOUNDS_4:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_4:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_4]]) -> !fir.ref> {name = "e"} !CHECK: omp.target_exit_data map_entries(%[[MAP_0]], %[[MAP_1]], %[[MAP_2]], %[[MAP_3]], %[[MAP_4]] : !fir.ref>, !fir.ref>, !fir.ref>, !fir.ref>, !fir.ref>) !$omp target exit data map(from: a,b) map(release: c) map(always, delete: d) map(from: e) end subroutine omp_target_exit_mt !=============================================================================== ! `device` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_exit_device() { subroutine omp_target_exit_device integer :: a(1024) integer :: d !CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1:.*]] : !fir.ref !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_exit_data device(%[[VAL_2]] : i32) map_entries(%[[MAP]] : !fir.ref>) !$omp target exit data map(from: a) device(d) end subroutine omp_target_exit_device !=============================================================================== ! Target_Exit `depend` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_exit_depend() { subroutine omp_target_exit_depend !CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFomp_target_exit_dependEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: omp.task depend(taskdependout -> %[[A]]#1 : !fir.ref>) { !$omp task depend(out: a) call foo(a) !$omp end task !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_exit_data map_entries(%[[MAP]] : !fir.ref>) depend(taskdependout -> %[[A]]#1 : !fir.ref>) !$omp target exit data map(from: a) depend(out: a) end subroutine omp_target_exit_depend !=============================================================================== ! Target_Update `depend` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_update_depend() { subroutine omp_target_update_depend !CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFomp_target_update_dependEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: omp.task depend(taskdependout -> %[[A]]#1 : !fir.ref>) { !$omp task depend(out: a) call foo(a) !$omp end task !CHECK: %[[BOUNDS:.*]] = omp.map.bounds !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_update motion_entries(%[[MAP]] : !fir.ref>) depend(taskdependin -> %[[A]]#1 : !fir.ref>) !$omp target update to(a) depend(in:a) end subroutine omp_target_update_depend !=============================================================================== ! Target_Update `to` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_update_to() { subroutine omp_target_update_to integer :: a(1024) !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds !CHECK: %[[TO_MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) !CHECK-SAME: map_clauses(to) capture(ByRef) !CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_update motion_entries(%[[TO_MAP]] : !fir.ref>) !$omp target update to(a) end subroutine omp_target_update_to !=============================================================================== ! Target_Update `from` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_update_from() { subroutine omp_target_update_from integer :: a(1024) !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds !CHECK: %[[FROM_MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) !CHECK-SAME: map_clauses(from) capture(ByRef) !CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_update motion_entries(%[[FROM_MAP]] : !fir.ref>) !$omp target update from(a) end subroutine omp_target_update_from !=============================================================================== ! Target_Update `if` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_update_if() { subroutine omp_target_update_if integer :: a(1024) logical :: i !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds !CHECK-DAG: %[[COND:.*]] = fir.convert %{{.*}} : (!fir.logical<4>) -> i1 !CHECK: omp.target_update if(%[[COND]] : i1) motion_entries !$omp target update from(a) if(i) end subroutine omp_target_update_if !=============================================================================== ! Target_Update `device` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_update_device() { subroutine omp_target_update_device integer :: a(1024) logical :: i !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds !CHECK-DAG: %[[DEVICE:.*]] = arith.constant 1 : i32 !CHECK: omp.target_update device(%[[DEVICE]] : i32) motion_entries !$omp target update from(a) device(1) end subroutine omp_target_update_device !=============================================================================== ! Target_Update `nowait` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_update_nowait() { subroutine omp_target_update_nowait integer :: a(1024) logical :: i !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds !CHECK: omp.target_update nowait motion_entries !$omp target update from(a) nowait end subroutine omp_target_update_nowait !=============================================================================== ! Target_Data with region !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_data() { subroutine omp_target_data !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_dataEa"} !CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[VAL_0]](%{{.*}}) {uniq_name = "_QFomp_target_dataEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP]] : !fir.ref>) { !$omp target data map(tofrom: a) !CHECK: %[[C10:.*]] = arith.constant 10 : i32 !CHECK: %[[C1:.*]] = arith.constant 1 : index !CHECK: %[[A_1:.*]] = hlfir.designate %[[A_DECL]]#0 (%[[C1]]) : (!fir.ref>, index) -> !fir.ref !CHECK: hlfir.assign %[[C10]] to %[[A_1]] : i32, !fir.ref {bindc_name = "a", uniq_name = "_QFomp_target_data_mtEa"} !CHECK: %[[VAR_A_DECL:.*]]:2 = hlfir.declare %[[VAR_A]](%{{.*}}) {uniq_name = "_QFomp_target_data_mtEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) !CHECK: %[[VAR_B:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "b", uniq_name = "_QFomp_target_data_mtEb"} !CHECK: %[[VAR_B_DECL:.*]]:2 = hlfir.declare %[[VAR_B]](%{{.*}}) {uniq_name = "_QFomp_target_data_mtEb"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) !CHECK: %[[BOUNDS_A:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAR_A_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP_A]] : !fir.ref>) { !$omp target data map(a) !CHECK: omp.terminator !$omp end target data !CHECK: } !CHECK: %[[BOUNDS_B:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAR_B_DECL]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(always, from) capture(ByRef) bounds(%[[BOUNDS_B]]) -> !fir.ref> {name = "b"} !CHECK: omp.target_data map_entries(%[[MAP_B]] : !fir.ref>) { !$omp target data map(always, from : b) !CHECK: omp.terminator !$omp end target data !CHECK: } end subroutine omp_target_data_mt !=============================================================================== ! Target with region !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target() { subroutine omp_target !CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFomp_targetEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_1]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]] : !fir.ref>) { !CHECK: ^bb0(%[[ARG_0]]: !fir.ref>): !$omp target map(tofrom: a) !CHECK: %[[VAL_7:.*]] = arith.constant 1024 : index !CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> !CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG_0]](%[[VAL_2]]) {uniq_name = "_QFomp_targetEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) !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>, index) -> !fir.ref !CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_6]] : i32, !fir.ref a(1) = 10 !CHECK: omp.terminator !$omp end target !CHECK: } end subroutine omp_target !=============================================================================== ! Target with region `depend` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_depend() { subroutine omp_target_depend !CHECK: %[[EXTENT_A:.*]] = arith.constant 1024 : index !CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFomp_target_dependEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: omp.task depend(taskdependout -> %[[A]]#1 : !fir.ref>) { !$omp task depend(out: a) call foo(a) !$omp end task !CHECK: %[[STRIDE_A:.*]] = arith.constant 1 : index !CHECK: %[[LBOUND_A:.*]] = arith.constant 0 : index !CHECK: %[[UBOUND_A:.*]] = arith.subi %c1024, %c1 : index !CHECK: %[[BOUNDS_A:.*]] = omp.map.bounds lower_bound(%[[LBOUND_A]] : index) upper_bound(%[[UBOUND_A]] : index) extent(%[[EXTENT_A]] : index) stride(%[[STRIDE_A]] : index) start_idx(%[[STRIDE_A]] : index) !CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref> {name = "a"} !CHECK: omp.target map_entries(%[[MAP_A]] -> %[[BB0_ARG:.*]] : !fir.ref>) depend(taskdependin -> %[[A]]#1 : !fir.ref>) { !$omp target map(tofrom: a) depend(in: a) a(1) = 10 !CHECK: omp.terminator !$omp end target !CHECK: } end subroutine omp_target_depend !=============================================================================== ! 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.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: %[[VAL_4:.*]] = omp.map.info var_ptr(%[[VAL_3]]#1 : !fir.ref>, !fir.array<1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.ref> {name = "a"} !CHECK: omp.target map_entries(%[[VAL_4]] -> %[[VAL_6:.*]] : !fir.ref>) { !CHECK: ^bb0(%[[VAL_6]]: !fir.ref>): !$omp target !CHECK: %[[VAL_7:.*]] = arith.constant 1024 : index !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.shape<1>) -> (!fir.ref>, !fir.ref>) !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>, index) -> !fir.ref !CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_12]] : i32, !fir.ref 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, !fir.ref) { !CHECK: ^bb0(%[[ARG0]]: !fir.ref, %[[ARG1]]: !fir.ref): !$omp target !CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFomp_target_implicit_nestedEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG1]] {uniq_name = "_QFomp_target_implicit_nestedEb"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[VAL_10:.*]] = arith.constant 10 : i32 !CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_8]]#0 : i32, !fir.ref 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 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( !CHECK: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "n"}) { subroutine omp_target_implicit_bounds(n) !CHECK: %[[VAL_COPY:.*]] = fir.alloca i32 !CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFomp_target_implicit_boundsEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref !CHECK: fir.store %[[VAL_2]] to %[[VAL_COPY]] : !fir.ref !CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (i32) -> i64 !CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index !CHECK: %[[VAL_5:.*]] = arith.constant 0 : index !CHECK: %[[VAL_6:.*]] = arith.cmpi sgt, %[[VAL_4]], %[[VAL_5]] : index !CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_6]], %[[VAL_4]], %[[VAL_5]] : index !CHECK: %[[VAL_8:.*]] = fir.alloca !fir.array, %[[VAL_7]] {bindc_name = "a", uniq_name = "_QFomp_target_implicit_boundsEa"} !CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_7]] : (index) -> !fir.shape<1> !CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_8]](%[[VAL_9]]) {uniq_name = "_QFomp_target_implicit_boundsEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.box>, !fir.ref>) !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %9#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) !CHECK: %[[UB:.*]] = arith.subi %[[DIMS0]]#1, %c1{{.*}} : index integer :: n integer :: a(n) !CHECK: %[[VAL_14:.*]] = omp.map.bounds lower_bound(%c0{{.*}} : index) upper_bound(%[[UB]] : index) extent(%[[DIMS0]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%c1{{.*}} : index) {stride_in_bytes = true} !CHECK: %[[VAL_15:.*]] = omp.map.info var_ptr(%[[VAL_10]]#1 : !fir.ref>, !fir.array) map_clauses(implicit, tofrom) capture(ByRef) bounds(%[[VAL_14]]) -> !fir.ref> {name = "a"} !CHECK: %[[VAL_16:.*]] = omp.map.info var_ptr(%[[VAL_COPY]] : !fir.ref, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref {name = ""} !CHECK: omp.target map_entries(%[[VAL_15]] -> %[[VAL_17:.*]], %[[VAL_16]] -> %[[VAL_18:.*]] : !fir.ref>, !fir.ref) { !CHECK: ^bb0(%[[VAL_17]]: !fir.ref>, %[[VAL_18]]: !fir.ref): !$omp target !CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_18]] : !fir.ref !CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 !CHECK: %[[VAL_21:.*]] = arith.constant 0 : index !CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_20]] : (i64) -> index !CHECK: %[[VAL_23:.*]] = arith.cmpi sgt, %[[VAL_22]], %[[VAL_21]] : index !CHECK: %[[VAL_24:.*]] = arith.select %[[VAL_23]], %[[VAL_22]], %[[VAL_21]] : index !CHECK: %[[VAL_25:.*]] = fir.shape %[[VAL_24]] : (index) -> !fir.shape<1> !CHECK: %[[VAL_26:.*]]:2 = hlfir.declare %[[VAL_17]](%[[VAL_25]]) {uniq_name = "_QFomp_target_implicit_boundsEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.box>, !fir.ref>) !CHECK: %[[VAL_27:.*]] = arith.constant 22 : i32 !CHECK: %[[VAL_28:.*]] = arith.constant 11 : index !CHECK: %[[VAL_29:.*]] = hlfir.designate %[[VAL_26]]#0 (%[[VAL_28]]) : (!fir.box>, index) -> !fir.ref !CHECK: hlfir.assign %[[VAL_27]] to %[[VAL_29]] : i32, !fir.ref a(11) = 22 !CHECK: omp.terminator !$omp end target !CHECK: } end subroutine omp_target_implicit_bounds !=============================================================================== ! Target `thread_limit` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_thread_limit() { 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 {name = "a"} !CHECK: omp.target thread_limit(%[[VAL_1]] : i32) map_entries(%[[MAP]] -> %{{.*}} : !fir.ref) { !CHECK: ^bb0(%{{.*}}: !fir.ref): !$omp target map(tofrom: a) thread_limit(64) a = 10 !CHECK: omp.terminator !$omp end target !CHECK: } end subroutine omp_target_thread_limit !=============================================================================== ! Target `use_device_ptr` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_device_ptr() { subroutine omp_target_device_ptr use iso_c_binding, only : c_ptr, c_loc type(c_ptr) :: a integer, target :: b !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> {{.*}} {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP]]{{.*}} !$omp target data map(tofrom: a) use_device_ptr(a) !CHECK: ^bb0(%[[VAL_1:.*]]: !fir.ref>): !CHECK: {{.*}} = fir.coordinate_of %[[VAL_1:.*]], {{.*}} : (!fir.ref>, !fir.field) -> !fir.ref a = c_loc(b) !CHECK: omp.terminator !$omp end target data !CHECK: } end subroutine omp_target_device_ptr !=============================================================================== ! Target `use_device_addr` clause !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_device_addr() { subroutine omp_target_device_addr integer, pointer :: a !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box> {bindc_name = "a", uniq_name = "_QFomp_target_device_addrEa"} !CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) !CHECK: %[[MAP_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBERS]] : !fir.llvm_ptr>) -> !fir.ref>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP_MEMBERS]], %[[MAP]] : {{.*}}) use_device_addr(%[[VAL_0_DECL]]#1 : !fir.ref>>) { !$omp target data map(tofrom: a) use_device_addr(a) !CHECK: ^bb0(%[[VAL_1:.*]]: !fir.ref>>): !CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) !CHECK: %[[C10:.*]] = arith.constant 10 : i32 !CHECK: %[[A_BOX:.*]] = fir.load %[[VAL_1_DECL]]#0 : !fir.ref>> !CHECK: %[[A_ADDR:.*]] = fir.box_addr %[[A_BOX]] : (!fir.box>) -> !fir.ptr !CHECK: hlfir.assign %[[C10]] to %[[A_ADDR]] : i32, !fir.ptr a = 10 !CHECK: omp.terminator !$omp end target data !CHECK: } end subroutine omp_target_device_addr !=============================================================================== ! Target Data with unstructured code !=============================================================================== !CHECK-LABEL: func.func @_QPsb subroutine sb integer :: i = 1 integer :: j = 11 !CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}} : !fir.ref, !fir.ref) !$omp target data map(tofrom: i, j) j = j - 1 !CHECK: %[[J_VAL:.*]] = arith.subi !CHECK: hlfir.assign %[[J_VAL]] !CHECK: cf.br ^[[BB:.*]] !CHECK: ^[[BB]]: goto 20 20 i = i + 1 !CHECK: %[[I_VAL:.*]] = arith.addi !CHECK: hlfir.assign %[[I_VAL]] !CHECK: omp.terminator !$omp end target data end subroutine !=============================================================================== ! Target with parallel loop !=============================================================================== !CHECK-LABEL: func.func @_QPomp_target_parallel_do() { subroutine omp_target_parallel_do !CHECK: %[[C1024:.*]] = arith.constant 1024 : index !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_parallel_doEa"} !CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]](%{{.*}}) {uniq_name = "_QFomp_target_parallel_doEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) integer :: a(1024) !CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_target_parallel_doEi"} !CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_target_parallel_doEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) integer :: i !CHECK: %[[C1:.*]] = arith.constant 1 : index !CHECK: %[[C0:.*]] = arith.constant 0 : index !CHECK: %[[SUB:.*]] = arith.subi %[[C1024]], %[[C1]] : index !CHECK: %[[BOUNDS:.*]] = omp.map.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]]#0 : !fir.ref>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]], %{{.*}} -> %{{.*}} : !fir.ref>, !fir.ref) { !CHECK: ^bb0(%[[ARG_0]]: !fir.ref>, %{{.*}}: !fir.ref): !CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[ARG_0]](%{{.*}}) {uniq_name = "_QFomp_target_parallel_doEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) !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) -> (!fir.ref, !fir.ref) !CHECK: omp.wsloop for (%[[I_VAL:.*]]) : i32 do i = 1, 1024 !CHECK: fir.store %[[I_VAL]] to %[[I_PVT_DECL]]#1 : !fir.ref !CHECK: %[[C10:.*]] = arith.constant 10 : i32 !CHECK: %[[I_PVT_VAL:.*]] = fir.load %[[I_PVT_DECL]]#0 : !fir.ref !CHECK: %[[I_VAL:.*]] = fir.convert %[[I_PVT_VAL]] : (i32) -> i64 !CHECK: %[[A_I:.*]] = hlfir.designate %[[VAL_0_DECL]]#0 (%[[I_VAL]]) : (!fir.ref>, i64) -> !fir.ref !CHECK: hlfir.assign %[[C10]] to %[[A_I]] : i32, !fir.ref a(i) = 10 end do !CHECK: omp.yield !CHECK: } !CHECK: omp.terminator !CHECK: } !CHECK: omp.terminator !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) -> (!fir.ref, !fir.ref) integer :: i = 1 !CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtarget_unstructuredEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) integer :: j = 11 !CHECK: %[[VAL_4:.*]] = omp.map.info var_ptr(%[[VAL_1]]#1 : !fir.ref, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref {name = "i"} !CHECK: %[[VAL_5:.*]] = omp.map.info var_ptr(%[[VAL_3]]#1 : !fir.ref, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref {name = "j"} !CHECK: omp.target map_entries(%[[VAL_4]] -> %[[VAL_6:.*]], %[[VAL_5]] -> %[[VAL_7:.*]] : !fir.ref, !fir.ref) { !CHECK: ^bb0(%[[VAL_6]]: !fir.ref, %[[VAL_7]]: !fir.ref): !$omp target !CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFtarget_unstructuredEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFtarget_unstructuredEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) !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