1// RUN: mlir-opt %s -pass-pipeline='func.func(canonicalize)' -split-input-file | FileCheck %s
2
3
4// -----
5
6func.func @single_iteration_some(%A: memref<?x?x?xi32>) {
7  %c0 = arith.constant 0 : index
8  %c1 = arith.constant 1 : index
9  %c2 = arith.constant 2 : index
10  %c3 = arith.constant 3 : index
11  %c6 = arith.constant 6 : index
12  %c7 = arith.constant 7 : index
13  %c10 = arith.constant 10 : index
14  scf.parallel (%i0, %i1, %i2) = (%c0, %c3, %c7) to (%c1, %c6, %c10) step (%c1, %c2, %c3) {
15    %c42 = arith.constant 42 : i32
16    memref.store %c42, %A[%i0, %i1, %i2] : memref<?x?x?xi32>
17    scf.yield
18  }
19  return
20}
21
22// CHECK-LABEL:   func @single_iteration_some(
23// CHECK-SAME:                        [[ARG0:%.*]]: memref<?x?x?xi32>) {
24// CHECK-DAG:           [[C42:%.*]] = arith.constant 42 : i32
25// CHECK-DAG:           [[C7:%.*]] = arith.constant 7 : index
26// CHECK-DAG:           [[C6:%.*]] = arith.constant 6 : index
27// CHECK-DAG:           [[C3:%.*]] = arith.constant 3 : index
28// CHECK-DAG:           [[C2:%.*]] = arith.constant 2 : index
29// CHECK-DAG:           [[C0:%.*]] = arith.constant 0 : index
30// CHECK:           scf.parallel ([[V0:%.*]]) = ([[C3]]) to ([[C6]]) step ([[C2]]) {
31// CHECK:             memref.store [[C42]], [[ARG0]]{{\[}}[[C0]], [[V0]], [[C7]]] : memref<?x?x?xi32>
32// CHECK:             scf.yield
33// CHECK:           }
34// CHECK:           return
35
36// -----
37
38func.func @single_iteration_all(%A: memref<?x?x?xi32>) {
39  %c0 = arith.constant 0 : index
40  %c1 = arith.constant 1 : index
41  %c3 = arith.constant 3 : index
42  %c6 = arith.constant 6 : index
43  %c7 = arith.constant 7 : index
44  %c10 = arith.constant 10 : index
45  scf.parallel (%i0, %i1, %i2) = (%c0, %c3, %c7) to (%c1, %c6, %c10) step (%c1, %c3, %c3) {
46    %c42 = arith.constant 42 : i32
47    memref.store %c42, %A[%i0, %i1, %i2] : memref<?x?x?xi32>
48    scf.yield
49  }
50  return
51}
52
53// CHECK-LABEL:   func @single_iteration_all(
54// CHECK-SAME:                        [[ARG0:%.*]]: memref<?x?x?xi32>) {
55// CHECK-DAG:           [[C42:%.*]] = arith.constant 42 : i32
56// CHECK-DAG:           [[C7:%.*]] = arith.constant 7 : index
57// CHECK-DAG:           [[C3:%.*]] = arith.constant 3 : index
58// CHECK-DAG:           [[C0:%.*]] = arith.constant 0 : index
59// CHECK-NOT:           scf.parallel
60// CHECK:               memref.store [[C42]], [[ARG0]]{{\[}}[[C0]], [[C3]], [[C7]]] : memref<?x?x?xi32>
61// CHECK-NOT:           scf.yield
62// CHECK:               return
63
64// -----
65
66func.func @single_iteration_reduce(%A: index, %B: index) -> (index, index) {
67  %c0 = arith.constant 0 : index
68  %c1 = arith.constant 1 : index
69  %c2 = arith.constant 2 : index
70  %c3 = arith.constant 3 : index
71  %c6 = arith.constant 6 : index
72  %0:2 = scf.parallel (%i0, %i1) = (%c1, %c3) to (%c2, %c6) step (%c1, %c3) init(%A, %B) -> (index, index) {
73    scf.reduce(%i0) : index {
74    ^bb0(%lhs: index, %rhs: index):
75      %1 = arith.addi %lhs, %rhs : index
76      scf.reduce.return %1 : index
77    }
78    scf.reduce(%i1) : index {
79    ^bb0(%lhs: index, %rhs: index):
80      %2 = arith.muli %lhs, %rhs : index
81      scf.reduce.return %2 : index
82    }
83    scf.yield
84  }
85  return %0#0, %0#1 : index, index
86}
87
88// CHECK-LABEL:   func @single_iteration_reduce(
89// CHECK-SAME:                        [[ARG0:%.*]]: index, [[ARG1:%.*]]: index)
90// CHECK-DAG:           [[C3:%.*]] = arith.constant 3 : index
91// CHECK-DAG:           [[C1:%.*]] = arith.constant 1 : index
92// CHECK-NOT:           scf.parallel
93// CHECK-NOT:           scf.reduce
94// CHECK-NOT:           scf.reduce.return
95// CHECK-NOT:           scf.yield
96// CHECK:               [[V0:%.*]] = arith.addi [[ARG0]], [[C1]]
97// CHECK:               [[V1:%.*]] = arith.muli [[ARG1]], [[C3]]
98// CHECK:               return [[V0]], [[V1]]
99
100// -----
101
102func.func @nested_parallel(%0: memref<?x?x?xf64>) -> memref<?x?x?xf64> {
103  %c0 = arith.constant 0 : index
104  %c1 = arith.constant 1 : index
105  %c2 = arith.constant 2 : index
106  %1 = memref.dim %0, %c0 : memref<?x?x?xf64>
107  %2 = memref.dim %0, %c1 : memref<?x?x?xf64>
108  %3 = memref.dim %0, %c2 : memref<?x?x?xf64>
109  %4 = memref.alloc(%1, %2, %3) : memref<?x?x?xf64>
110  scf.parallel (%arg1) = (%c0) to (%1) step (%c1) {
111    scf.parallel (%arg2) = (%c0) to (%2) step (%c1) {
112      scf.parallel (%arg3) = (%c0) to (%3) step (%c1) {
113        %5 = memref.load %0[%arg1, %arg2, %arg3] : memref<?x?x?xf64>
114        memref.store %5, %4[%arg1, %arg2, %arg3] : memref<?x?x?xf64>
115        scf.yield
116      }
117      scf.yield
118    }
119    scf.yield
120  }
121  return %4 : memref<?x?x?xf64>
122}
123
124// CHECK-LABEL:   func @nested_parallel(
125// CHECK-DAG:       [[C0:%.*]] = arith.constant 0 : index
126// CHECK-DAG:       [[C1:%.*]] = arith.constant 1 : index
127// CHECK-DAG:       [[C2:%.*]] = arith.constant 2 : index
128// CHECK:           [[B0:%.*]] = memref.dim {{.*}}, [[C0]]
129// CHECK:           [[B1:%.*]] = memref.dim {{.*}}, [[C1]]
130// CHECK:           [[B2:%.*]] = memref.dim {{.*}}, [[C2]]
131// CHECK:           scf.parallel ([[V0:%.*]], [[V1:%.*]], [[V2:%.*]]) = ([[C0]], [[C0]], [[C0]]) to ([[B0]], [[B1]], [[B2]]) step ([[C1]], [[C1]], [[C1]])
132// CHECK:           memref.load {{.*}}{{\[}}[[V0]], [[V1]], [[V2]]]
133// CHECK:           memref.store {{.*}}{{\[}}[[V0]], [[V1]], [[V2]]]
134
135// -----
136
137func.func private @side_effect()
138func.func @one_unused(%cond: i1) -> (index) {
139  %0, %1 = scf.if %cond -> (index, index) {
140    func.call @side_effect() : () -> ()
141    %c0 = "test.value0"() : () -> (index)
142    %c1 = "test.value1"() : () -> (index)
143    scf.yield %c0, %c1 : index, index
144  } else {
145    %c2 = "test.value2"() : () -> (index)
146    %c3 = "test.value3"() : () -> (index)
147    scf.yield %c2, %c3 : index, index
148  }
149  return %1 : index
150}
151
152// CHECK-LABEL:   func @one_unused
153// CHECK:           [[V0:%.*]] = scf.if %{{.*}} -> (index) {
154// CHECK:             call @side_effect() : () -> ()
155// CHECK:             [[C1:%.*]] = "test.value1"
156// CHECK:             scf.yield [[C1]] : index
157// CHECK:           } else
158// CHECK:             [[C3:%.*]] = "test.value3"
159// CHECK:             scf.yield [[C3]] : index
160// CHECK:           }
161// CHECK:           return [[V0]] : index
162
163// -----
164
165func.func private @side_effect()
166func.func @nested_unused(%cond1: i1, %cond2: i1) -> (index) {
167  %0, %1 = scf.if %cond1 -> (index, index) {
168    %2, %3 = scf.if %cond2 -> (index, index) {
169      func.call @side_effect() : () -> ()
170      %c0 = "test.value0"() : () -> (index)
171      %c1 = "test.value1"() : () -> (index)
172      scf.yield %c0, %c1 : index, index
173    } else {
174      %c2 = "test.value2"() : () -> (index)
175      %c3 = "test.value3"() : () -> (index)
176      scf.yield %c2, %c3 : index, index
177    }
178    scf.yield %2, %3 : index, index
179  } else {
180    %c0 = "test.value0_2"() : () -> (index)
181    %c1 = "test.value1_2"() : () -> (index)
182    scf.yield %c0, %c1 : index, index
183  }
184  return %1 : index
185}
186
187// CHECK-LABEL:   func @nested_unused
188// CHECK:           [[V0:%.*]] = scf.if {{.*}} -> (index) {
189// CHECK:             [[V1:%.*]] = scf.if {{.*}} -> (index) {
190// CHECK:               call @side_effect() : () -> ()
191// CHECK:               [[C1:%.*]] = "test.value1"
192// CHECK:               scf.yield [[C1]] : index
193// CHECK:             } else
194// CHECK:               [[C3:%.*]] = "test.value3"
195// CHECK:               scf.yield [[C3]] : index
196// CHECK:             }
197// CHECK:             scf.yield [[V1]] : index
198// CHECK:           } else
199// CHECK:             [[C1_2:%.*]] = "test.value1_2"
200// CHECK:             scf.yield [[C1_2]] : index
201// CHECK:           }
202// CHECK:           return [[V0]] : index
203
204// -----
205
206func.func private @side_effect()
207func.func @all_unused(%cond: i1) {
208  %c0 = arith.constant 0 : index
209  %c1 = arith.constant 1 : index
210  %0, %1 = scf.if %cond -> (index, index) {
211    func.call @side_effect() : () -> ()
212    scf.yield %c0, %c1 : index, index
213  } else {
214    func.call @side_effect() : () -> ()
215    scf.yield %c0, %c1 : index, index
216  }
217  return
218}
219
220// CHECK-LABEL:   func @all_unused
221// CHECK:           scf.if %{{.*}} {
222// CHECK:             call @side_effect() : () -> ()
223// CHECK:           } else
224// CHECK:             call @side_effect() : () -> ()
225// CHECK:           }
226// CHECK:           return
227
228// -----
229
230func.func @empty_if1(%cond: i1) {
231  scf.if %cond {
232    scf.yield
233  }
234  return
235}
236
237// CHECK-LABEL:   func @empty_if1
238// CHECK-NOT:       scf.if
239// CHECK:           return
240
241// -----
242
243func.func @empty_if2(%cond: i1) {
244  scf.if %cond {
245    scf.yield
246  } else {
247    scf.yield
248  }
249  return
250}
251
252// CHECK-LABEL:   func @empty_if2
253// CHECK-NOT:       scf.if
254// CHECK:           return
255
256// -----
257
258func.func @empty_else(%cond: i1, %v : memref<i1>) {
259  scf.if %cond {
260    memref.store %cond, %v[] : memref<i1>
261  } else {
262  }
263  return
264}
265
266// CHECK-LABEL: func @empty_else
267// CHECK:         scf.if
268// CHECK-NOT:     else
269
270// -----
271
272func.func @to_select1(%cond: i1) -> index {
273  %c0 = arith.constant 0 : index
274  %c1 = arith.constant 1 : index
275  %0 = scf.if %cond -> index {
276    scf.yield %c0 : index
277  } else {
278    scf.yield %c1 : index
279  }
280  return %0 : index
281}
282
283// CHECK-LABEL:   func @to_select1
284// CHECK-DAG:       [[C0:%.*]] = arith.constant 0 : index
285// CHECK-DAG:       [[C1:%.*]] = arith.constant 1 : index
286// CHECK:           [[V0:%.*]] = arith.select {{.*}}, [[C0]], [[C1]]
287// CHECK:           return [[V0]] : index
288
289// -----
290
291func.func @to_select_same_val(%cond: i1) -> (index, index) {
292  %c0 = arith.constant 0 : index
293  %c1 = arith.constant 1 : index
294  %0, %1 = scf.if %cond -> (index, index) {
295    scf.yield %c0, %c1 : index, index
296  } else {
297    scf.yield %c1, %c1 : index, index
298  }
299  return %0, %1 : index, index
300}
301
302// CHECK-LABEL:   func @to_select_same_val
303// CHECK-DAG:       [[C0:%.*]] = arith.constant 0 : index
304// CHECK-DAG:       [[C1:%.*]] = arith.constant 1 : index
305// CHECK:           [[V0:%.*]] = arith.select {{.*}}, [[C0]], [[C1]]
306// CHECK:           return [[V0]], [[C1]] : index, index
307
308
309func.func @to_select_with_body(%cond: i1) -> index {
310  %c0 = arith.constant 0 : index
311  %c1 = arith.constant 1 : index
312  %0 = scf.if %cond -> index {
313    "test.op"() : () -> ()
314    scf.yield %c0 : index
315  } else {
316    scf.yield %c1 : index
317  }
318  return %0 : index
319}
320
321// CHECK-LABEL:   func @to_select_with_body
322// CHECK-DAG:       [[C0:%.*]] = arith.constant 0 : index
323// CHECK-DAG:       [[C1:%.*]] = arith.constant 1 : index
324// CHECK:           [[V0:%.*]] = arith.select {{.*}}, [[C0]], [[C1]]
325// CHECK:           scf.if {{.*}} {
326// CHECK:             "test.op"() : () -> ()
327// CHECK:           }
328// CHECK:           return [[V0]] : index
329// -----
330
331func.func @to_select2(%cond: i1) -> (index, index) {
332  %c0 = arith.constant 0 : index
333  %c1 = arith.constant 1 : index
334  %c2 = arith.constant 2 : index
335  %c3 = arith.constant 3 : index
336  %0, %1 = scf.if %cond -> (index, index) {
337    scf.yield %c0, %c1 : index, index
338  } else {
339    scf.yield %c2, %c3 : index, index
340  }
341  return %0, %1 : index, index
342}
343
344// CHECK-LABEL:   func @to_select2
345// CHECK-DAG:       [[C0:%.*]] = arith.constant 0 : index
346// CHECK-DAG:       [[C1:%.*]] = arith.constant 1 : index
347// CHECK-DAG:       [[C2:%.*]] = arith.constant 2 : index
348// CHECK-DAG:       [[C3:%.*]] = arith.constant 3 : index
349// CHECK:           [[V0:%.*]] = arith.select {{.*}}, [[C0]], [[C2]]
350// CHECK:           [[V1:%.*]] = arith.select {{.*}}, [[C1]], [[C3]]
351// CHECK:           return [[V0]], [[V1]] : index
352
353// -----
354
355func.func private @make_i32() -> i32
356
357func.func @for_yields_2(%lb : index, %ub : index, %step : index) -> i32 {
358  %a = call @make_i32() : () -> (i32)
359  %b = scf.for %i = %lb to %ub step %step iter_args(%0 = %a) -> i32 {
360    scf.yield %0 : i32
361  }
362  return %b : i32
363}
364
365// CHECK-LABEL:   func @for_yields_2
366//  CHECK-NEXT:     %[[R:.*]] = call @make_i32() : () -> i32
367//  CHECK-NEXT:     return %[[R]] : i32
368
369func.func @for_yields_3(%lb : index, %ub : index, %step : index) -> (i32, i32, i32) {
370  %a = call @make_i32() : () -> (i32)
371  %b = call @make_i32() : () -> (i32)
372  %r:3 = scf.for %i = %lb to %ub step %step iter_args(%0 = %a, %1 = %a, %2 = %b) -> (i32, i32, i32) {
373    %c = func.call @make_i32() : () -> (i32)
374    scf.yield %0, %c, %2 : i32, i32, i32
375  }
376  return %r#0, %r#1, %r#2 : i32, i32, i32
377}
378
379// CHECK-LABEL:   func @for_yields_3
380//  CHECK-NEXT:     %[[a:.*]] = call @make_i32() : () -> i32
381//  CHECK-NEXT:     %[[b:.*]] = call @make_i32() : () -> i32
382//  CHECK-NEXT:     %[[r1:.*]] = scf.for {{.*}} iter_args(%arg4 = %[[a]]) -> (i32) {
383//  CHECK-NEXT:       %[[c:.*]] = func.call @make_i32() : () -> i32
384//  CHECK-NEXT:       scf.yield %[[c]] : i32
385//  CHECK-NEXT:     }
386//  CHECK-NEXT:     return %[[a]], %[[r1]], %[[b]] : i32, i32, i32
387
388// -----
389
390// Test that an empty loop which iterates at least once and only returns
391// values defined outside of the loop is folded away.
392func.func @for_yields_4() -> i32 {
393  %c0 = arith.constant 0 : index
394  %c1 = arith.constant 1 : index
395  %c2 = arith.constant 2 : index
396  %a = arith.constant 3 : i32
397  %b = arith.constant 4 : i32
398  %r = scf.for %i = %c0 to %c2 step %c1 iter_args(%0 = %a) -> i32 {
399    scf.yield %b : i32
400  }
401  return %r : i32
402}
403
404// CHECK-LABEL:   func @for_yields_4
405//  CHECK-NEXT:     %[[b:.*]] = arith.constant 4 : i32
406//  CHECK-NEXT:     return %[[b]] : i32
407
408// -----
409
410// CHECK-LABEL: @replace_true_if
411func.func @replace_true_if() {
412  %true = arith.constant true
413  // CHECK-NOT: scf.if
414  // CHECK: "test.op"
415  scf.if %true {
416    "test.op"() : () -> ()
417    scf.yield
418  }
419  return
420}
421
422// -----
423
424// CHECK-LABEL: @remove_false_if
425func.func @remove_false_if() {
426  %false = arith.constant false
427  // CHECK-NOT: scf.if
428  // CHECK-NOT: "test.op"
429  scf.if %false {
430    "test.op"() : () -> ()
431    scf.yield
432  }
433  return
434}
435
436// -----
437
438// CHECK-LABEL: @replace_true_if_with_values
439func.func @replace_true_if_with_values() {
440  %true = arith.constant true
441  // CHECK-NOT: scf.if
442  // CHECK: %[[VAL:.*]] = "test.op"
443  %0 = scf.if %true -> (i32) {
444    %1 = "test.op"() : () -> i32
445    scf.yield %1 : i32
446  } else {
447    %2 = "test.other_op"() : () -> i32
448    scf.yield %2 : i32
449  }
450  // CHECK: "test.consume"(%[[VAL]])
451  "test.consume"(%0) : (i32) -> ()
452  return
453}
454
455// -----
456
457// CHECK-LABEL: @replace_false_if_with_values
458func.func @replace_false_if_with_values() {
459  %false = arith.constant false
460  // CHECK-NOT: scf.if
461  // CHECK: %[[VAL:.*]] = "test.other_op"
462  %0 = scf.if %false -> (i32) {
463    %1 = "test.op"() : () -> i32
464    scf.yield %1 : i32
465  } else {
466    %2 = "test.other_op"() : () -> i32
467    scf.yield %2 : i32
468  }
469  // CHECK: "test.consume"(%[[VAL]])
470  "test.consume"(%0) : (i32) -> ()
471  return
472}
473
474// -----
475
476// CHECK-LABEL: @merge_nested_if
477// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)
478func.func @merge_nested_if(%arg0: i1, %arg1: i1) {
479// CHECK: %[[COND:.*]] = arith.andi %[[ARG0]], %[[ARG1]]
480// CHECK: scf.if %[[COND]] {
481// CHECK-NEXT: "test.op"()
482  scf.if %arg0 {
483    scf.if %arg1 {
484      "test.op"() : () -> ()
485      scf.yield
486    }
487    scf.yield
488  }
489  return
490}
491
492// -----
493
494// CHECK-LABEL: @merge_yielding_nested_if
495// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)
496func.func @merge_yielding_nested_if(%arg0: i1, %arg1: i1) -> (i32, f32, i32, i8) {
497// CHECK: %[[PRE0:.*]] = "test.op"() : () -> i32
498// CHECK: %[[PRE1:.*]] = "test.op1"() : () -> f32
499// CHECK: %[[PRE2:.*]] = "test.op2"() : () -> i32
500// CHECK: %[[PRE3:.*]] = "test.op3"() : () -> i8
501// CHECK: %[[COND:.*]] = arith.andi %[[ARG0]], %[[ARG1]]
502// CHECK: %[[RES:.*]]:2 = scf.if %[[COND]] -> (f32, i32)
503// CHECK:   %[[IN0:.*]] = "test.inop"() : () -> i32
504// CHECK:   %[[IN1:.*]] = "test.inop1"() : () -> f32
505// CHECK:   scf.yield %[[IN1]], %[[IN0]] : f32, i32
506// CHECK: } else {
507// CHECK:   scf.yield %[[PRE1]], %[[PRE2]] : f32, i32
508// CHECK: }
509// CHECK: return %[[PRE0]], %[[RES]]#0, %[[RES]]#1, %[[PRE3]] : i32, f32, i32, i8
510  %0 = "test.op"() : () -> (i32)
511  %1 = "test.op1"() : () -> (f32)
512  %2 = "test.op2"() : () -> (i32)
513  %3 = "test.op3"() : () -> (i8)
514  %r:4 = scf.if %arg0 -> (i32, f32, i32, i8) {
515    %a:2 = scf.if %arg1 -> (i32, f32) {
516      %i = "test.inop"() : () -> (i32)
517      %i1 = "test.inop1"() : () -> (f32)
518      scf.yield %i, %i1 : i32, f32
519    } else {
520      scf.yield %2, %1 : i32, f32
521    }
522    scf.yield %0, %a#1, %a#0, %3 : i32, f32, i32, i8
523  } else {
524    scf.yield %0, %1, %2, %3 : i32, f32, i32, i8
525  }
526  return %r#0, %r#1, %r#2, %r#3 : i32, f32, i32, i8
527}
528
529// CHECK-LABEL: @merge_yielding_nested_if_nv1
530// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)
531func.func @merge_yielding_nested_if_nv1(%arg0: i1, %arg1: i1) {
532// CHECK: %[[PRE0:.*]] = "test.op"() : () -> i32
533// CHECK: %[[PRE1:.*]] = "test.op1"() : () -> f32
534// CHECK: %[[COND:.*]] = arith.andi %[[ARG0]], %[[ARG1]]
535// CHECK: scf.if %[[COND]]
536// CHECK:   %[[IN0:.*]] = "test.inop"() : () -> i32
537// CHECK:   %[[IN1:.*]] = "test.inop1"() : () -> f32
538// CHECK: }
539  %0 = "test.op"() : () -> (i32)
540  %1 = "test.op1"() : () -> (f32)
541  scf.if %arg0 {
542    %a:2 = scf.if %arg1 -> (i32, f32) {
543      %i = "test.inop"() : () -> (i32)
544      %i1 = "test.inop1"() : () -> (f32)
545      scf.yield %i, %i1 : i32, f32
546    } else {
547      scf.yield %0, %1 : i32, f32
548    }
549  }
550  return
551}
552
553// CHECK-LABEL: @merge_yielding_nested_if_nv2
554// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)
555func.func @merge_yielding_nested_if_nv2(%arg0: i1, %arg1: i1) -> i32 {
556// CHECK: %[[PRE0:.*]] = "test.op"() : () -> i32
557// CHECK: %[[PRE1:.*]] = "test.op1"() : () -> i32
558// CHECK: %[[COND:.*]] = arith.andi %[[ARG0]], %[[ARG1]]
559// CHECK: %[[RES:.*]] = arith.select %[[ARG0]], %[[PRE0]], %[[PRE1]]
560// CHECK: scf.if %[[COND]]
561// CHECK:   "test.run"() : () -> ()
562// CHECK: }
563// CHECK: return %[[RES]]
564  %0 = "test.op"() : () -> (i32)
565  %1 = "test.op1"() : () -> (i32)
566  %r = scf.if %arg0 -> i32 {
567    scf.if %arg1 {
568      "test.run"() : () -> ()
569    }
570    scf.yield %0 : i32
571  } else {
572    scf.yield %1 : i32
573  }
574  return %r : i32
575}
576
577// CHECK-LABEL: @merge_fail_yielding_nested_if
578// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)
579func.func @merge_fail_yielding_nested_if(%arg0: i1, %arg1: i1) -> (i32, f32, i32, i8) {
580// CHECK-NOT: andi
581  %0 = "test.op"() : () -> (i32)
582  %1 = "test.op1"() : () -> (f32)
583  %2 = "test.op2"() : () -> (i32)
584  %3 = "test.op3"() : () -> (i8)
585  %r:4 = scf.if %arg0 -> (i32, f32, i32, i8) {
586    %a:2 = scf.if %arg1 -> (i32, f32) {
587      %i = "test.inop"() : () -> (i32)
588      %i1 = "test.inop1"() : () -> (f32)
589      scf.yield %i, %i1 : i32, f32
590    } else {
591      scf.yield %0, %1 : i32, f32
592    }
593    scf.yield %0, %a#1, %a#0, %3 : i32, f32, i32, i8
594  } else {
595    scf.yield %0, %1, %2, %3 : i32, f32, i32, i8
596  }
597  return %r#0, %r#1, %r#2, %r#3 : i32, f32, i32, i8
598}
599
600// -----
601
602// CHECK-LABEL:   func @if_condition_swap
603// CHECK-NEXT:     %{{.*}} = scf.if %arg0 -> (index) {
604// CHECK-NEXT:       %[[i1:.+]] = "test.origFalse"() : () -> index
605// CHECK-NEXT:       scf.yield %[[i1]] : index
606// CHECK-NEXT:     } else {
607// CHECK-NEXT:       %[[i2:.+]] = "test.origTrue"() : () -> index
608// CHECK-NEXT:       scf.yield %[[i2]] : index
609// CHECK-NEXT:     }
610func.func @if_condition_swap(%cond: i1) -> index {
611  %true = arith.constant true
612  %not = arith.xori %cond, %true : i1
613  %0 = scf.if %not -> (index) {
614    %1 = "test.origTrue"() : () -> index
615    scf.yield %1 : index
616  } else {
617    %1 = "test.origFalse"() : () -> index
618    scf.yield %1 : index
619  }
620  return %0 : index
621}
622
623// -----
624
625// CHECK-LABEL: @remove_zero_iteration_loop
626func.func @remove_zero_iteration_loop() {
627  %c42 = arith.constant 42 : index
628  %c1 = arith.constant 1 : index
629  // CHECK: %[[INIT:.*]] = "test.init"
630  %init = "test.init"() : () -> i32
631  // CHECK-NOT: scf.for
632  %0 = scf.for %i = %c42 to %c1 step %c1 iter_args(%arg = %init) -> (i32) {
633    %1 = "test.op"(%i, %arg) : (index, i32) -> i32
634    scf.yield %1 : i32
635  }
636  // CHECK: "test.consume"(%[[INIT]])
637  "test.consume"(%0) : (i32) -> ()
638  return
639}
640
641// -----
642
643// CHECK-LABEL: @remove_zero_iteration_loop_vals
644func.func @remove_zero_iteration_loop_vals(%arg0: index) {
645  %c2 = arith.constant 2 : index
646  // CHECK: %[[INIT:.*]] = "test.init"
647  %init = "test.init"() : () -> i32
648  // CHECK-NOT: scf.for
649  // CHECK-NOT: test.op
650  %0 = scf.for %i = %arg0 to %arg0 step %c2 iter_args(%arg = %init) -> (i32) {
651    %1 = "test.op"(%i, %arg) : (index, i32) -> i32
652    scf.yield %1 : i32
653  }
654  // CHECK: "test.consume"(%[[INIT]])
655  "test.consume"(%0) : (i32) -> ()
656  return
657}
658
659// -----
660
661// CHECK-LABEL: @replace_single_iteration_loop_1
662func.func @replace_single_iteration_loop_1() {
663  // CHECK: %[[LB:.*]] = arith.constant 42
664  %c42 = arith.constant 42 : index
665  %c43 = arith.constant 43 : index
666  %c1 = arith.constant 1 : index
667  // CHECK: %[[INIT:.*]] = "test.init"
668  %init = "test.init"() : () -> i32
669  // CHECK-NOT: scf.for
670  // CHECK: %[[VAL:.*]] = "test.op"(%[[LB]], %[[INIT]])
671  %0 = scf.for %i = %c42 to %c43 step %c1 iter_args(%arg = %init) -> (i32) {
672    %1 = "test.op"(%i, %arg) : (index, i32) -> i32
673    scf.yield %1 : i32
674  }
675  // CHECK: "test.consume"(%[[VAL]])
676  "test.consume"(%0) : (i32) -> ()
677  return
678}
679
680// -----
681
682// CHECK-LABEL: @replace_single_iteration_loop_2
683func.func @replace_single_iteration_loop_2() {
684  // CHECK: %[[LB:.*]] = arith.constant 5
685  %c5 = arith.constant 5 : index
686  %c6 = arith.constant 6 : index
687  %c11 = arith.constant 11 : index
688  // CHECK: %[[INIT:.*]] = "test.init"
689  %init = "test.init"() : () -> i32
690  // CHECK-NOT: scf.for
691  // CHECK: %[[VAL:.*]] = "test.op"(%[[LB]], %[[INIT]])
692  %0 = scf.for %i = %c5 to %c11 step %c6 iter_args(%arg = %init) -> (i32) {
693    %1 = "test.op"(%i, %arg) : (index, i32) -> i32
694    scf.yield %1 : i32
695  }
696  // CHECK: "test.consume"(%[[VAL]])
697  "test.consume"(%0) : (i32) -> ()
698  return
699}
700
701// -----
702
703// CHECK-LABEL: @replace_single_iteration_loop_non_unit_step
704func.func @replace_single_iteration_loop_non_unit_step() {
705  // CHECK: %[[LB:.*]] = arith.constant 42
706  %c42 = arith.constant 42 : index
707  %c47 = arith.constant 47 : index
708  %c5 = arith.constant 5 : index
709  // CHECK: %[[INIT:.*]] = "test.init"
710  %init = "test.init"() : () -> i32
711  // CHECK-NOT: scf.for
712  // CHECK: %[[VAL:.*]] = "test.op"(%[[LB]], %[[INIT]])
713  %0 = scf.for %i = %c42 to %c47 step %c5 iter_args(%arg = %init) -> (i32) {
714    %1 = "test.op"(%i, %arg) : (index, i32) -> i32
715    scf.yield %1 : i32
716  }
717  // CHECK: "test.consume"(%[[VAL]])
718  "test.consume"(%0) : (i32) -> ()
719  return
720}
721
722// -----
723
724// CHECK-LABEL: @remove_empty_parallel_loop
725func.func @remove_empty_parallel_loop(%lb: index, %ub: index, %s: index) {
726  // CHECK: %[[INIT:.*]] = "test.init"
727  %init = "test.init"() : () -> f32
728  // CHECK-NOT: scf.parallel
729  // CHECK-NOT: test.produce
730  // CHECK-NOT: test.transform
731  %0 = scf.parallel (%i, %j, %k) = (%lb, %ub, %lb) to (%ub, %ub, %ub) step (%s, %s, %s) init(%init) -> f32 {
732    %1 = "test.produce"() : () -> f32
733    scf.reduce(%1) : f32 {
734    ^bb0(%lhs: f32, %rhs: f32):
735      %2 = "test.transform"(%lhs, %rhs) : (f32, f32) -> f32
736      scf.reduce.return %2 : f32
737    }
738    scf.yield
739  }
740  // CHECK: "test.consume"(%[[INIT]])
741  "test.consume"(%0) : (f32) -> ()
742  return
743}
744
745// -----
746
747func.func private @process(%0 : memref<128x128xf32>)
748func.func private @process_tensor(%0 : tensor<128x128xf32>) -> memref<128x128xf32>
749
750// CHECK-LABEL: last_value
751//  CHECK-SAME:   %[[T0:[0-9a-z]*]]: tensor<128x128xf32>
752//  CHECK-SAME:   %[[T1:[0-9a-z]*]]: tensor<128x128xf32>
753//  CHECK-SAME:   %[[T2:[0-9a-z]*]]: tensor<128x128xf32>
754//  CHECK-SAME:   %[[M0:[0-9a-z]*]]: memref<128x128xf32>
755func.func @last_value(%t0: tensor<128x128xf32>, %t1: tensor<128x128xf32>,
756                 %t2: tensor<128x128xf32>, %m0: memref<128x128xf32>,
757                 %lb : index, %ub : index, %step : index)
758  -> (tensor<128x128xf32>, tensor<128x128xf32>, tensor<128x128xf32>)
759{
760  // CHECK-NEXT: %[[M1:.*]] = bufferization.to_memref %[[T1]] : memref<128x128xf32>
761  // CHECK-NEXT: %[[FOR_RES:.*]] = scf.for {{.*}} iter_args(%[[BBARG_T2:.*]] = %[[T2]]) -> (tensor<128x128xf32>) {
762  %0:3 = scf.for %arg0 = %lb to %ub step %step iter_args(%arg1 = %t0, %arg2 = %t1, %arg3 = %t2)
763    -> (tensor<128x128xf32>, tensor<128x128xf32>, tensor<128x128xf32>)
764  {
765    %m1 = bufferization.to_memref %arg2 : memref<128x128xf32>
766
767    // CHECK-NEXT:   call @process(%[[M0]]) : (memref<128x128xf32>) -> ()
768    func.call @process(%m0) : (memref<128x128xf32>) -> ()
769
770    // CHECK-NEXT:   call @process(%[[M1]]) : (memref<128x128xf32>) -> ()
771    func.call @process(%m1) : (memref<128x128xf32>) -> ()
772
773    // This does not hoist (fails the bbArg has at most a single check).
774    // CHECK-NEXT:   %[[T:.*]] = func.call @process_tensor(%[[BBARG_T2]]) : (tensor<128x128xf32>) -> memref<128x128xf32>
775    // CHECK-NEXT:   %[[YIELD_T:.*]] = bufferization.to_tensor %[[T:.*]]
776    %m2 = func.call @process_tensor(%arg3): (tensor<128x128xf32>) -> memref<128x128xf32>
777    %3 = bufferization.to_tensor %m2 : memref<128x128xf32>
778
779    // All this stuff goes away, incrementally
780    %1 = bufferization.to_tensor %m0 : memref<128x128xf32>
781    %2 = bufferization.to_tensor %m1 : memref<128x128xf32>
782
783    // CHECK-NEXT:   scf.yield %[[YIELD_T]] : tensor<128x128xf32>
784    scf.yield %1, %2, %3 : tensor<128x128xf32>, tensor<128x128xf32>, tensor<128x128xf32>
785
786  // CHECK-NEXT: }
787  }
788
789  // CHECK-NEXT: %[[R0:.*]] = bufferization.to_tensor %[[M0]] : memref<128x128xf32>
790  // CHECK-NEXT: %[[R1:.*]] = bufferization.to_tensor %[[M1]] : memref<128x128xf32>
791  // CHECK-NEXT: return %[[R0]], %[[R1]], %[[FOR_RES]] : tensor<128x128xf32>, tensor<128x128xf32>, tensor<128x128xf32>
792  return %0#0, %0#1, %0#2 : tensor<128x128xf32>, tensor<128x128xf32>, tensor<128x128xf32>
793}
794
795// -----
796
797// CHECK-LABEL: fold_away_iter_with_no_use_and_yielded_input
798//  CHECK-SAME:   %[[A0:[0-9a-z]*]]: i32
799func.func @fold_away_iter_with_no_use_and_yielded_input(%arg0 : i32,
800                    %ub : index, %lb : index, %step : index) -> (i32, i32) {
801  // CHECK-NEXT: %[[C32:.*]] = arith.constant 32 : i32
802  %cst = arith.constant 32 : i32
803  // CHECK-NEXT: %[[FOR_RES:.*]] = scf.for {{.*}} iter_args({{.*}} = %[[A0]]) -> (i32) {
804  %0:2 = scf.for %arg1 = %lb to %ub step %step iter_args(%arg2 = %arg0, %arg3 = %cst)
805    -> (i32, i32) {
806    %1 = arith.addi %arg2, %cst : i32
807    scf.yield %1, %cst : i32, i32
808  }
809
810  // CHECK: return %[[FOR_RES]], %[[C32]] : i32, i32
811  return %0#0, %0#1 : i32, i32
812}
813
814// -----
815
816// CHECK-LABEL: fold_away_iter_and_result_with_no_use
817//  CHECK-SAME:   %[[A0:[0-9a-z]*]]: i32
818func.func @fold_away_iter_and_result_with_no_use(%arg0 : i32,
819                    %ub : index, %lb : index, %step : index) -> (i32) {
820  %cst = arith.constant 32 : i32
821  // CHECK: %[[FOR_RES:.*]] = scf.for {{.*}} iter_args({{.*}} = %[[A0]]) -> (i32) {
822  %0:2 = scf.for %arg1 = %lb to %ub step %step iter_args(%arg2 = %arg0, %arg3 = %cst)
823    -> (i32, i32) {
824    %1 = arith.addi %arg2, %cst : i32
825    scf.yield %1, %1 : i32, i32
826  }
827
828  // CHECK: return %[[FOR_RES]] : i32
829  return %0#0 : i32
830}
831
832// -----
833
834func.func private @do(%arg0: tensor<?x?xf32>) -> tensor<?x?xf32>
835
836// CHECK-LABEL: matmul_on_tensors
837//  CHECK-SAME:   %[[T0:[0-9a-z]*]]: tensor<32x1024xf32>
838//  CHECK-SAME:   %[[T1:[0-9a-z]*]]: tensor<1024x1024xf32>
839func.func @matmul_on_tensors(%t0: tensor<32x1024xf32>, %t1: tensor<1024x1024xf32>) -> tensor<1024x1024xf32> {
840  %c0 = arith.constant 0 : index
841  %c32 = arith.constant 32 : index
842  %c1024 = arith.constant 1024 : index
843//   CHECK-NOT: tensor.cast
844//       CHECK: %[[FOR_RES:.*]] = scf.for {{.*}} iter_args(%[[ITER_T0:.*]] = %[[T0]]) -> (tensor<32x1024xf32>) {
845//       CHECK:   %[[CAST:.*]] = tensor.cast %[[ITER_T0]] : tensor<32x1024xf32> to tensor<?x?xf32>
846//       CHECK:   %[[DONE:.*]] = func.call @do(%[[CAST]]) : (tensor<?x?xf32>) -> tensor<?x?xf32>
847//       CHECK:   %[[UNCAST:.*]] = tensor.cast %[[DONE]] : tensor<?x?xf32> to tensor<32x1024xf32>
848//       CHECK:   scf.yield %[[UNCAST]] : tensor<32x1024xf32>
849  %0 = tensor.cast %t0 : tensor<32x1024xf32> to tensor<?x?xf32>
850  %1 = scf.for %i = %c0 to %c1024 step %c32 iter_args(%iter_t0 = %0) -> (tensor<?x?xf32>) {
851    %2 = func.call @do(%iter_t0) : (tensor<?x?xf32>) -> tensor<?x?xf32>
852    scf.yield %2 : tensor<?x?xf32>
853  }
854//   CHECK-NOT: tensor.cast
855//       CHECK: %[[RES:.*]] = tensor.insert_slice %[[FOR_RES]] into %[[T1]][0, 0] [32, 1024] [1, 1] : tensor<32x1024xf32> into tensor<1024x1024xf32>
856//       CHECK: return %[[RES]] : tensor<1024x1024xf32>
857  %2 = tensor.cast %1 : tensor<?x?xf32> to tensor<32x1024xf32>
858  %res = tensor.insert_slice %2 into %t1[0, 0] [32, 1024] [1, 1] : tensor<32x1024xf32> into tensor<1024x1024xf32>
859  return %res : tensor<1024x1024xf32>
860}
861
862// -----
863
864// CHECK-LABEL: @cond_prop
865func.func @cond_prop(%arg0 : i1) -> index {
866  %res = scf.if %arg0 -> index {
867    %res1 = scf.if %arg0 -> index {
868      %v1 = "test.get_some_value1"() : () -> index
869      scf.yield %v1 : index
870    } else {
871      %v2 = "test.get_some_value2"() : () -> index
872      scf.yield %v2 : index
873    }
874    scf.yield %res1 : index
875  } else {
876    %res2 = scf.if %arg0 -> index {
877      %v3 = "test.get_some_value3"() : () -> index
878      scf.yield %v3 : index
879    } else {
880      %v4 = "test.get_some_value4"() : () -> index
881      scf.yield %v4 : index
882    }
883    scf.yield %res2 : index
884  }
885  return %res : index
886}
887// CHECK-NEXT:  %[[if:.+]] = scf.if %arg0 -> (index) {
888// CHECK-NEXT:    %[[c1:.+]] = "test.get_some_value1"() : () -> index
889// CHECK-NEXT:    scf.yield %[[c1]] : index
890// CHECK-NEXT:  } else {
891// CHECK-NEXT:    %[[c4:.+]] = "test.get_some_value4"() : () -> index
892// CHECK-NEXT:    scf.yield %[[c4]] : index
893// CHECK-NEXT:  }
894// CHECK-NEXT:  return %[[if]] : index
895// CHECK-NEXT:}
896
897// -----
898
899// CHECK-LABEL: @replace_if_with_cond1
900func.func @replace_if_with_cond1(%arg0 : i1) -> (i32, i1) {
901  %true = arith.constant true
902  %false = arith.constant false
903  %res:2 = scf.if %arg0 -> (i32, i1) {
904    %v = "test.get_some_value"() : () -> i32
905    scf.yield %v, %true : i32, i1
906  } else {
907    %v2 = "test.get_some_value"() : () -> i32
908    scf.yield %v2, %false : i32, i1
909  }
910  return %res#0, %res#1 : i32, i1
911}
912// CHECK-NEXT:    %[[if:.+]] = scf.if %arg0 -> (i32) {
913// CHECK-NEXT:      %[[sv1:.+]] = "test.get_some_value"() : () -> i32
914// CHECK-NEXT:      scf.yield %[[sv1]] : i32
915// CHECK-NEXT:    } else {
916// CHECK-NEXT:      %[[sv2:.+]] = "test.get_some_value"() : () -> i32
917// CHECK-NEXT:      scf.yield %[[sv2]] : i32
918// CHECK-NEXT:    }
919// CHECK-NEXT:    return %[[if]], %arg0 : i32, i1
920
921// -----
922
923// CHECK-LABEL: @replace_if_with_cond2
924func.func @replace_if_with_cond2(%arg0 : i1) -> (i32, i1) {
925  %true = arith.constant true
926  %false = arith.constant false
927  %res:2 = scf.if %arg0 -> (i32, i1) {
928    %v = "test.get_some_value"() : () -> i32
929    scf.yield %v, %false : i32, i1
930  } else {
931    %v2 = "test.get_some_value"() : () -> i32
932    scf.yield %v2, %true : i32, i1
933  }
934  return %res#0, %res#1 : i32, i1
935}
936// CHECK-NEXT:     %true = arith.constant true
937// CHECK-NEXT:     %[[toret:.+]] = arith.xori %arg0, %true : i1
938// CHECK-NEXT:     %[[if:.+]] = scf.if %arg0 -> (i32) {
939// CHECK-NEXT:       %[[sv1:.+]] = "test.get_some_value"() : () -> i32
940// CHECK-NEXT:       scf.yield %[[sv1]] : i32
941// CHECK-NEXT:     } else {
942// CHECK-NEXT:       %[[sv2:.+]] = "test.get_some_value"() : () -> i32
943// CHECK-NEXT:       scf.yield %[[sv2]] : i32
944// CHECK-NEXT:     }
945// CHECK-NEXT:     return %[[if]], %[[toret]] : i32, i1
946
947// -----
948
949// CHECK-LABEL: @replace_if_with_cond3
950func.func @replace_if_with_cond3(%arg0 : i1, %arg2: i64) -> (i32, i64) {
951  %res:2 = scf.if %arg0 -> (i32, i64) {
952    %v = "test.get_some_value"() : () -> i32
953    scf.yield %v, %arg2 : i32, i64
954  } else {
955    %v2 = "test.get_some_value"() : () -> i32
956    scf.yield %v2, %arg2 : i32, i64
957  }
958  return %res#0, %res#1 : i32, i64
959}
960// CHECK-NEXT:     %[[if:.+]] = scf.if %arg0 -> (i32) {
961// CHECK-NEXT:       %[[sv1:.+]] = "test.get_some_value"() : () -> i32
962// CHECK-NEXT:       scf.yield %[[sv1]] : i32
963// CHECK-NEXT:     } else {
964// CHECK-NEXT:       %[[sv2:.+]] = "test.get_some_value"() : () -> i32
965// CHECK-NEXT:       scf.yield %[[sv2]] : i32
966// CHECK-NEXT:     }
967// CHECK-NEXT:     return %[[if]], %arg1 : i32, i64
968
969// -----
970
971// CHECK-LABEL: @while_cond_true
972func.func @while_cond_true() -> i1 {
973  %0 = scf.while () : () -> i1 {
974    %condition = "test.condition"() : () -> i1
975    scf.condition(%condition) %condition : i1
976  } do {
977  ^bb0(%arg0: i1):
978    "test.use"(%arg0) : (i1) -> ()
979    scf.yield
980  }
981  return %0 : i1
982}
983// CHECK-NEXT:         %[[true:.+]] = arith.constant true
984// CHECK-NEXT:         %{{.+}} = scf.while : () -> i1 {
985// CHECK-NEXT:           %[[cmp:.+]] = "test.condition"() : () -> i1
986// CHECK-NEXT:           scf.condition(%[[cmp]]) %[[cmp]] : i1
987// CHECK-NEXT:         } do {
988// CHECK-NEXT:         ^bb0(%arg0: i1):
989// CHECK-NEXT:           "test.use"(%[[true]]) : (i1) -> ()
990// CHECK-NEXT:           scf.yield
991// CHECK-NEXT:         }
992
993// -----
994
995// CHECK-LABEL: @while_unused_arg
996func.func @while_unused_arg(%x : i32, %y : f64) -> i32 {
997  %0 = scf.while (%arg1 = %x, %arg2 = %y) : (i32, f64) -> (i32) {
998    %condition = "test.condition"(%arg1) : (i32) -> i1
999    scf.condition(%condition) %arg1 : i32
1000  } do {
1001  ^bb0(%arg1: i32):
1002    %next = "test.use"(%arg1) : (i32) -> (i32)
1003    scf.yield %next, %y : i32, f64
1004  }
1005  return %0 : i32
1006}
1007// CHECK-NEXT:         %[[res:.*]] = scf.while (%[[arg2:.+]] = %{{.*}}) : (i32) -> i32 {
1008// CHECK-NEXT:           %[[cmp:.*]] = "test.condition"(%[[arg2]]) : (i32) -> i1
1009// CHECK-NEXT:           scf.condition(%[[cmp]]) %[[arg2]] : i32
1010// CHECK-NEXT:         } do {
1011// CHECK-NEXT:         ^bb0(%[[post:.+]]: i32):
1012// CHECK-NEXT:           %[[next:.+]] = "test.use"(%[[post]]) : (i32) -> i32
1013// CHECK-NEXT:           scf.yield %[[next]] : i32
1014// CHECK-NEXT:         }
1015// CHECK-NEXT:         return %[[res]] : i32
1016
1017// -----
1018
1019// CHECK-LABEL: @invariant_loop_args_in_same_order
1020// CHECK-SAME: (%[[FUNC_ARG0:.*]]: tensor<i32>)
1021func.func @invariant_loop_args_in_same_order(%f_arg0: tensor<i32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) {
1022  %cst_0 = arith.constant dense<0> : tensor<i32>
1023  %cst_1 = arith.constant dense<1> : tensor<i32>
1024  %cst_42 = arith.constant dense<42> : tensor<i32>
1025
1026  %0:5 = scf.while (%arg0 = %cst_0, %arg1 = %f_arg0, %arg2 = %cst_1, %arg3 = %cst_1, %arg4 = %cst_0) : (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) {
1027    %1 = arith.cmpi slt, %arg0, %cst_42 : tensor<i32>
1028    %2 = tensor.extract %1[] : tensor<i1>
1029    scf.condition(%2) %arg0, %arg1, %arg2, %arg3, %arg4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>
1030  } do {
1031  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>): // no predecessors
1032    // %arg1 here will get replaced by %cst_1
1033    %1 = arith.addi %arg0, %arg1 : tensor<i32>
1034    %2 = arith.addi %arg2, %arg3 : tensor<i32>
1035    scf.yield %1, %arg1, %2, %2, %arg4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>
1036  }
1037  return %0#0, %0#1, %0#2, %0#3, %0#4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>
1038}
1039// CHECK:    %[[CST42:.*]] = arith.constant dense<42>
1040// CHECK:    %[[ONE:.*]] = arith.constant dense<1>
1041// CHECK:    %[[ZERO:.*]] = arith.constant dense<0>
1042// CHECK:    %[[WHILE:.*]]:3 = scf.while (%[[ARG0:.*]] = %[[ZERO]], %[[ARG2:.*]] = %[[ONE]], %[[ARG3:.*]] = %[[ONE]])
1043// CHECK:       arith.cmpi slt, %[[ARG0]], %{{.*}}
1044// CHECK:       tensor.extract %{{.*}}[]
1045// CHECK:       scf.condition(%{{.*}}) %[[ARG0]], %[[ARG2]], %[[ARG3]]
1046// CHECK:    } do {
1047// CHECK:     ^{{.*}}(%[[ARG0:.*]]: tensor<i32>, %[[ARG2:.*]]: tensor<i32>, %[[ARG3:.*]]: tensor<i32>):
1048// CHECK:       %[[VAL0:.*]] = arith.addi %[[ARG0]], %[[FUNC_ARG0]]
1049// CHECK:       %[[VAL1:.*]] = arith.addi %[[ARG2]], %[[ARG3]]
1050// CHECK:       scf.yield %[[VAL0]], %[[VAL1]], %[[VAL1]]
1051// CHECK:    }
1052// CHECK:    return %[[WHILE]]#0, %[[FUNC_ARG0]], %[[WHILE]]#1, %[[WHILE]]#2, %[[ZERO]]
1053
1054// CHECK-LABEL: @while_loop_invariant_argument_different_order
1055func.func @while_loop_invariant_argument_different_order() -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) {
1056  %cst_0 = arith.constant dense<0> : tensor<i32>
1057  %cst_1 = arith.constant dense<1> : tensor<i32>
1058  %cst_42 = arith.constant dense<42> : tensor<i32>
1059
1060  %0:6 = scf.while (%arg0 = %cst_0, %arg1 = %cst_1, %arg2 = %cst_1, %arg3 = %cst_1, %arg4 = %cst_0) : (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) {
1061    %1 = arith.cmpi slt, %arg0, %cst_42 : tensor<i32>
1062    %2 = tensor.extract %1[] : tensor<i1>
1063    scf.condition(%2) %arg1, %arg0, %arg2, %arg0, %arg3, %arg4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>
1064  } do {
1065  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<i32>): // no predecessors
1066    %1 = arith.addi %arg0, %cst_1 : tensor<i32>
1067    %2 = arith.addi %arg2, %arg3 : tensor<i32>
1068    scf.yield %arg3, %arg1, %2, %2, %arg4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>
1069  }
1070  return %0#0, %0#1, %0#2, %0#3, %0#4, %0#5 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>
1071}
1072// CHECK:    %[[CST42:.*]] = arith.constant dense<42>
1073// CHECK:    %[[ONE:.*]] = arith.constant dense<1>
1074// CHECK:    %[[ZERO:.*]] = arith.constant dense<0>
1075// CHECK:    %[[WHILE:.*]]:2 = scf.while (%[[ARG1:.*]] = %[[ONE]], %[[ARG4:.*]] = %[[ZERO]])
1076// CHECK:       arith.cmpi slt, %[[ZERO]], %[[CST42]]
1077// CHECK:       tensor.extract %{{.*}}[]
1078// CHECK:       scf.condition(%{{.*}}) %[[ARG1]], %[[ARG4]]
1079// CHECK:    } do {
1080// CHECK:     ^{{.*}}(%{{.*}}: tensor<i32>, %{{.*}}: tensor<i32>):
1081// CHECK:       scf.yield %[[ZERO]], %[[ONE]]
1082// CHECK:    }
1083// CHECK:    return %[[WHILE]]#0, %[[ZERO]], %[[ONE]], %[[ZERO]], %[[ONE]], %[[WHILE]]#1
1084
1085// -----
1086
1087// CHECK-LABEL: @while_unused_result
1088func.func @while_unused_result() -> i32 {
1089  %0:2 = scf.while () : () -> (i32, i64) {
1090    %condition = "test.condition"() : () -> i1
1091    %v1 = "test.get_some_value"() : () -> i32
1092    %v2 = "test.get_some_value"() : () -> i64
1093    scf.condition(%condition) %v1, %v2 : i32, i64
1094  } do {
1095  ^bb0(%arg0: i32, %arg1: i64):
1096    "test.use"(%arg0) : (i32) -> ()
1097    scf.yield
1098  }
1099  return %0#0 : i32
1100}
1101// CHECK-NEXT:         %[[res:.*]] = scf.while : () -> i32 {
1102// CHECK-NEXT:           %[[cmp:.*]] = "test.condition"() : () -> i1
1103// CHECK-NEXT:           %[[val:.*]] = "test.get_some_value"() : () -> i32
1104// CHECK-NEXT:           %{{.*}} = "test.get_some_value"() : () -> i64
1105// CHECK-NEXT:           scf.condition(%[[cmp]]) %[[val]] : i32
1106// CHECK-NEXT:         } do {
1107// CHECK-NEXT:         ^bb0(%[[arg:.*]]: i32):
1108// CHECK-NEXT:           "test.use"(%[[arg]]) : (i32) -> ()
1109// CHECK-NEXT:           scf.yield
1110// CHECK-NEXT:         }
1111// CHECK-NEXT:         return %[[res]] : i32
1112
1113// CHECK-LABEL: @while_cmp_lhs
1114func.func @while_cmp_lhs(%arg0 : i32) {
1115  %0 = scf.while () : () -> i32 {
1116    %val = "test.val"() : () -> i32
1117    %condition = arith.cmpi ne, %val, %arg0 : i32
1118    scf.condition(%condition) %val : i32
1119  } do {
1120  ^bb0(%val2: i32):
1121    %condition2 = arith.cmpi ne, %val2, %arg0 : i32
1122    %negcondition2 = arith.cmpi eq, %val2, %arg0 : i32
1123    "test.use"(%condition2, %negcondition2, %val2) : (i1, i1, i32) -> ()
1124    scf.yield
1125  }
1126  return
1127}
1128// CHECK-DAG:         %[[true:.+]] = arith.constant true
1129// CHECK-DAG:         %[[false:.+]] = arith.constant false
1130// CHECK-DAG:         %{{.+}} = scf.while : () -> i32 {
1131// CHECK-NEXT:         %[[val:.+]] = "test.val"
1132// CHECK-NEXT:         %[[cmp:.+]] = arith.cmpi ne, %[[val]], %arg0 : i32
1133// CHECK-NEXT:           scf.condition(%[[cmp]]) %[[val]] : i32
1134// CHECK-NEXT:         } do {
1135// CHECK-NEXT:         ^bb0(%arg1: i32):
1136// CHECK-NEXT:           "test.use"(%[[true]], %[[false]], %arg1) : (i1, i1, i32) -> ()
1137// CHECK-NEXT:           scf.yield
1138// CHECK-NEXT:         }
1139
1140// CHECK-LABEL: @while_cmp_rhs
1141func.func @while_cmp_rhs(%arg0 : i32) {
1142  %0 = scf.while () : () -> i32 {
1143    %val = "test.val"() : () -> i32
1144    %condition = arith.cmpi ne, %arg0, %val : i32
1145    scf.condition(%condition) %val : i32
1146  } do {
1147  ^bb0(%val2: i32):
1148    %condition2 = arith.cmpi ne, %arg0, %val2 : i32
1149    %negcondition2 = arith.cmpi eq, %arg0, %val2 : i32
1150    "test.use"(%condition2, %negcondition2, %val2) : (i1, i1, i32) -> ()
1151    scf.yield
1152  }
1153  return
1154}
1155// CHECK-DAG:         %[[true:.+]] = arith.constant true
1156// CHECK-DAG:         %[[false:.+]] = arith.constant false
1157// CHECK-DAG:         %{{.+}} = scf.while : () -> i32 {
1158// CHECK-NEXT:         %[[val:.+]] = "test.val"
1159// CHECK-NEXT:         %[[cmp:.+]] = arith.cmpi ne, %arg0, %[[val]] : i32
1160// CHECK-NEXT:           scf.condition(%[[cmp]]) %[[val]] : i32
1161// CHECK-NEXT:         } do {
1162// CHECK-NEXT:         ^bb0(%arg1: i32):
1163// CHECK-NEXT:           "test.use"(%[[true]], %[[false]], %arg1) : (i1, i1, i32) -> ()
1164// CHECK-NEXT:           scf.yield
1165// CHECK-NEXT:         }
1166
1167// -----
1168
1169// CHECK-LABEL: @combineIfs
1170func.func @combineIfs(%arg0 : i1, %arg2: i64) -> (i32, i32) {
1171  %res = scf.if %arg0 -> i32 {
1172    %v = "test.firstCodeTrue"() : () -> i32
1173    scf.yield %v : i32
1174  } else {
1175    %v2 = "test.firstCodeFalse"() : () -> i32
1176    scf.yield %v2 : i32
1177  }
1178  %res2 = scf.if %arg0 -> i32 {
1179    %v = "test.secondCodeTrue"() : () -> i32
1180    scf.yield %v : i32
1181  } else {
1182    %v2 = "test.secondCodeFalse"() : () -> i32
1183    scf.yield %v2 : i32
1184  }
1185  return %res, %res2 : i32, i32
1186}
1187// CHECK-NEXT:     %[[res:.+]]:2 = scf.if %arg0 -> (i32, i32) {
1188// CHECK-NEXT:       %[[tval0:.+]] = "test.firstCodeTrue"() : () -> i32
1189// CHECK-NEXT:       %[[tval:.+]] = "test.secondCodeTrue"() : () -> i32
1190// CHECK-NEXT:       scf.yield %[[tval0]], %[[tval]] : i32, i32
1191// CHECK-NEXT:     } else {
1192// CHECK-NEXT:       %[[fval0:.+]] = "test.firstCodeFalse"() : () -> i32
1193// CHECK-NEXT:       %[[fval:.+]] = "test.secondCodeFalse"() : () -> i32
1194// CHECK-NEXT:       scf.yield %[[fval0]], %[[fval]] : i32, i32
1195// CHECK-NEXT:     }
1196// CHECK-NEXT:     return %[[res]]#0, %[[res]]#1 : i32, i32
1197
1198
1199// CHECK-LABEL: @combineIfs2
1200func.func @combineIfs2(%arg0 : i1, %arg2: i64) -> i32 {
1201  scf.if %arg0 {
1202    "test.firstCodeTrue"() : () -> ()
1203    scf.yield
1204  }
1205  %res = scf.if %arg0 -> i32 {
1206    %v = "test.secondCodeTrue"() : () -> i32
1207    scf.yield %v : i32
1208  } else {
1209    %v2 = "test.secondCodeFalse"() : () -> i32
1210    scf.yield %v2 : i32
1211  }
1212  return %res : i32
1213}
1214// CHECK-NEXT:     %[[res:.+]] = scf.if %arg0 -> (i32) {
1215// CHECK-NEXT:       "test.firstCodeTrue"() : () -> ()
1216// CHECK-NEXT:       %[[tval:.+]] = "test.secondCodeTrue"() : () -> i32
1217// CHECK-NEXT:       scf.yield %[[tval]] : i32
1218// CHECK-NEXT:     } else {
1219// CHECK-NEXT:       %[[fval:.+]] = "test.secondCodeFalse"() : () -> i32
1220// CHECK-NEXT:       scf.yield %[[fval]] : i32
1221// CHECK-NEXT:     }
1222// CHECK-NEXT:     return %[[res]] : i32
1223
1224
1225// CHECK-LABEL: @combineIfs3
1226func.func @combineIfs3(%arg0 : i1, %arg2: i64) -> i32 {
1227  %res = scf.if %arg0 -> i32 {
1228    %v = "test.firstCodeTrue"() : () -> i32
1229    scf.yield %v : i32
1230  } else {
1231    %v2 = "test.firstCodeFalse"() : () -> i32
1232    scf.yield %v2 : i32
1233  }
1234  scf.if %arg0 {
1235    "test.secondCodeTrue"() : () -> ()
1236    scf.yield
1237  }
1238  return %res : i32
1239}
1240// CHECK-NEXT:     %[[res:.+]] = scf.if %arg0 -> (i32) {
1241// CHECK-NEXT:       %[[tval:.+]] = "test.firstCodeTrue"() : () -> i32
1242// CHECK-NEXT:       "test.secondCodeTrue"() : () -> ()
1243// CHECK-NEXT:       scf.yield %[[tval]] : i32
1244// CHECK-NEXT:     } else {
1245// CHECK-NEXT:       %[[fval:.+]] = "test.firstCodeFalse"() : () -> i32
1246// CHECK-NEXT:       scf.yield %[[fval]] : i32
1247// CHECK-NEXT:     }
1248// CHECK-NEXT:     return %[[res]] : i32
1249
1250// CHECK-LABEL: @combineIfs4
1251func.func @combineIfs4(%arg0 : i1, %arg2: i64) {
1252  scf.if %arg0 {
1253    "test.firstCodeTrue"() : () -> ()
1254    scf.yield
1255  }
1256  scf.if %arg0 {
1257    "test.secondCodeTrue"() : () -> ()
1258    scf.yield
1259  }
1260  return
1261}
1262
1263// CHECK-NEXT:     scf.if %arg0 {
1264// CHECK-NEXT:       "test.firstCodeTrue"() : () -> ()
1265// CHECK-NEXT:       "test.secondCodeTrue"() : () -> ()
1266// CHECK-NEXT:     }
1267
1268// CHECK-LABEL: @combineIfsUsed
1269// CHECK-SAME: %[[arg0:.+]]: i1
1270func.func @combineIfsUsed(%arg0 : i1, %arg2: i64) -> (i32, i32) {
1271  %res = scf.if %arg0 -> i32 {
1272    %v = "test.firstCodeTrue"() : () -> i32
1273    scf.yield %v : i32
1274  } else {
1275    %v2 = "test.firstCodeFalse"() : () -> i32
1276    scf.yield %v2 : i32
1277  }
1278  %res2 = scf.if %arg0 -> i32 {
1279    %v = "test.secondCodeTrue"(%res) : (i32) -> i32
1280    scf.yield %v : i32
1281  } else {
1282    %v2 = "test.secondCodeFalse"(%res) : (i32) -> i32
1283    scf.yield %v2 : i32
1284  }
1285  return %res, %res2 : i32, i32
1286}
1287// CHECK-NEXT:     %[[res:.+]]:2 = scf.if %[[arg0]] -> (i32, i32) {
1288// CHECK-NEXT:       %[[tval0:.+]] = "test.firstCodeTrue"() : () -> i32
1289// CHECK-NEXT:       %[[tval:.+]] = "test.secondCodeTrue"(%[[tval0]]) : (i32) -> i32
1290// CHECK-NEXT:       scf.yield %[[tval0]], %[[tval]] : i32, i32
1291// CHECK-NEXT:     } else {
1292// CHECK-NEXT:       %[[fval0:.+]] = "test.firstCodeFalse"() : () -> i32
1293// CHECK-NEXT:       %[[fval:.+]] = "test.secondCodeFalse"(%[[fval0]]) : (i32) -> i32
1294// CHECK-NEXT:       scf.yield %[[fval0]], %[[fval]] : i32, i32
1295// CHECK-NEXT:     }
1296// CHECK-NEXT:     return %[[res]]#0, %[[res]]#1 : i32, i32
1297
1298// CHECK-LABEL: @combineIfsNot
1299// CHECK-SAME: %[[arg0:.+]]: i1
1300func.func @combineIfsNot(%arg0 : i1, %arg2: i64) {
1301  %true = arith.constant true
1302  %not = arith.xori %arg0, %true : i1
1303  scf.if %arg0 {
1304    "test.firstCodeTrue"() : () -> ()
1305    scf.yield
1306  }
1307  scf.if %not {
1308    "test.secondCodeTrue"() : () -> ()
1309    scf.yield
1310  }
1311  return
1312}
1313
1314// CHECK-NEXT:     scf.if %[[arg0]] {
1315// CHECK-NEXT:       "test.firstCodeTrue"() : () -> ()
1316// CHECK-NEXT:     } else {
1317// CHECK-NEXT:       "test.secondCodeTrue"() : () -> ()
1318// CHECK-NEXT:     }
1319
1320// CHECK-LABEL: @combineIfsNot2
1321// CHECK-SAME: %[[arg0:.+]]: i1
1322func.func @combineIfsNot2(%arg0 : i1, %arg2: i64) {
1323  %true = arith.constant true
1324  %not = arith.xori %arg0, %true : i1
1325  scf.if %not {
1326    "test.firstCodeTrue"() : () -> ()
1327    scf.yield
1328  }
1329  scf.if %arg0 {
1330    "test.secondCodeTrue"() : () -> ()
1331    scf.yield
1332  }
1333  return
1334}
1335
1336// CHECK-NEXT:     scf.if %[[arg0]] {
1337// CHECK-NEXT:       "test.secondCodeTrue"() : () -> ()
1338// CHECK-NEXT:     } else {
1339// CHECK-NEXT:       "test.firstCodeTrue"() : () -> ()
1340// CHECK-NEXT:     }
1341// -----
1342
1343// CHECK-LABEL: func @propagate_into_execute_region
1344func.func @propagate_into_execute_region() {
1345  %cond = arith.constant 0 : i1
1346  affine.for %i = 0 to 100 {
1347    "test.foo"() : () -> ()
1348    %v = scf.execute_region -> i64 {
1349      cf.cond_br %cond, ^bb1, ^bb2
1350
1351    ^bb1:
1352      %c1 = arith.constant 1 : i64
1353      cf.br ^bb3(%c1 : i64)
1354
1355    ^bb2:
1356      %c2 = arith.constant 2 : i64
1357      cf.br ^bb3(%c2 : i64)
1358
1359    ^bb3(%x : i64):
1360      scf.yield %x : i64
1361    }
1362    "test.bar"(%v) : (i64) -> ()
1363    // CHECK:      %[[C2:.*]] = arith.constant 2 : i64
1364    // CHECK: "test.foo"
1365    // CHECK-NEXT: "test.bar"(%[[C2]]) : (i64) -> ()
1366  }
1367  return
1368}
1369
1370// -----
1371
1372// CHECK-LABEL: func @execute_region_elim
1373func.func @execute_region_elim() {
1374  affine.for %i = 0 to 100 {
1375    "test.foo"() : () -> ()
1376    %v = scf.execute_region -> i64 {
1377      %x = "test.val"() : () -> i64
1378      scf.yield %x : i64
1379    }
1380    "test.bar"(%v) : (i64) -> ()
1381  }
1382  return
1383}
1384
1385// CHECK-NEXT:     affine.for %arg0 = 0 to 100 {
1386// CHECK-NEXT:       "test.foo"() : () -> ()
1387// CHECK-NEXT:       %[[VAL:.*]] = "test.val"() : () -> i64
1388// CHECK-NEXT:       "test.bar"(%[[VAL]]) : (i64) -> ()
1389// CHECK-NEXT:     }
1390
1391
1392// -----
1393
1394// CHECK-LABEL: func @func_execute_region_elim
1395func.func @func_execute_region_elim() {
1396    "test.foo"() : () -> ()
1397    %v = scf.execute_region -> i64 {
1398      %c = "test.cmp"() : () -> i1
1399      cf.cond_br %c, ^bb2, ^bb3
1400    ^bb2:
1401      %x = "test.val1"() : () -> i64
1402      cf.br ^bb4(%x : i64)
1403    ^bb3:
1404      %y = "test.val2"() : () -> i64
1405      cf.br ^bb4(%y : i64)
1406    ^bb4(%z : i64):
1407      scf.yield %z : i64
1408    }
1409    "test.bar"(%v) : (i64) -> ()
1410  return
1411}
1412
1413// CHECK-NOT: execute_region
1414// CHECK:     "test.foo"
1415// CHECK:     %[[cmp:.+]] = "test.cmp"
1416// CHECK:     cf.cond_br %[[cmp]], ^[[bb1:.+]], ^[[bb2:.+]]
1417// CHECK:   ^[[bb1]]:
1418// CHECK:     %[[x:.+]] = "test.val1"
1419// CHECK:     cf.br ^[[bb3:.+]](%[[x]] : i64)
1420// CHECK:   ^[[bb2]]:
1421// CHECK:     %[[y:.+]] = "test.val2"
1422// CHECK:     cf.br ^[[bb3]](%[[y:.+]] : i64)
1423// CHECK:   ^[[bb3]](%[[z:.+]]: i64):
1424// CHECK:     "test.bar"(%[[z]])
1425// CHECK:     return
1426
1427
1428// -----
1429
1430// CHECK-LABEL: func @func_execute_region_elim_multi_yield
1431func.func @func_execute_region_elim_multi_yield() {
1432    "test.foo"() : () -> ()
1433    %v = scf.execute_region -> i64 {
1434      %c = "test.cmp"() : () -> i1
1435      cf.cond_br %c, ^bb2, ^bb3
1436    ^bb2:
1437      %x = "test.val1"() : () -> i64
1438      scf.yield %x : i64
1439    ^bb3:
1440      %y = "test.val2"() : () -> i64
1441      scf.yield %y : i64
1442    }
1443    "test.bar"(%v) : (i64) -> ()
1444  return
1445}
1446
1447// CHECK-NOT: execute_region
1448// CHECK:     "test.foo"
1449// CHECK:     %[[cmp:.+]] = "test.cmp"
1450// CHECK:     cf.cond_br %[[cmp]], ^[[bb1:.+]], ^[[bb2:.+]]
1451// CHECK:   ^[[bb1]]:
1452// CHECK:     %[[x:.+]] = "test.val1"
1453// CHECK:     cf.br ^[[bb3:.+]](%[[x]] : i64)
1454// CHECK:   ^[[bb2]]:
1455// CHECK:     %[[y:.+]] = "test.val2"
1456// CHECK:     cf.br ^[[bb3]](%[[y:.+]] : i64)
1457// CHECK:   ^[[bb3]](%[[z:.+]]: i64):
1458// CHECK:     "test.bar"(%[[z]])
1459// CHECK:     return
1460