CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
784 lines
46 KiB
Fortran
784 lines
46 KiB
Fortran
! The "thread_limit" clause was added to the "target" construct in OpenMP 5.1.
|
|
! NOTE: Do not check for false delayed privatization flag until all enable-delayed-privatization flags are switched on in amd-staging
|
|
!RUN %flang_fc1 -emit-hlfir -fopenmp -mmlir --enable-delayed-privatization-staging=false -fopenmp-version=51 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NO-FPRIV
|
|
!RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --enable-delayed-privatization-staging=true -fopenmp-version=51 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-FPRIV
|
|
|
|
!===============================================================================
|
|
! 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<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_enter_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$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.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
integer :: a(1024)
|
|
|
|
!CHECK: omp.task depend(taskdependout -> %[[A]]#0 : !fir.ref<!fir.array<1024xi32>>) private({{.*}}) {
|
|
!$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<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_enter_data depend(taskdependin -> %[[A]]#0 : !fir.ref<!fir.array<1024xi32>>) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$omp target enter data map(to: a) depend(in: a)
|
|
return
|
|
end subroutine omp_target_enter_depend
|
|
|
|
!CHECK-LABEL: func.func @_QPomp_target_enter_depend_section() {
|
|
subroutine omp_target_enter_depend_section
|
|
!CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFomp_target_enter_depend_sectionEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
integer :: a(1024)
|
|
|
|
!CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[A]]#0 ({{.*}}) shape %{{.*}} : (!fir.ref<!fir.array<1024xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<512xi32>>
|
|
!CHECK: omp.task depend(taskdependout -> %[[DESIGNATE]] : !fir.ref<!fir.array<512xi32>>) private({{.*}}) {
|
|
!$omp task depend(out: a(1:512))
|
|
call foo(a)
|
|
!$omp end task
|
|
!CHECK: %[[DESIGNATE2:.*]] = hlfir.designate %[[A]]#0 ({{.*}}) shape %{{.*}} : (!fir.ref<!fir.array<1024xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<512xi32>>
|
|
!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<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_enter_data depend(taskdependin -> %[[DESIGNATE2]] : !fir.ref<!fir.array<512xi32>>) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$omp target enter data map(to: a) depend(in: a(1:512))
|
|
return
|
|
end subroutine omp_target_enter_depend_section
|
|
|
|
!===============================================================================
|
|
! 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<!fir.array<1024xi32>> {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<!fir.array<1024xi32>> {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, storage) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {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<!fir.array<1024xi32>> {name = "d"}
|
|
!CHECK: omp.target_enter_data map_entries(%[[MAP_0]], %[[MAP_1]], %[[MAP_2]], %[[MAP_3]] : !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
!$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<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_enter_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) nowait
|
|
!$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<i32>
|
|
!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<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_enter_data if(%[[VAL_5]]) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$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<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_enter_data device(%[[VAL_1]] : i32) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$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<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_exit_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$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<!fir.array<1024xi32>> {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<!fir.array<1024xi32>> {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(storage) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {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, storage) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref<!fir.array<1024xi32>> {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<!fir.array<1024xi32>> {name = "e"}
|
|
!CHECK: omp.target_exit_data map_entries(%[[MAP_0]], %[[MAP_1]], %[[MAP_2]], %[[MAP_3]], %[[MAP_4]] : !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
!$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<i32>
|
|
!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<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_exit_data device(%[[VAL_2]] : i32) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$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.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
integer :: a(1024)
|
|
!CHECK: omp.task depend(taskdependout -> %[[A]]#0 : !fir.ref<!fir.array<1024xi32>>) private({{.*}}) {
|
|
!$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<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_exit_data depend(taskdependout -> %[[A]]#0 : !fir.ref<!fir.array<1024xi32>>) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$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.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
integer :: a(1024)
|
|
|
|
!CHECK: omp.task depend(taskdependout -> %[[A]]#0 : !fir.ref<!fir.array<1024xi32>>) private({{.*}}) {
|
|
!$omp task depend(out: a)
|
|
call foo(a)
|
|
!$omp end task
|
|
|
|
!CHECK: %[[BOUNDS:.*]] = omp.map.bounds
|
|
!CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_update depend(taskdependin -> %[[A]]#0 : !fir.ref<!fir.array<1024xi32>>) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$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]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
|
|
!CHECK-SAME: map_clauses(to) capture(ByRef)
|
|
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
|
|
|
|
!CHECK: omp.target_update map_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$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]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
|
|
!CHECK-SAME: map_clauses(from) capture(ByRef)
|
|
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
|
|
|
|
!CHECK: omp.target_update map_entries(%[[FROM_MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
|
!$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]]) map_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) map_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 map_entries({{.*}}) nowait
|
|
!$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.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
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]]#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_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) {
|
|
!$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<!fir.array<1024xi32>>, index) -> !fir.ref<i32>
|
|
!CHECK: hlfir.assign %[[C10]] to %[[A_1]] : i32, !fir.ref<i32
|
|
a(1) = 10
|
|
!CHECK: omp.terminator
|
|
!$omp end target data
|
|
!CHECK: }
|
|
end subroutine omp_target_data
|
|
|
|
!CHECK-LABEL: func.func @_QPomp_target_data_mt
|
|
subroutine omp_target_data_mt
|
|
integer :: a(1024)
|
|
integer :: b(1024)
|
|
!CHECK: %[[VAR_A:.*]] = fir.alloca !fir.array<1024xi32> {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.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
!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.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
!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]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target_data map_entries(%[[MAP_A]] : !fir.ref<!fir.array<1024xi32>>) {
|
|
!$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]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(always, from) capture(ByRef) bounds(%[[BOUNDS_B]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"}
|
|
!CHECK: omp.target_data map_entries(%[[MAP_B]] : !fir.ref<!fir.array<1024xi32>>) {
|
|
!$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.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
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]]#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:.*]] : !fir.ref<!fir.array<1024xi32>>) {
|
|
!$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.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
|
|
!$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.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
integer :: a(1024)
|
|
!CHECK: omp.task depend(taskdependout -> %[[A]]#0 : !fir.ref<!fir.array<1024xi32>>) private({{.*}}) {
|
|
!$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]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
|
|
!CHECK: omp.target depend(taskdependin -> %[[A]]#0 : !fir.ref<!fir.array<1024xi32>>) map_entries(%[[MAP_A]] -> %[[BB0_ARG:.*]] : !fir.ref<!fir.array<1024xi32>>) {
|
|
!$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.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: omp.target map_entries(%[[VAL_4]] -> %[[VAL_6:.*]] : !fir.ref<!fir.array<1024xi32>>) {
|
|
!$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.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-NO-FPRIV: omp.target map_entries(%{{.*}} -> %[[ARG0:.*]], %{{.*}} -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
|
|
!CHECK-FPRIV: omp.target map_entries(%{{.*}} -> %[[ARG0:.*]], %{{.*}} -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) private(@{{.*}} %{{.*}} -> %[[ARG2:.*]] [map_idx=0], @{{.*}} %{{.*}} -> %[[ARG3:.*]] [map_idx=1] : !fir.ref<i32>, !fir.ref<i32>) {
|
|
!$omp target
|
|
!CHECK-NO-FPRIV: %[[VAL_8:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFomp_target_implicit_nestedEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
|
!CHECK-NO-FPRIV: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG1]] {uniq_name = "_QFomp_target_implicit_nestedEb"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
|
!CHECK-FPRIV: %[[VAL_8:.*]]:2 = hlfir.declare %[[ARG2]] {uniq_name = "_QFomp_target_implicit_nestedEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
|
!CHECK-FPRIV: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG3]] {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(
|
|
!CHECK: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) {
|
|
subroutine omp_target_implicit_bounds(n)
|
|
!CHECK: %[[VAL_COPY:.*]] = fir.alloca i32
|
|
!CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFomp_target_implicit_boundsEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
|
|
!CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i32>
|
|
!CHECK: fir.store %[[VAL_2]] to %[[VAL_COPY]] : !fir.ref<i32>
|
|
!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<?xi32>, %[[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.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>)
|
|
!CHECK: %[[UB:.*]] = arith.subi %[[VAL_7]], %c1{{.*}} : index
|
|
|
|
integer :: n
|
|
integer :: a(n)
|
|
!CHECK: %[[VAL_14:.*]] = omp.map.bounds lower_bound(%c0{{.*}} : index) upper_bound(%[[UB]] : index) extent(%[[VAL_7]] : index) stride(%c1{{.*}} : index) start_idx(%c1{{.*}} : index)
|
|
!CHECK: %[[VAL_15:.*]] = omp.map.info var_ptr(%[[VAL_10]]#1 : !fir.ref<!fir.array<?xi32>>, i32) map_clauses(implicit, tofrom) capture(ByRef) bounds(%[[VAL_14]]) -> !fir.ref<!fir.array<?xi32>> {name = "a"}
|
|
!CHECK: %[[VAL_16:.*]] = omp.map.info var_ptr(%[[VAL_COPY]] : !fir.ref<i32>, i32) map_clauses(implicit) capture(ByCopy) -> !fir.ref<i32> {name = ""}
|
|
!CHECK: omp.target map_entries(%[[VAL_15]] -> %[[VAL_17:.*]], %[[VAL_16]] -> %[[VAL_18:.*]] : !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) {
|
|
!$omp target
|
|
!CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_18]] : !fir.ref<i32>
|
|
!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.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>)
|
|
!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<!fir.array<?xi32>>, index) -> !fir.ref<i32>
|
|
!CHECK: hlfir.assign %[[VAL_27]] to %[[VAL_29]] : i32, !fir.ref<i32>
|
|
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: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a"}
|
|
!CHECK: %[[VAL_1:.*]] = arith.constant 64 : i32
|
|
!CHECK: omp.target thread_limit(%[[VAL_1]] : i32) map_entries(%[[MAP]] -> %{{.*}} : !fir.ref<i32>) {
|
|
!$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) mapper(@[[CPTR_DEFAULT:_QQM__fortran_builtinsc_ptr_omp_default_mapper]]) -> {{.*}} {name = "a"}
|
|
!CHECK: omp.target_data map_entries(%[[MAP]]{{.*}}) use_device_ptr({{.*}} -> %[[VAL_1:.*]] : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
|
|
!$omp target data map(tofrom: a) use_device_ptr(a)
|
|
!CHECK: {{.*}} = fir.coordinate_of %[[VAL_1:.*]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64>
|
|
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<!fir.ptr<i32>> {bindc_name = "a", uniq_name = "_QFomp_target_device_addrEa"}
|
|
!CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
|
|
!CHECK: %[[MAP_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
|
|
!CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, descriptor, to) capture(ByRef) members(%[[MAP_MEMBERS]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"}
|
|
!CHECK: %[[MAP_ATTACH:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(attach, ref_ptr, ref_ptee) capture(ByRef) var_ptr_ptr(%{{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"}
|
|
!CHECK: %[[DEV_ADDR_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(return_param) capture(ByRef) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
|
|
!CHECK: %[[DEV_ADDR:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, descriptor, to) capture(ByRef) members(%[[DEV_ADDR_MEMBERS]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"}
|
|
!CHECK: %[[DEV_ADDR_ATTACH:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(attach, ref_ptr, ref_ptee) capture(ByRef) var_ptr_ptr(%{{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"}
|
|
!CHECK: omp.target_data map_entries(%[[MAP]], %[[MAP_ATTACH]], %[[DEV_ADDR_ATTACH]], %[[MAP_MEMBERS]] : {{.*}}) use_device_addr(%[[DEV_ADDR]] -> %[[ARG_0:.*]], %[[DEV_ADDR_MEMBERS]] -> %[[ARG_1:.*]] : {{.*}}) {
|
|
!$omp target data map(tofrom: a) use_device_addr(a)
|
|
!CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[ARG_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
|
|
!CHECK: %[[C10:.*]] = arith.constant 10 : i32
|
|
!CHECK: %[[A_BOX:.*]] = fir.load %[[VAL_1_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
|
|
!CHECK: %[[A_ADDR:.*]] = fir.box_addr %[[A_BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
|
|
!CHECK: hlfir.assign %[[C10]] to %[[A_ADDR]] : i32, !fir.ptr<i32>
|
|
a = 10
|
|
!CHECK: omp.terminator
|
|
!$omp end target data
|
|
!CHECK: }
|
|
end subroutine omp_target_device_addr
|
|
|
|
|
|
!===============================================================================
|
|
! Target `is_device_ptr` clause
|
|
!===============================================================================
|
|
|
|
!CHECK-LABEL: func.func @_QPomp_target_is_device_ptr() {
|
|
subroutine omp_target_is_device_ptr
|
|
use iso_c_binding, only: c_ptr
|
|
implicit none
|
|
integer :: i
|
|
integer :: arr(4)
|
|
type(c_ptr) :: p
|
|
|
|
i = 0
|
|
arr = 0
|
|
|
|
!CHECK: %[[P_STORAGE:.*]] = omp.map.info {{.*}}{name = "p"}
|
|
!CHECK: %[[P_IS:.*]] = omp.map.info {{.*}}{name = "p"}
|
|
!CHECK: %[[ARR_MAP:.*]] = omp.map.info {{.*}}{name = "arr"}
|
|
!CHECK: omp.target is_device_ptr(%[[P_IS]] :
|
|
!CHECK-SAME: has_device_addr(%[[P_STORAGE]] ->
|
|
!CHECK-SAME: map_entries({{.*}}%[[ARR_MAP]] ->
|
|
!$omp target is_device_ptr(p)
|
|
i = i + 1
|
|
arr(1) = i
|
|
!$omp end target
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
end subroutine omp_target_is_device_ptr
|
|
|
|
|
|
!===============================================================================
|
|
! 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<i32>, !fir.ref<i32>)
|
|
!$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.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>)
|
|
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<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
|
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]]#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:.*]], %{{.*}} -> %{{.*}} : !fir.ref<!fir.array<1024xi32>>, !fir.ref<i32>) {
|
|
!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: omp.wsloop private(@{{.*}} %{{.*}}#0 -> %[[I_PVT_ALLOCA:.*]] : !fir.ref<i32>) {
|
|
!CHECK-NEXT: omp.loop_nest (%[[I_VAL:.*]]) : i32
|
|
do i = 1, 1024
|
|
!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>)
|
|
!CHECK: hlfir.assign %[[I_VAL]] to %[[I_PVT_DECL]]#0 : i32, !fir.ref<i32>
|
|
!CHECK: %[[C10:.*]] = arith.constant 10 : i32
|
|
!CHECK: %[[I_PVT_VAL:.*]] = fir.load %[[I_PVT_DECL]]#0 : !fir.ref<i32>
|
|
!CHECK: %[[I_VAL:.*]] = fir.convert %[[I_PVT_VAL]] : (i32) -> i64
|
|
!CHECK: %[[A_I:.*]] = hlfir.designate %[[VAL_0_DECL]]#0 (%[[I_VAL]]) : (!fir.ref<!fir.array<1024xi32>>, i64) -> !fir.ref<i32>
|
|
!CHECK: hlfir.assign %[[C10]] to %[[A_I]] : i32, !fir.ref<i32>
|
|
a(i) = 10
|
|
end do
|
|
!CHECK: omp.yield
|
|
!CHECK: }
|
|
!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<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-NO-FPRIV: %[[VAL_4:.*]] = omp.map.info var_ptr(%[[VAL_1]]#1 : !fir.ref<i32>, i32) map_clauses(implicit) capture(ByCopy) -> !fir.ref<i32> {name = "i"}
|
|
!CHECK-NO-FPRIV: %[[VAL_5:.*]] = omp.map.info var_ptr(%[[VAL_3]]#1 : !fir.ref<i32>, i32) map_clauses(implicit) capture(ByCopy) -> !fir.ref<i32> {name = "j"}
|
|
!CHECK-NO-FPRIV: omp.target map_entries(%[[VAL_4]] -> %[[VAL_6:.*]], %[[VAL_5]] -> %[[VAL_7:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
|
|
!CHECK-FPRIV: %[[VAL_4:.*]] = omp.map.info var_ptr(%[[VAL_1]]#0 : !fir.ref<i32>, i32) map_clauses(to) capture(ByCopy) -> !fir.ref<i32>
|
|
!CHECK-FPRIV: %[[VAL_5:.*]] = omp.map.info var_ptr(%[[VAL_3]]#0 : !fir.ref<i32>, i32) map_clauses(to) capture(ByCopy) -> !fir.ref<i32>
|
|
!CHECK-FPRIV: omp.target map_entries(%[[VAL_4]] -> %[[ARG_0:.*]], %[[VAL_5]] -> %[[ARG_1:.*]] : !fir.ref<i32>, !fir.ref<i32>) private(@{{.*}} %[[VAL_1]]#0 -> %[[ARG_2:.*]] [map_idx=0], @{{.*}} %[[VAL_3]]#0 -> %[[ARG_3:.*]] [map_idx=1] : !fir.ref<i32>, !fir.ref<i32>) {
|
|
!$omp target
|
|
!CHECK-FPRIV: %[[VAL_8:.*]]:2 = hlfir.declare %[[ARG_2]] {uniq_name = "_QFtarget_unstructuredEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
|
!CHECK-FPRIV: %[[VAL_9:.*]]:2 = hlfir.declare %[[ARG_3]] {uniq_name = "_QFtarget_unstructuredEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
|
!CHECK-NO-FPRIV: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFtarget_unstructuredEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
|
|
!CHECK-NO-FPRIV: %[[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
|
|
|
|
!===============================================================================
|
|
! Target `device` clause
|
|
!===============================================================================
|
|
|
|
!CHECK-LABEL: func.func @_QPomp_target_device() {
|
|
subroutine omp_target_device
|
|
integer :: dev32
|
|
integer(kind=8) :: dev64
|
|
integer(kind=2) :: dev16
|
|
|
|
dev32 = 1
|
|
dev64 = 2_8
|
|
dev16 = 3_2
|
|
|
|
!$omp target device(dev32)
|
|
!$omp end target
|
|
! CHECK: %[[DEV32:.*]] = fir.load %{{.*}} : !fir.ref<i32>
|
|
! CHECK: omp.target device(%[[DEV32]] : i32)
|
|
|
|
!$omp target device(dev64)
|
|
!$omp end target
|
|
! CHECK: %[[DEV64:.*]] = fir.load %{{.*}} : !fir.ref<i64>
|
|
! CHECK: omp.target device(%[[DEV64]] : i64)
|
|
|
|
!$omp target device(dev16)
|
|
!$omp end target
|
|
! CHECK: %[[DEV16:.*]] = fir.load %{{.*}} : !fir.ref<i16>
|
|
! CHECK: omp.target device(%[[DEV16]] : i16)
|
|
|
|
!$omp target device(2)
|
|
!$omp end target
|
|
! CHECK: %[[C2:.*]] = arith.constant 2 : i32
|
|
! CHECK: omp.target device(%[[C2]] : i32)
|
|
|
|
!$omp target device(5_8)
|
|
!$omp end target
|
|
! CHECK: %[[C5:.*]] = arith.constant 5 : i64
|
|
! CHECK: omp.target device(%[[C5]] : i64)
|
|
|
|
end subroutine omp_target_device
|
|
|
|
!===============================================================================
|
|
! Target data `device` clause
|
|
!===============================================================================
|
|
|
|
!CHECK-LABEL: func.func @_QPomp_target_data_device() {
|
|
subroutine omp_target_data_device
|
|
integer :: dev32
|
|
integer(kind=8) :: dev64
|
|
integer(kind=2) :: dev16
|
|
integer :: x
|
|
|
|
dev32 = 1
|
|
dev64 = 2_8
|
|
dev16 = 3_2
|
|
x = 0
|
|
|
|
!$omp target data device(dev32) map(tofrom: x)
|
|
!$omp end target data
|
|
! CHECK: %[[DEV32:.*]] = fir.load %{{.*}} : !fir.ref<i32>
|
|
! CHECK: omp.target_data device(%[[DEV32]] : i32)
|
|
|
|
!$omp target data device(dev64) map(tofrom: x)
|
|
!$omp end target data
|
|
! CHECK: %[[DEV64:.*]] = fir.load %{{.*}} : !fir.ref<i64>
|
|
! CHECK: omp.target_data device(%[[DEV64]] : i64)
|
|
|
|
!$omp target data device(dev16) map(tofrom: x)
|
|
!$omp end target data
|
|
! CHECK: %[[DEV16:.*]] = fir.load %{{.*}} : !fir.ref<i16>
|
|
! CHECK: omp.target_data device(%[[DEV16]] : i16)
|
|
|
|
!$omp target data device(2) map(tofrom: x)
|
|
!$omp end target data
|
|
! CHECK: %[[C2:.*]] = arith.constant 2 : i32
|
|
! CHECK: omp.target_data device(%[[C2]] : i32)
|
|
|
|
!$omp target data device(5_8) map(tofrom: x)
|
|
!$omp end target data
|
|
! CHECK: %[[C5:.*]] = arith.constant 5 : i64
|
|
! CHECK: omp.target_data device(%[[C5]] : i64)
|
|
|
|
end subroutine omp_target_data_device
|