blob: 67194fa5b19a3146d5e9ffd9c0ad8045be20f158 [file] [log] [blame] [edit]
! REQUIRES: openmp_runtime
!RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s
!CHECK-LABEL: func @_QPomp_task_simple() {
subroutine omp_task_simple
!CHECK: omp.task {
!$omp task
!CHECK: fir.call @_QPfoo() {{.*}}: () -> ()
call foo()
!CHECK: omp.terminator
!$omp end task
end subroutine omp_task_simple
!===============================================================================
! `if` clause
!===============================================================================
!CHECK-LABEL: func @_QPomp_task_if(%{{.+}}) {
subroutine omp_task_if(bar)
logical, intent(inout) :: bar
!CHECK: omp.task if(%{{.+}}) {
!$omp task if(bar)
!CHECK: fir.call @_QPfoo() {{.*}}: () -> ()
call foo()
!CHECK: omp.terminator
!$omp end task
end subroutine omp_task_if
!===============================================================================
! `final` clause
!===============================================================================
!CHECK-LABEL: func @_QPomp_task_final(%{{.+}}) {
subroutine omp_task_final(bar)
logical, intent(inout) :: bar
!CHECK: omp.task final(%{{.+}}) {
!$omp task final(bar)
!CHECK: fir.call @_QPfoo() {{.*}}: () -> ()
call foo()
!CHECK: omp.terminator
!$omp end task
end subroutine omp_task_final
!===============================================================================
! `priority` clause
!===============================================================================
!CHECK-LABEL: func @_QPomp_task_priority(%{{.+}}) {
subroutine omp_task_priority(bar)
integer, intent(inout) :: bar
!CHECK: omp.task priority(%{{.+}}) {
!$omp task priority(bar)
!CHECK: fir.call @_QPfoo() {{.*}}: () -> ()
call foo()
!CHECK: omp.terminator
!$omp end task
end subroutine omp_task_priority
!===============================================================================
! `allocate` clause
!===============================================================================
!CHECK-LABEL: func @_QPtask_allocate
subroutine task_allocate()
use omp_lib
integer :: x
!CHECK: omp.task allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) {
!$omp task allocate(omp_high_bw_mem_alloc: x) private(x)
!CHECK: arith.addi
x = x + 12
!CHECK: omp.terminator
!$omp end task
end subroutine task_allocate
!===============================================================================
! `depend` clause
!===============================================================================
!CHECK-LABEL: func @_QPtask_depend
subroutine task_depend()
integer :: x
!CHECK: omp.task depend(taskdependin -> %{{.+}} : !fir.ref<i32>) {
!$omp task depend(in : x)
!CHECK: arith.addi
x = x + 12
!CHECK: omp.terminator
!$omp end task
end subroutine task_depend
!CHECK-LABEL: func @_QPtask_depend_non_int
subroutine task_depend_non_int()
character(len = 15) :: x
integer, allocatable :: y
complex :: z
!CHECK: omp.task depend(taskdependin -> %{{.+}} : !fir.ref<!fir.char<1,15>>, taskdependin -> %{{.+}} : !fir.heap<i32>, taskdependin -> %{{.+}} : !fir.ref<complex<f32>>) {
!$omp task depend(in : x, y, z)
!CHECK: omp.terminator
!$omp end task
end subroutine task_depend_non_int
!CHECK-LABEL: func @_QPtask_depend_all_kinds_one_task
subroutine task_depend_all_kinds_one_task()
integer :: x
!CHECK: omp.task depend(taskdependin -> %{{.+}} : !fir.ref<i32>, taskdependout -> %{{.+}} : !fir.ref<i32>, taskdependinout -> %{{.+}} : !fir.ref<i32>) {
!$omp task depend(in : x) depend(out : x) depend(inout : x)
!CHECK: arith.addi
x = x + 12
!CHECK: omp.terminator
!$omp end task
end subroutine task_depend_all_kinds_one_task
!CHECK-LABEL: func @_QPtask_depend_multi_var
subroutine task_depend_multi_var()
integer :: x
integer :: y
!CHECK: omp.task depend(taskdependin -> %{{.*}} : !fir.ref<i32>, taskdependin -> %{{.+}} : !fir.ref<i32>) private({{.*x_firstprivate.*}}, {{.*y_firstprivate.*}}) {
!$omp task depend(in :x,y)
!CHECK: arith.addi
x = x + 12
y = y + 12
!CHECK: omp.terminator
!$omp end task
end subroutine task_depend_multi_var
!CHECK-LABEL: func @_QPtask_depend_multi_task
subroutine task_depend_multi_task()
integer :: x
!CHECK: omp.task depend(taskdependout -> %{{.+}} : !fir.ref<i32>)
!$omp task depend(out : x)
!CHECK: arith.addi
x = x + 12
!CHECK: omp.terminator
!$omp end task
!CHECK: omp.task depend(taskdependinout -> %{{.+}} : !fir.ref<i32>)
!$omp task depend(inout : x)
!CHECK: arith.addi
x = x + 12
!CHECK: omp.terminator
!$omp end task
!CHECK: omp.task depend(taskdependin -> %{{.+}} : !fir.ref<i32>)
!$omp task depend(in : x)
!CHECK: arith.addi
x = x + 12
!CHECK: omp.terminator
!$omp end task
!CHECK: omp.task depend(taskdependmutexinoutset -> %{{.+}} : !fir.ref<i32>)
!$omp task depend(mutexinoutset : x)
!CHECK: arith.subi
x = x - 12
!CHECK: omp.terminator
!$omp end task
!CHECK: omp.task depend(taskdependinoutset -> %{{.+}} : !fir.ref<i32>)
!$omp task depend(inoutset : x)
!CHECK: arith.subi
x = x - 12
!CHECK: omp.terminator
!$omp end task
end subroutine task_depend_multi_task
subroutine task_depend_box(array)
integer :: array(:)
!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %{{.*}} : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
!CHECK: omp.task depend(taskdependin -> %[[BOX_ADDR]] : !fir.ref<!fir.array<?xi32>>)
!$omp task depend(in: array)
!$omp end task
end subroutine
subroutine task_depend_mutable_box(alloc)
integer, allocatable :: alloc
!CHECK: %[[LOAD:.*]] = fir.load %{{.*}} : !fir.ref<!fir.box<!fir.heap<i32>>>
!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
!CHECK: omp.task depend(taskdependin -> %[[BOX_ADDR]] : !fir.heap<i32>)
!$omp task depend(in: alloc)
!$omp end task
end subroutine
!===============================================================================
! `private` clause
!===============================================================================
!CHECK-LABEL: func @_QPtask_private
subroutine task_private
type mytype
integer :: x
end type mytype
!CHECK: %[[INT_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "int_var", uniq_name = "_QFtask_privateEint_var"}
!CHECK: %[[INT_VAR:.+]]:2 = hlfir.declare %[[INT_ALLOCA]] {uniq_name = "_QFtask_privateEint_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[MYTYPE_ALLOCA:.*]] = fir.alloca !fir.type<_QFtask_privateTmytype{x:i32}> {bindc_name = "mytype_var", uniq_name = "_QFtask_privateEmytype_var"}
!CHECK: %[[MYTYPE_VAR:.+]]:2 = hlfir.declare %[[MYTYPE_ALLOCA]] {uniq_name = "_QFtask_privateEmytype_var"} : (!fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>) -> (!fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>, !fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>)
integer :: int_var
type(mytype) :: mytype_var
!CHECK: fir.call @_QPbar(%[[INT_VAR]]#0, %[[MYTYPE_VAR]]#0) {{.*}}: (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>) -> ()
call bar(int_var, mytype_var)
!CHECK: omp.task private(@{{.*int_var_private.*}} %[[INT_VAR]]#0 -> %[[INT_VAR_ARG:.*]], @{{.*mytype_var_private.*}} %[[MYTYPE_VAR]]#0 -> %[[MYTYPE_VAR_ARG:.*]] : !fir.ref<i32>, !fir.ref<!fir.type<{{.*}}>) {
!$omp task private(int_var, mytype_var)
!CHECK: %[[INT_VAR_PRIVATE:.+]]:2 = hlfir.declare %[[INT_VAR_ARG]] {uniq_name = "_QFtask_privateEint_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[MYTYPE_VAR_PRIVATE:.+]]:2 = hlfir.declare %[[MYTYPE_VAR_ARG]] {uniq_name = "_QFtask_privateEmytype_var"} : (!fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>) -> (!fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>, !fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>)
!CHECK: fir.call @_QPbar(%[[INT_VAR_PRIVATE]]#0, %[[MYTYPE_VAR_PRIVATE]]#0) fastmath<contract> : (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>) -> ()
call bar(int_var, mytype_var)
!CHECK: omp.terminator
!$omp end task
end subroutine task_private
!===============================================================================
! `firstprivate` clause
!===============================================================================
!CHECK-LABEL: func @_QPtask_firstprivate
subroutine task_firstprivate
type mytype
integer :: x
end type mytype
!CHECK: %[[INT_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "int_var", uniq_name = "_QFtask_firstprivateEint_var"}
!CHECK: %[[INT_VAR:.+]]:2 = hlfir.declare %[[INT_ALLOCA]] {uniq_name = "_QFtask_firstprivateEint_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[MYTYPE_ALLOCA:.+]] = fir.alloca !fir.type<_QFtask_firstprivateTmytype{x:i32}> {bindc_name = "mytype_var", uniq_name = "_QFtask_firstprivateEmytype_var"}
!CHECK: %[[MYTYPE_VAR:.+]]:2 = hlfir.declare %[[MYTYPE_ALLOCA]] {uniq_name = "_QFtask_firstprivateEmytype_var"} : (!fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>) -> (!fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>, !fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>)
integer :: int_var
type(mytype) :: mytype_var
!CHECK: fir.call @_QPbaz(%[[INT_VAR]]#0, %[[MYTYPE_VAR]]#0) fastmath<contract> : (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>) -> ()
call baz(int_var, mytype_var)
!CHECK: omp.task private(@{{.*int_var_firstprivate.*}} %[[INT_VAR]]#0 -> %[[INT_VAR_ARG:.*]], @{{.*mytype_var_firstprivate.*}} %[[MYTYPE_VAR]]#0 -> %[[MYTYPE_VAR_ARG:.*]] : !fir.ref<i32>, !fir.ref<{{.*}}) {
!$omp task firstprivate(int_var, mytype_var)
!CHECK: %[[INT_VAR_FIRSTPRIVATE:.+]]:2 = hlfir.declare %[[INT_VAR_ARG]] {uniq_name = "_QFtask_firstprivateEint_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[MYTYPE_VAR_FIRSTPRIVATE:.+]]:2 = hlfir.declare %[[MYTYPE_VAR_ARG]] {uniq_name = "_QFtask_firstprivateEmytype_var"} : (!fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>) -> (!fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>, !fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>)
call baz(int_var, mytype_var)
!CHECK: omp.terminator
!$omp end task
end subroutine task_firstprivate
!===============================================================================
! Multiple clauses
!===============================================================================
!CHECK-LABEL: func @_QPtask_multiple_clauses
subroutine task_multiple_clauses()
use omp_lib
!CHECK: %[[X_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFtask_multiple_clausesEx"}
!CHECK: %[[X:.+]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = "_QFtask_multiple_clausesEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[Y_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFtask_multiple_clausesEy"}
!CHECK: %[[Y:.+]]:2 = hlfir.declare %[[Y_ALLOCA]] {uniq_name = "_QFtask_multiple_clausesEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[Z_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFtask_multiple_clausesEz"}
!CHECK: %[[Z:.+]]:2 = hlfir.declare %[[Z_ALLOCA]] {uniq_name = "_QFtask_multiple_clausesEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
integer :: x, y, z
logical :: buzz
!CHECK: omp.task allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) final(%{{.+}}) if(%{{.+}}) priority(%{{.+}}) private({{.*}}) {
!$omp task if(buzz) final(buzz) priority(z) allocate(omp_high_bw_mem_alloc: x) private(x) firstprivate(y)
!CHECK: %[[X_PRIV:.+]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtask_multiple_clausesEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[Y_PRIV:.+]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtask_multiple_clausesEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: arith.addi
x = x + 12
!CHECK: arith.subi
y = y - 12
!CHECK: omp.terminator
!$omp end task
end subroutine task_multiple_clauses
!===============================================================================
! `mergeable` clause
!===============================================================================
subroutine task_mergeable()
!CHECK: omp.task mergeable {
!CHECK: omp.terminator
!CHECK: }
!$omp task mergeable
!$omp end task
end subroutine
!===============================================================================
! `untied` clause
!===============================================================================
!CHECK-LABEL: func.func @_QPomp_task_untied() {
subroutine omp_task_untied()
!CHECK: omp.task untied {
!$omp task untied
call foo()
!CHECK: omp.terminator
!$omp end task
end subroutine omp_task_untied