xref: /llvm-project/flang/test/Lower/OpenMP/task.f90 (revision c2aa11d148679b7d49cdff3819d5c8bdbd807777)
1! REQUIRES: openmp_runtime
2
3!RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s
4
5!CHECK-LABEL: func @_QPomp_task_simple() {
6subroutine omp_task_simple
7  !CHECK: omp.task {
8  !$omp task
9  !CHECK: fir.call @_QPfoo() {{.*}}: () -> ()
10  call foo()
11  !CHECK: omp.terminator
12  !$omp end task
13end subroutine omp_task_simple
14
15!===============================================================================
16! `if` clause
17!===============================================================================
18
19!CHECK-LABEL: func @_QPomp_task_if(%{{.+}}) {
20subroutine omp_task_if(bar)
21  logical, intent(inout) :: bar
22  !CHECK: omp.task if(%{{.+}}) {
23  !$omp task if(bar)
24  !CHECK: fir.call @_QPfoo() {{.*}}: () -> ()
25  call foo()
26  !CHECK: omp.terminator
27  !$omp end task
28end subroutine omp_task_if
29
30!===============================================================================
31! `final` clause
32!===============================================================================
33
34!CHECK-LABEL: func @_QPomp_task_final(%{{.+}}) {
35subroutine omp_task_final(bar)
36  logical, intent(inout) :: bar
37  !CHECK: omp.task final(%{{.+}}) {
38  !$omp task final(bar)
39  !CHECK: fir.call @_QPfoo() {{.*}}: () -> ()
40  call foo()
41  !CHECK: omp.terminator
42  !$omp end task
43end subroutine omp_task_final
44
45!===============================================================================
46! `priority` clause
47!===============================================================================
48
49!CHECK-LABEL: func @_QPomp_task_priority(%{{.+}}) {
50subroutine omp_task_priority(bar)
51  integer, intent(inout) :: bar
52  !CHECK: omp.task priority(%{{.+}}) {
53  !$omp task priority(bar)
54  !CHECK: fir.call @_QPfoo() {{.*}}: () -> ()
55  call foo()
56  !CHECK: omp.terminator
57  !$omp end task
58end subroutine omp_task_priority
59
60!===============================================================================
61! `allocate` clause
62!===============================================================================
63
64!CHECK-LABEL: func @_QPtask_allocate
65subroutine task_allocate()
66  use omp_lib
67  integer :: x
68  !CHECK: omp.task allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) {
69  !$omp task allocate(omp_high_bw_mem_alloc: x) private(x)
70  !CHECK: arith.addi
71  x = x + 12
72  !CHECK: omp.terminator
73  !$omp end task
74end subroutine task_allocate
75
76!===============================================================================
77! `depend` clause
78!===============================================================================
79
80!CHECK-LABEL: func @_QPtask_depend
81subroutine task_depend()
82  integer :: x
83  !CHECK: omp.task depend(taskdependin -> %{{.+}} : !fir.ref<i32>) {
84  !$omp task depend(in : x)
85  !CHECK: arith.addi
86  x = x + 12
87  !CHECK: omp.terminator
88  !$omp end task
89end subroutine task_depend
90
91!CHECK-LABEL: func @_QPtask_depend_non_int
92subroutine task_depend_non_int()
93  character(len = 15) :: x
94  integer, allocatable :: y
95  complex :: z
96  !CHECK: omp.task depend(taskdependin -> %{{.+}} : !fir.ref<!fir.char<1,15>>, taskdependin -> %{{.+}} : !fir.ref<!fir.box<!fir.heap<i32>>>, taskdependin ->  %{{.+}} : !fir.ref<complex<f32>>) {
97  !$omp task depend(in : x, y, z)
98  !CHECK: omp.terminator
99  !$omp end task
100end subroutine task_depend_non_int
101
102!CHECK-LABEL: func @_QPtask_depend_all_kinds_one_task
103subroutine task_depend_all_kinds_one_task()
104  integer :: x
105  !CHECK: omp.task depend(taskdependin -> %{{.+}} : !fir.ref<i32>, taskdependout -> %{{.+}} : !fir.ref<i32>, taskdependinout -> %{{.+}} : !fir.ref<i32>) {
106  !$omp task depend(in : x) depend(out : x) depend(inout : x)
107  !CHECK: arith.addi
108  x = x + 12
109  !CHECK: omp.terminator
110  !$omp end task
111end subroutine task_depend_all_kinds_one_task
112
113!CHECK-LABEL: func @_QPtask_depend_multi_var
114subroutine task_depend_multi_var()
115  integer :: x
116  integer :: y
117  !CHECK: omp.task depend(taskdependin -> %{{.*}} : !fir.ref<i32>, taskdependin -> %{{.+}} : !fir.ref<i32>) private({{.*x_firstprivate.*}}, {{.*y_firstprivate.*}}) {
118  !$omp task depend(in :x,y)
119  !CHECK: arith.addi
120  x = x + 12
121  y = y + 12
122  !CHECK: omp.terminator
123  !$omp end task
124end subroutine task_depend_multi_var
125
126!CHECK-LABEL: func @_QPtask_depend_multi_task
127subroutine task_depend_multi_task()
128  integer :: x
129  !CHECK: omp.task depend(taskdependout -> %{{.+}} : !fir.ref<i32>)
130  !$omp task depend(out : x)
131  !CHECK: arith.addi
132  x = x + 12
133  !CHECK: omp.terminator
134  !$omp end task
135  !CHECK: omp.task depend(taskdependinout -> %{{.+}} : !fir.ref<i32>)
136  !$omp task depend(inout : x)
137  !CHECK: arith.addi
138  x = x + 12
139  !CHECK: omp.terminator
140  !$omp end task
141  !CHECK: omp.task depend(taskdependin -> %{{.+}} : !fir.ref<i32>)
142  !$omp task depend(in : x)
143  !CHECK: arith.addi
144  x = x + 12
145  !CHECK: omp.terminator
146  !$omp end task
147  !CHECK: omp.task depend(taskdependmutexinoutset -> %{{.+}} : !fir.ref<i32>)
148  !$omp task depend(mutexinoutset : x)
149  !CHECK: arith.subi
150  x = x - 12
151  !CHECK: omp.terminator
152  !$omp end task
153    !CHECK: omp.task depend(taskdependinoutset -> %{{.+}} : !fir.ref<i32>)
154  !$omp task depend(inoutset : x)
155  !CHECK: arith.subi
156  x = x - 12
157  !CHECK: omp.terminator
158  !$omp end task
159end subroutine task_depend_multi_task
160
161!===============================================================================
162! `private` clause
163!===============================================================================
164!CHECK-LABEL: func @_QPtask_private
165subroutine task_private
166  type mytype
167  integer :: x
168  end type mytype
169
170!CHECK: %[[INT_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "int_var", uniq_name = "_QFtask_privateEint_var"}
171!CHECK: %[[INT_VAR:.+]]:2 = hlfir.declare %[[INT_ALLOCA]] {uniq_name = "_QFtask_privateEint_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
172!CHECK: %[[MYTYPE_ALLOCA:.*]] = fir.alloca !fir.type<_QFtask_privateTmytype{x:i32}> {bindc_name = "mytype_var", uniq_name = "_QFtask_privateEmytype_var"}
173!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}>>)
174  integer :: int_var
175  type(mytype) :: mytype_var
176
177  !CHECK: fir.call @_QPbar(%[[INT_VAR]]#1, %[[MYTYPE_VAR]]#1) {{.*}}: (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>) -> ()
178  call bar(int_var, mytype_var)
179
180  !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<{{.*}}>) {
181  !$omp task private(int_var, mytype_var)
182!CHECK: %[[INT_VAR_PRIVATE:.+]]:2 = hlfir.declare %[[INT_VAR_ARG]] {uniq_name = "_QFtask_privateEint_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
183!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}>>)
184!CHECK: fir.call @_QPbar(%[[INT_VAR_PRIVATE]]#1, %[[MYTYPE_VAR_PRIVATE]]#1) fastmath<contract> : (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>) -> ()
185  call bar(int_var, mytype_var)
186  !CHECK: omp.terminator
187  !$omp end task
188end subroutine task_private
189
190!===============================================================================
191! `firstprivate` clause
192!===============================================================================
193!CHECK-LABEL: func @_QPtask_firstprivate
194subroutine task_firstprivate
195  type mytype
196  integer :: x
197  end type mytype
198
199  !CHECK: %[[INT_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "int_var", uniq_name = "_QFtask_firstprivateEint_var"}
200  !CHECK: %[[INT_VAR:.+]]:2 = hlfir.declare %[[INT_ALLOCA]] {uniq_name = "_QFtask_firstprivateEint_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
201  !CHECK: %[[MYTYPE_ALLOCA:.+]] = fir.alloca !fir.type<_QFtask_firstprivateTmytype{x:i32}> {bindc_name = "mytype_var", uniq_name = "_QFtask_firstprivateEmytype_var"}
202  !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}>>)
203  integer :: int_var
204  type(mytype) :: mytype_var
205
206!CHECK: fir.call @_QPbaz(%[[INT_VAR]]#1, %[[MYTYPE_VAR]]#1) fastmath<contract> : (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>) -> ()
207  call baz(int_var, mytype_var)
208
209  !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<{{.*}}) {
210  !$omp task firstprivate(int_var, mytype_var)
211!CHECK: %[[INT_VAR_FIRSTPRIVATE:.+]]:2 = hlfir.declare %[[INT_VAR_ARG]] {uniq_name = "_QFtask_firstprivateEint_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
212!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}>>)
213  call baz(int_var, mytype_var)
214  !CHECK: omp.terminator
215  !$omp end task
216end subroutine task_firstprivate
217
218!===============================================================================
219! Multiple clauses
220!===============================================================================
221
222!CHECK-LABEL: func @_QPtask_multiple_clauses
223subroutine task_multiple_clauses()
224  use omp_lib
225
226!CHECK: %[[X_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFtask_multiple_clausesEx"}
227!CHECK: %[[X:.+]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = "_QFtask_multiple_clausesEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
228!CHECK: %[[Y_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFtask_multiple_clausesEy"}
229!CHECK: %[[Y:.+]]:2 = hlfir.declare %[[Y_ALLOCA]] {uniq_name = "_QFtask_multiple_clausesEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
230!CHECK: %[[Z_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFtask_multiple_clausesEz"}
231!CHECK: %[[Z:.+]]:2 = hlfir.declare %[[Z_ALLOCA]] {uniq_name = "_QFtask_multiple_clausesEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
232  integer :: x, y, z
233  logical :: buzz
234
235  !CHECK: omp.task allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) final(%{{.+}}) if(%{{.+}}) priority(%{{.+}}) private({{.*}}) {
236  !$omp task if(buzz) final(buzz) priority(z) allocate(omp_high_bw_mem_alloc: x) private(x) firstprivate(y)
237
238!CHECK: %[[X_PRIV:.+]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtask_multiple_clausesEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
239!CHECK: %[[Y_PRIV:.+]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtask_multiple_clausesEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
240
241  !CHECK: arith.addi
242  x = x + 12
243  !CHECK: arith.subi
244  y = y - 12
245
246  !CHECK: omp.terminator
247  !$omp end task
248end subroutine task_multiple_clauses
249
250!===============================================================================
251! `mergeable` clause
252!===============================================================================
253
254subroutine task_mergeable()
255!CHECK: omp.task mergeable {
256!CHECK: omp.terminator
257!CHECK: }
258 !$omp task mergeable
259 !$omp end task
260end subroutine
261
262!===============================================================================
263! `untied` clause
264!===============================================================================
265
266!CHECK-LABEL: func.func @_QPomp_task_untied() {
267subroutine omp_task_untied()
268  !CHECK: omp.task untied {
269  !$omp task untied
270    call foo()
271  !CHECK: omp.terminator
272  !$omp end task
273end subroutine omp_task_untied
274