1// RUN: fir-opt --split-input-file --cfg-conversion %s | FileCheck %s
2
3func.func @x(%lb : index, %ub : index, %step : index, %b : i1, %addr : !fir.ref<index>) {
4  fir.do_loop %iv = %lb to %ub step %step unordered {
5    // expect following conditional blocks to get fused
6    fir.if %b {
7      fir.store %iv to %addr : !fir.ref<index>
8    } else {
9      %zero = arith.constant 0 : index
10      fir.store %zero to %addr : !fir.ref<index>
11    }
12  }
13  return
14}
15
16func.func private @f2() -> i1
17
18// CHECK:     func @x(%[[VAL_0:.*]]: index, %[[VAL_1:.*]]: index, %[[VAL_2:.*]]: index, %[[VAL_3:.*]]: i1, %[[VAL_4:.*]]: !fir.ref<index>) {
19// CHECK:       %[[VAL_5:.*]] = arith.subi %[[VAL_1]], %[[VAL_0]] : index
20// CHECK:       %[[VAL_6:.*]] = arith.addi %[[VAL_5]], %[[VAL_2]] : index
21// CHECK:       %[[VAL_7:.*]] = arith.divsi %[[VAL_6]], %[[VAL_2]] : index
22// CHECK:       br ^bb1(%[[VAL_0]], %[[VAL_7]] : index, index)
23// CHECK:     ^bb1(%[[VAL_8:.*]]: index, %[[VAL_9:.*]]: index):
24// CHECK:       %[[VAL_10:.*]] = arith.constant 0 : index
25// CHECK:       %[[VAL_11:.*]] = arith.cmpi sgt, %[[VAL_9]], %[[VAL_10]] : index
26// CHECK:       cond_br %[[VAL_11]], ^bb2, ^bb6
27// CHECK:     ^bb2:
28// CHECK:       cond_br %[[VAL_3]], ^bb3, ^bb4
29// CHECK:     ^bb3:
30// CHECK:       fir.store %[[VAL_8]] to %[[VAL_4]] : !fir.ref<index>
31// CHECK:       br ^bb5
32// CHECK:     ^bb4:
33// CHECK:       %[[VAL_12:.*]] = arith.constant 0 : index
34// CHECK:       fir.store %[[VAL_12]] to %[[VAL_4]] : !fir.ref<index>
35// CHECK:       br ^bb5
36// CHECK:     ^bb5:
37// CHECK:       %[[VAL_13:.*]] = arith.addi %[[VAL_8]], %[[VAL_2]] : index
38// CHECK:       %[[VAL_14:.*]] = arith.constant 1 : index
39// CHECK:       %[[VAL_15:.*]] = arith.subi %[[VAL_9]], %[[VAL_14]] : index
40// CHECK:       br ^bb1(%[[VAL_13]], %[[VAL_15]] : index, index)
41// CHECK:     ^bb6:
42// CHECK:       return
43// CHECK:     }
44// CHECK:     func private @f2() -> i1
45
46// -----
47
48func.func @x2(%lo : index, %up : index, %ok : i1) {
49  %c1 = arith.constant 1 : index
50  %unused = fir.iterate_while (%i = %lo to %up step %c1) and (%ok1 = %ok) {
51    %ok2 = fir.call @f2() : () -> i1
52    fir.result %ok2 : i1
53  }
54  return
55}
56
57func.func private @f3(i16)
58
59// CHECK:   func @x2(%[[VAL_0:.*]]: index, %[[VAL_1:.*]]: index, %[[VAL_2:.*]]: i1) {
60// CHECK:     %[[VAL_3:.*]] = arith.constant 1 : index
61// CHECK:     br ^bb1(%[[VAL_0]], %[[VAL_2]] : index, i1)
62// CHECK:   ^bb1(%[[VAL_4:.*]]: index, %[[VAL_5:.*]]: i1):
63// CHECK:     %[[VAL_6:.*]] = arith.constant 0 : index
64// CHECK:     %[[VAL_7:.*]] = arith.cmpi slt, %[[VAL_6]], %[[VAL_3]] : index
65// CHECK:     %[[VAL_8:.*]] = arith.cmpi sle, %[[VAL_4]], %[[VAL_1]] : index
66// CHECK:     %[[VAL_9:.*]] = arith.cmpi slt, %[[VAL_3]], %[[VAL_6]] : index
67// CHECK:     %[[VAL_10:.*]] = arith.cmpi sle, %[[VAL_1]], %[[VAL_4]] : index
68// CHECK:     %[[VAL_11:.*]] = arith.andi %[[VAL_7]], %[[VAL_8]] : i1
69// CHECK:     %[[VAL_12:.*]] = arith.andi %[[VAL_9]], %[[VAL_10]] : i1
70// CHECK:     %[[VAL_13:.*]] = arith.ori %[[VAL_11]], %[[VAL_12]] : i1
71// CHECK:     %[[VAL_14:.*]] = arith.andi %[[VAL_5]], %[[VAL_13]] : i1
72// CHECK:     cond_br %[[VAL_14]], ^bb2, ^bb3
73// CHECK:   ^bb2:
74// CHECK:     %[[VAL_15:.*]] = fir.call @f2() : () -> i1
75// CHECK:     %[[VAL_16:.*]] = arith.addi %[[VAL_4]], %[[VAL_3]] : index
76// CHECK:     br ^bb1(%[[VAL_16]], %[[VAL_15]] : index, i1)
77// CHECK:   ^bb3:
78// CHECK:     return
79// CHECK:   }
80// CHECK:   func private @f3(i16)
81
82// -----
83
84// do_loop with an extra loop-carried value
85func.func @x3(%lo : index, %up : index) -> i1 {
86  %c1 = arith.constant 1 : index
87  %ok1 = arith.constant true
88  %ok2 = fir.do_loop %i = %lo to %up step %c1 iter_args(%j = %ok1) -> i1 {
89    %ok = fir.call @f2() : () -> i1
90    fir.result %ok : i1
91  }
92  return %ok2 : i1
93}
94
95// CHECK-LABEL:   func @x3(
96// CHECK-SAME:             %[[VAL_0:.*]]: index,
97// CHECK-SAME:             %[[VAL_1:.*]]: index) -> i1 {
98// CHECK:           %[[VAL_2:.*]] = arith.constant 1 : index
99// CHECK:           %[[VAL_3:.*]] = arith.constant true
100// CHECK:           %[[VAL_4:.*]] = arith.subi %[[VAL_1]], %[[VAL_0]] : index
101// CHECK:           %[[VAL_5:.*]] = arith.addi %[[VAL_4]], %[[VAL_2]] : index
102// CHECK:           %[[VAL_6:.*]] = arith.divsi %[[VAL_5]], %[[VAL_2]] : index
103// CHECK:           br ^bb1(%[[VAL_0]], %[[VAL_3]], %[[VAL_6]] : index, i1, index)
104// CHECK:         ^bb1(%[[VAL_7:.*]]: index, %[[VAL_8:.*]]: i1, %[[VAL_9:.*]]: index):
105// CHECK:           %[[VAL_10:.*]] = arith.constant 0 : index
106// CHECK:           %[[VAL_11:.*]] = arith.cmpi sgt, %[[VAL_9]], %[[VAL_10]] : index
107// CHECK:           cond_br %[[VAL_11]], ^bb2, ^bb3
108// CHECK:         ^bb2:
109// CHECK:           %[[VAL_12:.*]] = fir.call @f2() : () -> i1
110// CHECK:           %[[VAL_13:.*]] = arith.addi %[[VAL_7]], %[[VAL_2]] : index
111// CHECK:           %[[VAL_14:.*]] = arith.constant 1 : index
112// CHECK:           %[[VAL_15:.*]] = arith.subi %[[VAL_9]], %[[VAL_14]] : index
113// CHECK:           br ^bb1(%[[VAL_13]], %[[VAL_12]], %[[VAL_15]] : index, i1, index)
114// CHECK:         ^bb3:
115// CHECK:           return %[[VAL_8]] : i1
116// CHECK:         }
117
118// -----
119
120// iterate_while with an extra loop-carried value
121func.func @y3(%lo : index, %up : index) -> i1 {
122  %c1 = arith.constant 1 : index
123  %ok1 = arith.constant true
124  %ok4 = fir.call @f2() : () -> i1
125  %ok2:2 = fir.iterate_while (%i = %lo to %up step %c1) and (%ok3 = %ok1) iter_args(%j = %ok4) -> i1 {
126    %ok = fir.call @f2() : () -> i1
127    fir.result %ok3, %ok : i1, i1
128  }
129  %andok = arith.andi %ok2#0, %ok2#1 : i1
130  return %andok : i1
131}
132
133func.func private @f4(i32) -> i1
134
135// CHECK-LABEL:   func @y3(
136// CHECK-SAME:             %[[VAL_0:.*]]: index,
137// CHECK-SAME:             %[[VAL_1:.*]]: index) -> i1 {
138// CHECK:           %[[VAL_2:.*]] = arith.constant 1 : index
139// CHECK:           %[[VAL_3:.*]] = arith.constant true
140// CHECK:           %[[VAL_4:.*]] = fir.call @f2() : () -> i1
141// CHECK:           br ^bb1(%[[VAL_0]], %[[VAL_3]], %[[VAL_4]] : index, i1, i1)
142// CHECK:         ^bb1(%[[VAL_5:.*]]: index, %[[VAL_6:.*]]: i1, %[[VAL_7:.*]]: i1):
143// CHECK:           %[[VAL_8:.*]] = arith.constant 0 : index
144// CHECK:           %[[VAL_9:.*]] = arith.cmpi slt, %[[VAL_8]], %[[VAL_2]] : index
145// CHECK:           %[[VAL_10:.*]] = arith.cmpi sle, %[[VAL_5]], %[[VAL_1]] : index
146// CHECK:           %[[VAL_11:.*]] = arith.cmpi slt, %[[VAL_2]], %[[VAL_8]] : index
147// CHECK:           %[[VAL_12:.*]] = arith.cmpi sle, %[[VAL_1]], %[[VAL_5]] : index
148// CHECK:           %[[VAL_13:.*]] = arith.andi %[[VAL_9]], %[[VAL_10]] : i1
149// CHECK:           %[[VAL_14:.*]] = arith.andi %[[VAL_11]], %[[VAL_12]] : i1
150// CHECK:           %[[VAL_15:.*]] = arith.ori %[[VAL_13]], %[[VAL_14]] : i1
151// CHECK:           %[[VAL_16:.*]] = arith.andi %[[VAL_6]], %[[VAL_15]] : i1
152// CHECK:           cond_br %[[VAL_16]], ^bb2, ^bb3
153// CHECK:         ^bb2:
154// CHECK:           %[[VAL_17:.*]] = fir.call @f2() : () -> i1
155// CHECK:           %[[VAL_18:.*]] = arith.addi %[[VAL_5]], %[[VAL_2]] : index
156// CHECK:           br ^bb1(%[[VAL_18]], %[[VAL_6]], %[[VAL_17]] : index, i1, i1)
157// CHECK:         ^bb3:
158// CHECK:           %[[VAL_19:.*]] = arith.andi %[[VAL_6]], %[[VAL_7]] : i1
159// CHECK:           return %[[VAL_19]] : i1
160// CHECK:         }
161// CHECK:         func private @f4(i32) -> i1
162
163// -----
164
165// do_loop that returns the final value of the induction
166func.func @x4(%lo : index, %up : index) -> index {
167  %c1 = arith.constant 1 : index
168  %v = fir.do_loop %i = %lo to %up step %c1 -> index {
169    %i1 = fir.convert %i : (index) -> i32
170    %ok = fir.call @f4(%i1) : (i32) -> i1
171    fir.result %i : index
172  }
173  return %v : index
174}
175
176// CHECK-LABEL:   func @x4(
177// CHECK-SAME:             %[[VAL_0:.*]]: index,
178// CHECK-SAME:             %[[VAL_1:.*]]: index) -> index {
179// CHECK:           %[[VAL_2:.*]] = arith.constant 1 : index
180// CHECK:           %[[VAL_3:.*]] = arith.subi %[[VAL_1]], %[[VAL_0]] : index
181// CHECK:           %[[VAL_4:.*]] = arith.addi %[[VAL_3]], %[[VAL_2]] : index
182// CHECK:           %[[VAL_5:.*]] = arith.divsi %[[VAL_4]], %[[VAL_2]] : index
183// CHECK:           br ^bb1(%[[VAL_0]], %[[VAL_5]] : index, index)
184// CHECK:         ^bb1(%[[VAL_6:.*]]: index, %[[VAL_7:.*]]: index):
185// CHECK:           %[[VAL_8:.*]] = arith.constant 0 : index
186// CHECK:           %[[VAL_9:.*]] = arith.cmpi sgt, %[[VAL_7]], %[[VAL_8]] : index
187// CHECK:           cond_br %[[VAL_9]], ^bb2, ^bb3
188// CHECK:         ^bb2:
189// CHECK:           %[[VAL_10:.*]] = fir.convert %[[VAL_6]] : (index) -> i32
190// CHECK:           %[[VAL_11:.*]] = fir.call @f4(%[[VAL_10]]) : (i32) -> i1
191// CHECK:           %[[VAL_12:.*]] = arith.addi %[[VAL_6]], %[[VAL_2]] : index
192// CHECK:           %[[VAL_13:.*]] = arith.constant 1 : index
193// CHECK:           %[[VAL_14:.*]] = arith.subi %[[VAL_7]], %[[VAL_13]] : index
194// CHECK:           br ^bb1(%[[VAL_12]], %[[VAL_14]] : index, index)
195// CHECK:         ^bb3:
196// CHECK:           return %[[VAL_6]] : index
197// CHECK:         }
198
199// -----
200
201// iterate_while that returns the final value of both inductions
202func.func @y4(%lo : index, %up : index) -> index {
203  %c1 = arith.constant 1 : index
204  %ok1 = arith.constant true
205  %v:2 = fir.iterate_while (%i = %lo to %up step %c1) and (%ok2 = %ok1) -> (index, i1) {
206    %i1 = fir.convert %i : (index) -> i32
207    %ok = fir.call @f4(%i1) : (i32) -> i1
208    fir.result %i, %ok : index, i1
209  }
210  return %v#0 : index
211}
212
213// CHECK-LABEL:   func @y4(
214// CHECK-SAME:             %[[VAL_0:.*]]: index,
215// CHECK-SAME:             %[[VAL_1:.*]]: index) -> index {
216// CHECK:           %[[VAL_2:.*]] = arith.constant 1 : index
217// CHECK:           %[[VAL_3:.*]] = arith.constant true
218// CHECK:           br ^bb1(%[[VAL_0]], %[[VAL_3]] : index, i1)
219// CHECK:         ^bb1(%[[VAL_4:.*]]: index, %[[VAL_5:.*]]: i1):
220// CHECK:           %[[VAL_6:.*]] = arith.constant 0 : index
221// CHECK:           %[[VAL_7:.*]] = arith.cmpi slt, %[[VAL_6]], %[[VAL_2]] : index
222// CHECK:           %[[VAL_8:.*]] = arith.cmpi sle, %[[VAL_4]], %[[VAL_1]] : index
223// CHECK:           %[[VAL_9:.*]] = arith.cmpi slt, %[[VAL_2]], %[[VAL_6]] : index
224// CHECK:           %[[VAL_10:.*]] = arith.cmpi sle, %[[VAL_1]], %[[VAL_4]] : index
225// CHECK:           %[[VAL_11:.*]] = arith.andi %[[VAL_7]], %[[VAL_8]] : i1
226// CHECK:           %[[VAL_12:.*]] = arith.andi %[[VAL_9]], %[[VAL_10]] : i1
227// CHECK:           %[[VAL_13:.*]] = arith.ori %[[VAL_11]], %[[VAL_12]] : i1
228// CHECK:           %[[VAL_14:.*]] = arith.andi %[[VAL_5]], %[[VAL_13]] : i1
229// CHECK:           cond_br %[[VAL_14]], ^bb2, ^bb3
230// CHECK:         ^bb2:
231// CHECK:           %[[VAL_15:.*]] = fir.convert %[[VAL_4]] : (index) -> i32
232// CHECK:           %[[VAL_16:.*]] = fir.call @f4(%[[VAL_15]]) : (i32) -> i1
233// CHECK:           %[[VAL_17:.*]] = arith.addi %[[VAL_4]], %[[VAL_2]] : index
234// CHECK:           br ^bb1(%[[VAL_17]], %[[VAL_16]] : index, i1)
235// CHECK:         ^bb3:
236// CHECK:           return %[[VAL_4]] : index
237// CHECK:         }
238
239// -----
240
241// do_loop that returns the final induction value
242// and an extra loop-carried value
243func.func @x5(%lo : index, %up : index) -> index {
244  %c1 = arith.constant 1 : index
245  %s1 = arith.constant 42 : i16
246  %v:2 = fir.do_loop %i = %lo to %up step %c1 iter_args(%s = %s1) -> (index, i16) {
247    %ok = fir.call @f2() : () -> i1
248    %s2 = fir.convert %ok : (i1) -> i16
249    fir.result %i, %s2 : index, i16
250  }
251  fir.call @f3(%v#1) : (i16) -> ()
252  return %v#0 : index
253}
254
255// CHECK-LABEL:   func @x5(
256// CHECK-SAME:             %[[VAL_0:.*]]: index,
257// CHECK-SAME:             %[[VAL_1:.*]]: index) -> index {
258// CHECK:           %[[VAL_2:.*]] = arith.constant 1 : index
259// CHECK:           %[[VAL_3:.*]] = arith.constant 42 : i16
260// CHECK:           %[[VAL_4:.*]] = arith.subi %[[VAL_1]], %[[VAL_0]] : index
261// CHECK:           %[[VAL_5:.*]] = arith.addi %[[VAL_4]], %[[VAL_2]] : index
262// CHECK:           %[[VAL_6:.*]] = arith.divsi %[[VAL_5]], %[[VAL_2]] : index
263// CHECK:           br ^bb1(%[[VAL_0]], %[[VAL_3]], %[[VAL_6]] : index, i16, index)
264// CHECK:         ^bb1(%[[VAL_7:.*]]: index, %[[VAL_8:.*]]: i16, %[[VAL_9:.*]]: index):
265// CHECK:           %[[VAL_10:.*]] = arith.constant 0 : index
266// CHECK:           %[[VAL_11:.*]] = arith.cmpi sgt, %[[VAL_9]], %[[VAL_10]] : index
267// CHECK:           cond_br %[[VAL_11]], ^bb2, ^bb3
268// CHECK:         ^bb2:
269// CHECK:           %[[VAL_12:.*]] = fir.call @f2() : () -> i1
270// CHECK:           %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> i16
271// CHECK:           %[[VAL_14:.*]] = arith.addi %[[VAL_7]], %[[VAL_2]] : index
272// CHECK:           %[[VAL_15:.*]] = arith.constant 1 : index
273// CHECK:           %[[VAL_16:.*]] = arith.subi %[[VAL_9]], %[[VAL_15]] : index
274// CHECK:           br ^bb1(%[[VAL_14]], %[[VAL_13]], %[[VAL_16]] : index, i16, index)
275// CHECK:         ^bb3:
276// CHECK:           fir.call @f3(%[[VAL_8]]) : (i16) -> ()
277// CHECK:           return %[[VAL_7]] : index
278// CHECK:         }
279
280// -----
281
282// iterate_while that returns the both induction values
283// and an extra loop-carried value
284func.func @y5(%lo : index, %up : index) -> index {
285  %c1 = arith.constant 1 : index
286  %s1 = arith.constant 42 : i16
287  %ok1 = arith.constant true
288  %v:3 = fir.iterate_while (%i = %lo to %up step %c1) and (%ok2 = %ok1) iter_args(%s = %s1) -> (index, i1, i16) {
289    %ok = fir.call @f2() : () -> i1
290    %s2 = fir.convert %ok : (i1) -> i16
291    fir.result %i, %ok, %s2 : index, i1, i16
292  }
293  fir.if %v#1 {
294    %arg = arith.constant 0 : i32
295    %ok4 = fir.call @f4(%arg) : (i32) -> i1
296  }
297  fir.call @f3(%v#2) : (i16) -> ()
298  return %v#0 : index
299}
300
301// CHECK-LABEL:   func @y5(
302// CHECK-SAME:             %[[VAL_0:.*]]: index,
303// CHECK-SAME:             %[[VAL_1:.*]]: index) -> index {
304// CHECK:           %[[VAL_2:.*]] = arith.constant 1 : index
305// CHECK:           %[[VAL_3:.*]] = arith.constant 42 : i16
306// CHECK:           %[[VAL_4:.*]] = arith.constant true
307// CHECK:           br ^bb1(%[[VAL_0]], %[[VAL_4]], %[[VAL_3]] : index, i1, i16)
308// CHECK:         ^bb1(%[[VAL_5:.*]]: index, %[[VAL_6:.*]]: i1, %[[VAL_7:.*]]: i16):
309// CHECK:           %[[VAL_8:.*]] = arith.constant 0 : index
310// CHECK:           %[[VAL_9:.*]] = arith.cmpi slt, %[[VAL_8]], %[[VAL_2]] : index
311// CHECK:           %[[VAL_10:.*]] = arith.cmpi sle, %[[VAL_5]], %[[VAL_1]] : index
312// CHECK:           %[[VAL_11:.*]] = arith.cmpi slt, %[[VAL_2]], %[[VAL_8]] : index
313// CHECK:           %[[VAL_12:.*]] = arith.cmpi sle, %[[VAL_1]], %[[VAL_5]] : index
314// CHECK:           %[[VAL_13:.*]] = arith.andi %[[VAL_9]], %[[VAL_10]] : i1
315// CHECK:           %[[VAL_14:.*]] = arith.andi %[[VAL_11]], %[[VAL_12]] : i1
316// CHECK:           %[[VAL_15:.*]] = arith.ori %[[VAL_13]], %[[VAL_14]] : i1
317// CHECK:           %[[VAL_16:.*]] = arith.andi %[[VAL_6]], %[[VAL_15]] : i1
318// CHECK:           cond_br %[[VAL_16]], ^bb2, ^bb3
319// CHECK:         ^bb2:
320// CHECK:           %[[VAL_17:.*]] = fir.call @f2() : () -> i1
321// CHECK:           %[[VAL_18:.*]] = fir.convert %[[VAL_17]] : (i1) -> i16
322// CHECK:           %[[VAL_19:.*]] = arith.addi %[[VAL_5]], %[[VAL_2]] : index
323// CHECK:           br ^bb1(%[[VAL_19]], %[[VAL_17]], %[[VAL_18]] : index, i1, i16)
324// CHECK:         ^bb3:
325// CHECK:           cond_br %[[VAL_6]], ^bb4, ^bb5
326// CHECK:         ^bb4:
327// CHECK:           %[[VAL_20:.*]] = arith.constant 0 : i32
328// CHECK:           %[[VAL_21:.*]] = fir.call @f4(%[[VAL_20]]) : (i32) -> i1
329// CHECK:           br ^bb5
330// CHECK:         ^bb5:
331// CHECK:           fir.call @f3(%[[VAL_7]]) : (i16) -> ()
332// CHECK:           return %[[VAL_5]] : index
333// CHECK:         }
334