Break circular dependency between FIR dialect and utilities
[llvm-project.git] / flang / test / Fir / convert-to-llvm-openmp-and-fir.fir
blobee94ac19accd772e9cd97ea216df22b0d64feb64
1 // RUN: fir-opt --split-input-file --cfg-conversion --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s
3 func.func @_QPsb1(%arg0: !fir.ref<i32> {fir.bindc_name = "n"}, %arg1: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr"}) {
4   %c1_i64 = arith.constant 1 : i64
5   %c1_i32 = arith.constant 1 : i32
6   %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsbEi"}
7   omp.parallel  {
8     %1 = fir.alloca i32 {adapt.valuebyref, pinned}
9     %2 = fir.load %arg0 : !fir.ref<i32>
10     omp.wsloop nowait
11     for (%arg2) : i32 = (%c1_i32) to (%2) inclusive step (%c1_i32)  {
12       fir.store %arg2 to %1 : !fir.ref<i32>
13       %3 = fir.load %1 : !fir.ref<i32>
14       %4 = fir.convert %3 : (i32) -> i64
15       %5 = arith.subi %4, %c1_i64 : i64
16       %6 = fir.coordinate_of %arg1, %5 : (!fir.ref<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
17       fir.store %3 to %6 : !fir.ref<i32>
18       omp.yield
19     }
20     omp.terminator
21   }
22   return
25 // CHECK-LABEL:  _QPsb1
26 // CHECK-SAME: %[[N_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "n"}, %[[ARR_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "arr"}) {
27 // CHECK:    %[[ONE_1:.*]] = llvm.mlir.constant(1 : i64) : i64
28 // CHECK:    %[[ONE_2:.*]] = llvm.mlir.constant(1 : i32) : i32
29 // CHECK: omp.parallel   {
30 // CHECK:      %[[ONE_3:.*]] = llvm.mlir.constant(1 : i64) : i64
31 // CHECK:      %[[I_VAR:.*]] = llvm.alloca %[[ONE_3]] x i32 {adapt.valuebyref, in_type = i32, operand_segment_sizes = array<i32: 0, 0>, pinned} : (i64) -> !llvm.ptr<i32>
32 // CHECK:      %[[N:.*]] = llvm.load %[[N_REF]] : !llvm.ptr<i32>
33 // CHECK: omp.wsloop nowait
34 // CHECK-SAME: for (%[[I:.*]]) : i32 = (%[[ONE_2]]) to (%[[N]]) inclusive step (%[[ONE_2]]) {
35 // CHECK:   llvm.store %[[I]], %[[I_VAR]] : !llvm.ptr<i32>
36 // CHECK:   %[[I1:.*]] = llvm.load %[[I_VAR]] : !llvm.ptr<i32>
37 // CHECK:   %[[I1_EXT:.*]] = llvm.sext %[[I1]] : i32 to i64
38 // CHECK:   %[[I_CSTYLE:.*]] = llvm.sub %[[I1_EXT]], %[[ONE_1]]  : i64
39 // CHECK:   %[[ARR_I_REF:.*]] = llvm.getelementptr %[[ARR_REF]][%[[I_CSTYLE]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
40 // CHECK:   llvm.store %[[I1]], %[[ARR_I_REF]] : !llvm.ptr<i32>
41 // CHECK: omp.yield
42 // CHECK: }
43 // CHECK: omp.terminator
44 // CHECK: }
45 // CHECK: llvm.return
46 // CHECK: }
48 // -----
50 func.func @_QPsb2(%arg0: !fir.ref<i32> {fir.bindc_name = "x"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}) {
51   omp.parallel  {
52     omp.master  {
53       %0 = fir.load %arg1 : !fir.ref<i32>
54       fir.store %0 to %arg0 : !fir.ref<i32>
55       omp.terminator
56     }
57     omp.terminator
58   }
59   return
62 // CHECK-LABEL: _QPsb2
63 // CHECK-SAME: %[[X_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "x"}, %[[N_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "n"}) {
64 // CHECK: omp.parallel   {
65 // CHECK:   omp.master {
66 // CHECK:     %[[N:.*]] = llvm.load %[[N_REF]] : !llvm.ptr<i32>
67 // CHECK:     llvm.store %[[N]], %[[X_REF]] : !llvm.ptr<i32>
68 // CHECK:     omp.terminator
69 // CHECK:   }
70 // CHECK:   omp.terminator
71 // CHECK: }
72 // CHECK: llvm.return
73 // CHECK: }
75 // -----
77 func.func @_QPsb(%arr: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr"}) {
78   %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsbEi"}
79   omp.parallel   {
80     %c1 = arith.constant 1 : i32
81     %c50 = arith.constant 50 : i32
82     omp.wsloop   for  (%indx) : i32 = (%c1) to (%c50) inclusive step (%c1) {
83       %1 = fir.convert %indx : (i32) -> i64
84       %c1_i64 = arith.constant 1 : i64
85       %2 = arith.subi %1, %c1_i64 : i64
86       %3 = fir.coordinate_of %arr, %2 : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
87       fir.store %indx to %3 : !fir.ref<i32>
88       omp.yield
89     }
90     omp.terminator
91   }
92   return
95 // Check only for the structure of the OpenMP portion and the feasibility of the conversion
96 // CHECK-LABEL: @_QPsb
97 // CHECK-SAME: %{{.*}}: !llvm.ptr<struct<({{.*}})>> {fir.bindc_name = "arr"}
98 // CHECK:    omp.parallel   {
99 // CHECK:      %[[C1:.*]] = llvm.mlir.constant(1 : i32) : i32
100 // CHECK:      %[[C50:.*]] = llvm.mlir.constant(50 : i32) : i32
101 // CHECK:      omp.wsloop   for  (%[[INDX:.*]]) : i32 = (%[[C1]]) to (%[[C50]]) inclusive step (%[[C1]]) {
102 // CHECK:        llvm.store %[[INDX]], %{{.*}} : !llvm.ptr<i32>
103 // CHECK:        omp.yield
104 // CHECK:      omp.terminator
105 // CHECK:    llvm.return
107 // -----
109 func.func private @foo()
110 func.func private @bar()
112 func.func @sections_no_data() {
113   omp.sections {
114     omp.section {
115       fir.call @foo() : () -> ()
116       omp.terminator
117     }
118     omp.section {
119       fir.call @bar() : () -> ()
120       omp.terminator
121     }
122     omp.terminator
123   }
124   return
127 // CHECK-LABEL: llvm.func @sections_no_data
128 // CHECK: omp.sections {
129 // CHECK:   omp.section {
130 // CHECK:     llvm.call @foo() : () -> ()
131 // CHECK:     omp.terminator
132 // CHECK:   }
133 // CHECK:   omp.section {
134 // CHECK:     llvm.call @bar() : () -> ()
135 // CHECK:     omp.terminator
136 // CHECK:   }
137 // CHECK:   omp.terminator
138 // CHECK: }
140 // -----
142 func.func private @foo(!fir.ref<i32>)
143 func.func private @bar(!fir.ref<i32>, !fir.ref<i32>)
145 func.func @sections_data_without_clauses(%arg0: !fir.ref<i32> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "b"}) {
146   omp.sections {
147     omp.section {
148       fir.call @foo(%arg0) : (!fir.ref<i32>) -> ()
149       omp.terminator
150     }
151     omp.section {
152       fir.call @bar(%arg0, %arg1) : (!fir.ref<i32>, !fir.ref<i32>) -> ()
153       omp.terminator
154     }
155     omp.terminator
156   }
157   return
160 // CHECK-LABEL: llvm.func @sections_data_without_clauses
161 // CHECK-SAME:            (%[[ARG0:.+]]: !llvm.ptr<i32> {fir.bindc_name = "a"}, %[[ARG1:.+]]: !llvm.ptr<i32> {fir.bindc_name = "b"})
162 // CHECK: omp.sections {
163 // CHECK:   omp.section {
164 // CHECK:     llvm.call @foo(%arg0) : (!llvm.ptr<i32>) -> ()
165 // CHECK:     omp.terminator
166 // CHECK:   }
167 // CHECK:   omp.section {
168 // CHECK:     llvm.call @bar(%[[ARG0]], %[[ARG1]]) : (!llvm.ptr<i32>, !llvm.ptr<i32>) -> ()
169 // CHECK:     omp.terminator
170 // CHECK:   }
171 // CHECK:   omp.terminator
172 // CHECK: }
174 // -----
176 func.func @_QPsimd1(%arg0: !fir.ref<i32> {fir.bindc_name = "n"}, %arg1: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr"}) {
177   %c1_i64 = arith.constant 1 : i64
178   %c1_i32 = arith.constant 1 : i32
179   %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsbEi"}
180   omp.parallel  {
181     %1 = fir.alloca i32 {adapt.valuebyref, pinned}
182     %2 = fir.load %arg0 : !fir.ref<i32>
183     omp.simdloop for (%arg2) : i32 = (%c1_i32) to (%2) step (%c1_i32)  {
184       fir.store %arg2 to %1 : !fir.ref<i32>
185       %3 = fir.load %1 : !fir.ref<i32>
186       %4 = fir.convert %3 : (i32) -> i64
187       %5 = arith.subi %4, %c1_i64 : i64
188       %6 = fir.coordinate_of %arg1, %5 : (!fir.ref<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
189       fir.store %3 to %6 : !fir.ref<i32>
190       omp.yield
191     }
192     omp.terminator
193   }
194   return
197 // CHECK-LABEL:  _QPsimd1
198 // CHECK-SAME: %[[N_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "n"}, %[[ARR_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "arr"}) {
199 // CHECK:    %[[ONE_1:.*]] = llvm.mlir.constant(1 : i64) : i64
200 // CHECK:    %[[ONE_2:.*]] = llvm.mlir.constant(1 : i32) : i32
201 // CHECK: omp.parallel   {
202 // CHECK:      %[[ONE_3:.*]] = llvm.mlir.constant(1 : i64) : i64
203 // CHECK:      %[[I_VAR:.*]] = llvm.alloca %[[ONE_3]] x i32 {adapt.valuebyref, in_type = i32, operand_segment_sizes = array<i32: 0, 0>, pinned} : (i64) -> !llvm.ptr<i32>
204 // CHECK:      %[[N:.*]] = llvm.load %[[N_REF]] : !llvm.ptr<i32>
205 // CHECK: omp.simdloop
206 // CHECK-SAME: (%[[I:.*]]) : i32 = (%[[ONE_2]]) to (%[[N]]) step (%[[ONE_2]]) {
207 // CHECK:   llvm.store %[[I]], %[[I_VAR]] : !llvm.ptr<i32>
208 // CHECK:   %[[I1:.*]] = llvm.load %[[I_VAR]] : !llvm.ptr<i32>
209 // CHECK:   %[[I1_EXT:.*]] = llvm.sext %[[I1]] : i32 to i64
210 // CHECK:   %[[I_CSTYLE:.*]] = llvm.sub %[[I1_EXT]], %[[ONE_1]]  : i64
211 // CHECK:   %[[ARR_I_REF:.*]] = llvm.getelementptr %[[ARR_REF]][%[[I_CSTYLE]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
212 // CHECK:   llvm.store %[[I1]], %[[ARR_I_REF]] : !llvm.ptr<i32>
213 // CHECK: omp.yield
214 // CHECK: }
215 // CHECK: omp.terminator
216 // CHECK: }
217 // CHECK: llvm.return
218 // CHECK: }
220 // -----
222 func.func @_QPomp_target_data() {
223   %0 = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_dataEa"}
224   %1 = fir.alloca !fir.array<1024xi32> {bindc_name = "b", uniq_name = "_QFomp_target_dataEb"}
225   %2 = fir.alloca !fir.array<1024xi32> {bindc_name = "c", uniq_name = "_QFomp_target_dataEc"}
226   %3 = fir.alloca !fir.array<1024xi32> {bindc_name = "d", uniq_name = "_QFomp_target_dataEd"}
227   omp.target_enter_data   map((to -> %0 : !fir.ref<!fir.array<1024xi32>>), (to -> %1 : !fir.ref<!fir.array<1024xi32>>), (always, alloc -> %2 : !fir.ref<!fir.array<1024xi32>>))
228   omp.target_exit_data   map((from -> %0 : !fir.ref<!fir.array<1024xi32>>), (from -> %1 : !fir.ref<!fir.array<1024xi32>>), (release -> %2 : !fir.ref<!fir.array<1024xi32>>), (always, delete -> %3 : !fir.ref<!fir.array<1024xi32>>))
229   return
232 // CHECK-LABEL:   llvm.func @_QPomp_target_data() {
233 // CHECK:           %[[VAL_0:.*]] = llvm.mlir.constant(1 : i64) : i64
234 // CHECK:           %[[VAL_1:.*]] = llvm.alloca %[[VAL_0]] x !llvm.array<1024 x i32> {bindc_name = "a", in_type = !fir.array<1024xi32>, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFomp_target_dataEa"} : (i64) -> !llvm.ptr<array<1024 x i32>>
235 // CHECK:           %[[VAL_2:.*]] = llvm.mlir.constant(1 : i64) : i64
236 // CHECK:           %[[VAL_3:.*]] = llvm.alloca %[[VAL_2]] x !llvm.array<1024 x i32> {bindc_name = "b", in_type = !fir.array<1024xi32>, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFomp_target_dataEb"} : (i64) -> !llvm.ptr<array<1024 x i32>>
237 // CHECK:           %[[VAL_4:.*]] = llvm.mlir.constant(1 : i64) : i64
238 // CHECK:           %[[VAL_5:.*]] = llvm.alloca %[[VAL_4]] x !llvm.array<1024 x i32> {bindc_name = "c", in_type = !fir.array<1024xi32>, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFomp_target_dataEc"} : (i64) -> !llvm.ptr<array<1024 x i32>>
239 // CHECK:           %[[VAL_6:.*]] = llvm.mlir.constant(1 : i64) : i64
240 // CHECK:           %[[VAL_7:.*]] = llvm.alloca %[[VAL_6]] x !llvm.array<1024 x i32> {bindc_name = "d", in_type = !fir.array<1024xi32>, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFomp_target_dataEd"} : (i64) -> !llvm.ptr<array<1024 x i32>>
241 // CHECK:           omp.target_enter_data   map((to -> %[[VAL_1]] : !llvm.ptr<array<1024 x i32>>), (to -> %[[VAL_3]] : !llvm.ptr<array<1024 x i32>>), (always, alloc -> %[[VAL_5]] : !llvm.ptr<array<1024 x i32>>))
242 // CHECK:           omp.target_exit_data   map((from -> %[[VAL_1]] : !llvm.ptr<array<1024 x i32>>), (from -> %[[VAL_3]] : !llvm.ptr<array<1024 x i32>>), (release -> %[[VAL_5]] : !llvm.ptr<array<1024 x i32>>), (always, delete -> %[[VAL_7]] : !llvm.ptr<array<1024 x i32>>))
243 // CHECK:           llvm.return
244 // CHECK:         }
246 // -----
248 func.func @_QPopenmp_target_data_region() {
249   %0 = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFopenmp_target_data_regionEa"}
250   %1 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFopenmp_target_data_regionEi"}
251   omp.target_data   map((tofrom -> %0 : !fir.ref<!fir.array<1024xi32>>)) {
252     %c1_i32 = arith.constant 1 : i32
253     %2 = fir.convert %c1_i32 : (i32) -> index
254     %c1024_i32 = arith.constant 1024 : i32
255     %3 = fir.convert %c1024_i32 : (i32) -> index
256     %c1 = arith.constant 1 : index
257     %4 = fir.convert %2 : (index) -> i32
258     %5:2 = fir.do_loop %arg0 = %2 to %3 step %c1 iter_args(%arg1 = %4) -> (index, i32) {
259       fir.store %arg1 to %1 : !fir.ref<i32>
260       %6 = fir.load %1 : !fir.ref<i32>
261       %7 = fir.load %1 : !fir.ref<i32>
262       %8 = fir.convert %7 : (i32) -> i64
263       %c1_i64 = arith.constant 1 : i64
264       %9 = arith.subi %8, %c1_i64 : i64
265       %10 = fir.coordinate_of %0, %9 : (!fir.ref<!fir.array<1024xi32>>, i64) -> !fir.ref<i32>
266       fir.store %6 to %10 : !fir.ref<i32>
267       %11 = arith.addi %arg0, %c1 : index
268       %12 = fir.convert %c1 : (index) -> i32
269       %13 = fir.load %1 : !fir.ref<i32>
270       %14 = arith.addi %13, %12 : i32
271       fir.result %11, %14 : index, i32
272     }
273     fir.store %5#1 to %1 : !fir.ref<i32>
274     omp.terminator
275   }
276   return
279 // CHECK-LABEL:   llvm.func @_QPopenmp_target_data_region() {
280 // CHECK:           %[[VAL_0:.*]] = llvm.mlir.constant(1 : i64) : i64
281 // CHECK:           %[[VAL_1:.*]] = llvm.alloca %[[VAL_0]] x !llvm.array<1024 x i32> {bindc_name = "a", in_type = !fir.array<1024xi32>, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_data_regionEa"} : (i64) -> !llvm.ptr<array<1024 x i32>>
282 // CHECK:           %[[VAL_2:.*]] = llvm.mlir.constant(1 : i64) : i64
283 // CHECK:           %[[VAL_3:.*]] = llvm.alloca %[[VAL_2]] x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_data_regionEi"} : (i64) -> !llvm.ptr<i32>
284 // CHECK:           omp.target_data   map((tofrom -> %[[VAL_1]] : !llvm.ptr<array<1024 x i32>>)) {
285 // CHECK:             %[[VAL_4:.*]] = llvm.mlir.constant(1 : i32) : i32
286 // CHECK:             %[[VAL_5:.*]] = llvm.sext %[[VAL_4]] : i32 to i64
287 // CHECK:             %[[VAL_6:.*]] = llvm.mlir.constant(1024 : i32) : i32
288 // CHECK:             %[[VAL_7:.*]] = llvm.sext %[[VAL_6]] : i32 to i64
289 // CHECK:             %[[VAL_8:.*]] = llvm.mlir.constant(1 : index) : i64
290 // CHECK:             %[[VAL_9:.*]] = llvm.trunc %[[VAL_5]] : i64 to i32
291 // CHECK:             %[[VAL_10:.*]] = llvm.sub %[[VAL_7]], %[[VAL_5]]  : i64
292 // CHECK:             %[[VAL_11:.*]] = llvm.add %[[VAL_10]], %[[VAL_8]]  : i64
293 // CHECK:             llvm.br ^bb1(%[[VAL_5]], %[[VAL_9]], %[[VAL_11]] : i64, i32, i64)
294 // CHECK:           ^bb1(%[[VAL_12:.*]]: i64, %[[VAL_13:.*]]: i32, %[[VAL_14:.*]]: i64):
295 // CHECK:             %[[VAL_15:.*]] = llvm.mlir.constant(0 : index) : i64
296 // CHECK:             %[[VAL_16:.*]] = llvm.icmp "sgt" %[[VAL_14]], %[[VAL_15]] : i64
297 // CHECK:             llvm.cond_br %[[VAL_16]], ^bb2, ^bb3
298 // CHECK:           ^bb2:
299 // CHECK:             llvm.store %[[VAL_13]], %[[VAL_3]] : !llvm.ptr<i32>
300 // CHECK:             %[[VAL_17:.*]] = llvm.load %[[VAL_3]] : !llvm.ptr<i32>
301 // CHECK:             %[[VAL_18:.*]] = llvm.load %[[VAL_3]] : !llvm.ptr<i32>
302 // CHECK:             %[[VAL_19:.*]] = llvm.sext %[[VAL_18]] : i32 to i64
303 // CHECK:             %[[VAL_20:.*]] = llvm.mlir.constant(1 : i64) : i64
304 // CHECK:             %[[VAL_21:.*]] = llvm.sub %[[VAL_19]], %[[VAL_20]]  : i64
305 // CHECK:             %[[VAL_22:.*]] = llvm.getelementptr %[[VAL_1]][0, %[[VAL_21]]] : (!llvm.ptr<array<1024 x i32>>, i64) -> !llvm.ptr<i32>
306 // CHECK:             llvm.store %[[VAL_17]], %[[VAL_22]] : !llvm.ptr<i32>
307 // CHECK:             %[[VAL_23:.*]] = llvm.add %[[VAL_12]], %[[VAL_8]]  : i64
308 // CHECK:             %[[VAL_24:.*]] = llvm.trunc %[[VAL_8]] : i64 to i32
309 // CHECK:             %[[VAL_25:.*]] = llvm.load %[[VAL_3]] : !llvm.ptr<i32>
310 // CHECK:             %[[VAL_26:.*]] = llvm.add %[[VAL_25]], %[[VAL_24]]  : i32
311 // CHECK:             %[[VAL_27:.*]] = llvm.add %[[VAL_12]], %[[VAL_8]]  : i64
312 // CHECK:             %[[VAL_28:.*]] = llvm.mlir.constant(1 : index) : i64
313 // CHECK:             %[[VAL_29:.*]] = llvm.sub %[[VAL_14]], %[[VAL_28]]  : i64
314 // CHECK:             llvm.br ^bb1(%[[VAL_27]], %[[VAL_26]], %[[VAL_29]] : i64, i32, i64)
315 // CHECK:           ^bb3:
316 // CHECK:             llvm.store %[[VAL_13]], %[[VAL_3]] : !llvm.ptr<i32>
317 // CHECK:             omp.terminator
318 // CHECK:           }
319 // CHECK:           llvm.return
320 // CHECK:         }
322 // -----
324 func.func @_QPsimdloop_with_nested_loop() {
325   %0 = fir.alloca i32 {adapt.valuebyref}
326   %1 = fir.alloca !fir.array<10xi32> {bindc_name = "a", uniq_name = "_QFsimdloop_with_nested_loopEa"}
327   %2 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimdloop_with_nested_loopEi"}
328   %3 = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFsimdloop_with_nested_loopEj"}
329   %c1_i32 = arith.constant 1 : i32
330   %c10_i32 = arith.constant 10 : i32
331   %c1_i32_0 = arith.constant 1 : i32
332   omp.simdloop   for  (%arg0) : i32 = (%c1_i32) to (%c10_i32) inclusive step (%c1_i32_0) {
333     fir.store %arg0 to %0 : !fir.ref<i32>
334     %c1_i32_1 = arith.constant 1 : i32
335     %4 = fir.convert %c1_i32_1 : (i32) -> index
336     %c10_i32_2 = arith.constant 10 : i32
337     %5 = fir.convert %c10_i32_2 : (i32) -> index
338     %c1 = arith.constant 1 : index
339     %6 = fir.do_loop %arg1 = %4 to %5 step %c1 -> index {
340       %8 = fir.convert %arg1 : (index) -> i32
341       fir.store %8 to %3 : !fir.ref<i32>
342       %9 = fir.load %0 : !fir.ref<i32>
343       %10 = fir.load %0 : !fir.ref<i32>
344       %11 = fir.convert %10 : (i32) -> i64
345       %c1_i64 = arith.constant 1 : i64
346       %12 = arith.subi %11, %c1_i64 : i64
347       %13 = fir.coordinate_of %1, %12 : (!fir.ref<!fir.array<10xi32>>, i64) -> !fir.ref<i32>
348       fir.store %9 to %13 : !fir.ref<i32>
349       %14 = arith.addi %arg1, %c1 : index
350       fir.result %14 : index
351     }
352     %7 = fir.convert %6 : (index) -> i32
353     fir.store %7 to %3 : !fir.ref<i32>
354     omp.yield
355   }
356   return
359 // CHECK-LABEL:   llvm.func @_QPsimdloop_with_nested_loop() {
360 // CHECK:           %[[LOWER:.*]] = llvm.mlir.constant(1 : i32) : i32
361 // CHECK:           %[[UPPER:.*]] = llvm.mlir.constant(10 : i32) : i32
362 // CHECK:           %[[STEP:.*]] = llvm.mlir.constant(1 : i32) : i32
363 // CHECK:           omp.simdloop   for  (%[[CNT:.*]]) : i32 = (%[[LOWER]]) to (%[[UPPER]]) inclusive step (%[[STEP]]) {
364 // CHECK:             llvm.br ^bb1(%[[VAL_1:.*]], %[[VAL_2:.*]] : i64, i64)
365 // CHECK:           ^bb1(%[[VAL_3:.*]]: i64, %[[VAL_4:.*]]: i64):
366 // CHECK:             %[[VAL_5:.*]] = llvm.mlir.constant(0 : index) : i64
367 // CHECK:             %[[VAL_6:.*]] = llvm.icmp "sgt" %[[VAL_4]], %[[VAL_5]] : i64
368 // CHECK:             llvm.cond_br %[[VAL_6]], ^bb2, ^bb3
369 // CHECK:           ^bb2:
370 // CHECK:             llvm.br ^bb1(%[[VAL_7:.*]], %[[VAL_8:.*]] : i64, i64)
371 // CHECK:           ^bb3:
372 // CHECK:             omp.yield
373 // CHECK:           }
374 // CHECK:           llvm.return
375 // CHECK:         }
377 // -----
379 func.func @_QPomp_taskgroup() {
380   omp.taskgroup {
381     omp.task   {
382       fir.call @_QPwork() : () -> ()
383       omp.terminator
384     }
385     omp.terminator
386   }
387   return
389 func.func private @_QPwork()
391 // CHECK-LABEL: llvm.func @_QPomp_taskgroup() {
392 // CHECK:          omp.taskgroup   {
393 // CHECK:            omp.task   {
394 // CHECK:              llvm.call @_QPwork() : () -> ()
395 // CHECK:              omp.terminator
396 // CHECK:            }
397 // CHECK:            omp.terminator
398 // CHECK:          }
399 // CHECK:          llvm.return
400 // CHECK:        }
401 // CHECK:        llvm.func @_QPwork() attributes {sym_visibility = "private"}
402 // CHECK:      }
404 // -----
406 func.func @_QPs() {
407   %0 = fir.address_of(@_QFsEc) : !fir.ref<i32>
408   omp.atomic.update   %0 : !fir.ref<i32> {
409   ^bb0(%arg0: i32):
410     %c1_i32 = arith.constant 1 : i32
411     %1 = arith.addi %arg0, %c1_i32 : i32
412     omp.yield(%1 : i32)
413   }
414   return
416 fir.global internal @_QFsEc : i32 {
417   %c10_i32 = arith.constant 10 : i32
418   fir.has_value %c10_i32 : i32
421 // CHECK-LABEL:  llvm.func @_QPs() {
422 // CHECK:    %[[GLOBAL_VAR:.*]] = llvm.mlir.addressof @[[GLOBAL:.*]] : !llvm.ptr<i32>
423 // CHECK:    omp.atomic.update   %[[GLOBAL_VAR]] : !llvm.ptr<i32> {
424 // CHECK:    ^bb0(%[[IN_VAL:.*]]: i32):
425 // CHECK:      %[[CONST_1:.*]] = llvm.mlir.constant(1 : i32) : i32
426 // CHECK:      %[[OUT_VAL:.*]] = llvm.add %[[IN_VAL]], %[[CONST_1]]  : i32
427 // CHECK:      omp.yield(%[[OUT_VAL]] : i32)
428 // CHECK:    }
429 // CHECK:    llvm.return
430 // CHECK:  }
431 // CHECK:  llvm.mlir.global internal @[[GLOBAL]]() {{.*}} : i32 {
432 // CHECK:    %[[INIT_10:.*]] = llvm.mlir.constant(10 : i32) : i32
433 // CHECK:    llvm.return %[[INIT_10]] : i32
434 // CHECK:  }
436 func.func @_QPsb() {
437   %c10 = arith.constant 10 : index
438   %c1 = arith.constant 1 : index
439   %c1_i32 = arith.constant 1 : i32
440   %c0_i32 = arith.constant 0 : i32
441   %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsbEi"}
442   %1 = fir.alloca i32 {bindc_name = "li", uniq_name = "_QFsbEli"}
443   fir.store %c0_i32 to %1 : !fir.ref<i32>
444   omp.sections   {
445     omp.section {
446       %2 = fir.convert %c1 : (index) -> i32
447       %3:2 = fir.do_loop %arg0 = %c1 to %c10 step %c1 iter_args(%arg1 = %2) -> (index, i32) {
448         fir.store %arg1 to %0 : !fir.ref<i32>
449         %4 = fir.load %1 : !fir.ref<i32>
450         %5 = arith.addi %4, %c1_i32 : i32
451         fir.store %5 to %1 : !fir.ref<i32>
452         %6 = arith.addi %arg0, %c1 : index
453         %7 = fir.convert %c1 : (index) -> i32
454         %8 = fir.load %0 : !fir.ref<i32>
455         %9 = arith.addi %8, %7 : i32
456         fir.result %6, %9 : index, i32
457       }
458       fir.store %3#1 to %0 : !fir.ref<i32>
459       omp.terminator
460     }
461     omp.terminator
462   }
463   return
466 // CHECK:  llvm.func @_QPsb() {
467 // CHECK:    %[[ONE:.*]] = llvm.mlir.constant(1 : i32) : i32
468 // CHECK:    %[[SIZE:.*]] = llvm.mlir.constant(1 : i64) : i64
469 // CHECK:    %[[LI_REF:.*]] = llvm.alloca %6 x i32 {bindc_name = "li", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFsbEli"} : (i64) -> !llvm.ptr<i32>
470 // CHECK:    omp.sections   {
471 // CHECK:      omp.section {
472 // CHECK:        llvm.br ^[[BB_ENTRY:.*]]({{.*}})
473 // CHECK:      ^[[BB_ENTRY]]({{.*}}):
474 // CHECK:        %[[EXIT_COND:.*]] = llvm.icmp "sgt"
475 // CHECK:        llvm.cond_br %[[EXIT_COND]], ^[[BB_LOOP_BODY:.*]], ^[[BB_EXIT:.*]]
476 // CHECK:      ^[[BB_LOOP_BODY]]:
477 // CHECK:        %[[LI_VAL:.*]] = llvm.load %[[LI_REF]] : !llvm.ptr<i32>
478 // CHECK:        %[[LI_INC:.*]] = llvm.add %[[LI_VAL]], %[[ONE]]  : i32
479 // CHECK:        llvm.store %[[LI_INC]], %[[LI_REF]] : !llvm.ptr<i32>
480 // CHECK:        llvm.br ^[[BB_ENTRY]]({{.*}})
481 // CHECK:      ^[[BB_EXIT]]:
482 // CHECK:        omp.terminator
483 // CHECK:      }
484 // CHECK:      omp.terminator
485 // CHECK:    }
486 // CHECK:    llvm.return
487 // CHECK:  }
489 // -----
491 // CHECK:  omp.reduction.declare @[[EQV_REDUCTION:.*]] : i32 init {
492 // CHECK:  ^bb0(%{{.*}}: i32):
493 // CHECK:    %[[TRUE:.*]] = llvm.mlir.constant(true) : i1
494 // CHECK:    %[[TRUE_EXT:.*]] = llvm.zext %[[TRUE]] : i1 to i32
495 // CHECK:    omp.yield(%[[TRUE_EXT]] : i32)
496 // CHECK:  } combiner {
497 // CHECK:  ^bb0(%[[ARG_1:.*]]: i32, %[[ARG_2:.*]]: i32):
498 // CHECK:    %[[ZERO_1:.*]] = llvm.mlir.constant(0 : i64) : i32
499 // CHECK:    %[[ARGVAL_1:.*]] = llvm.icmp "ne" %[[ARG_1]], %[[ZERO_1]] : i32
500 // CHECK:    %[[ZERO_2:.*]] = llvm.mlir.constant(0 : i64) : i32
501 // CHECK:    %[[ARGVAL_2:.*]] = llvm.icmp "ne" %[[ARG_2]], %[[ZERO_2]] : i32
502 // CHECK:    %[[RES:.*]] = llvm.icmp "eq" %[[ARGVAL_1]], %[[ARGVAL_2]] : i1
503 // CHECK:    %[[RES_EXT:.*]] = llvm.zext %[[RES]] : i1 to i32
504 // CHECK:    omp.yield(%[[RES_EXT]] : i32)
505 // CHECK:  } 
506 // CHECK-LABEL:  @_QPsimple_reduction
507 // CHECK-SAME: %[[ARRAY_REF:.*]]: !llvm.ptr<array<100 x i32>>
508 // CHECK:    %[[RED_ACCUMULATOR:.*]] = llvm.alloca %2 x i32 {bindc_name = "x", in_type = !fir.logical<4>, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFsimple_reductionEx"} : (i64) -> !llvm.ptr<i32>
509 // CHECK:    omp.parallel   {
510 // CHECK:      omp.wsloop   reduction(@[[EQV_REDUCTION]] -> %[[RED_ACCUMULATOR]] : !llvm.ptr<i32>) for
511 // CHECK:        %[[ARRAY_ELEM_REF:.*]] = llvm.getelementptr %[[ARRAY_REF]][0, %{{.*}}] : (!llvm.ptr<array<100 x i32>>, i64) -> !llvm.ptr<i32>
512 // CHECK:        %[[ARRAY_ELEM:.*]] = llvm.load %[[ARRAY_ELEM_REF]] : !llvm.ptr<i32>
513 // CHECK:        omp.reduction %[[ARRAY_ELEM]], %[[RED_ACCUMULATOR]] : i32, !llvm.ptr<i32>
514 // CHECK:        omp.yield
515 // CHECK:      omp.terminator
516 // CHECK:    llvm.return
518 omp.reduction.declare @eqv_reduction : !fir.logical<4> init {
519 ^bb0(%arg0: !fir.logical<4>):
520   %true = arith.constant true
521   %0 = fir.convert %true : (i1) -> !fir.logical<4>
522   omp.yield(%0 : !fir.logical<4>)
523 } combiner {
524 ^bb0(%arg0: !fir.logical<4>, %arg1: !fir.logical<4>):
525   %0 = fir.convert %arg0 : (!fir.logical<4>) -> i1
526   %1 = fir.convert %arg1 : (!fir.logical<4>) -> i1
527   %2 = arith.cmpi eq, %0, %1 : i1
528   %3 = fir.convert %2 : (i1) -> !fir.logical<4>
529   omp.yield(%3 : !fir.logical<4>)
531 func.func @_QPsimple_reduction(%arg0: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) {
532   %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"}
533   %1 = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"}
534   %true = arith.constant true
535   %2 = fir.convert %true : (i1) -> !fir.logical<4>
536   fir.store %2 to %1 : !fir.ref<!fir.logical<4>>
537   omp.parallel   {
538     %3 = fir.alloca i32 {adapt.valuebyref, pinned}
539     %c1_i32 = arith.constant 1 : i32
540     %c100_i32 = arith.constant 100 : i32
541     %c1_i32_0 = arith.constant 1 : i32
542     omp.wsloop   reduction(@eqv_reduction -> %1 : !fir.ref<!fir.logical<4>>) for  (%arg1) : i32 = (%c1_i32) to (%c100_i32) inclusive step (%c1_i32_0) {
543       fir.store %arg1 to %3 : !fir.ref<i32>
544       %4 = fir.load %3 : !fir.ref<i32>
545       %5 = fir.convert %4 : (i32) -> i64
546       %c1_i64 = arith.constant 1 : i64
547       %6 = arith.subi %5, %c1_i64 : i64
548       %7 = fir.coordinate_of %arg0, %6 : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>>
549       %8 = fir.load %7 : !fir.ref<!fir.logical<4>>
550       omp.reduction %8, %1 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
551       omp.yield
552     }
553     omp.terminator
554   }
555   return