[clang-format] Handle C-style cast of member function pointer type (#126340)
[llvm-project.git] / mlir / test / Conversion / ControlFlowToSCF / test.mlir
blobf6e7fb265790b78edf74277223bbdda29c589394
1 // RUN: mlir-opt --lift-cf-to-scf -split-input-file %s | FileCheck %s
3 func.func @simple_if() {
4   %cond = "test.test1"() : () -> i1
5   cf.cond_br %cond, ^bb1, ^bb2
6 ^bb1:
7   "test.test2"() : () -> ()
8   cf.br ^bb3
9 ^bb2:
10   "test.test3"() : () -> ()
11   cf.br ^bb3
12 ^bb3:
13   "test.test4"() : () -> ()
14   return
17 // CHECK-LABEL: func @simple_if
18 // CHECK:      %[[COND:.*]] = "test.test1"()
19 // CHECK-NEXT: scf.if %[[COND]]
20 // CHECK-NEXT:   "test.test2"()
21 // CHECK-NEXT: else
22 // CHECK-NEXT:   "test.test3"()
23 // CHECK-NEXT: }
24 // CHECK-NEXT: "test.test4"()
25 // CHECK-NEXT: return
27 // -----
29 func.func @if_with_block_args() -> index {
30   %cond = "test.test1"() : () -> i1
31   cf.cond_br %cond, ^bb1, ^bb2
32 ^bb1:
33   %1 = "test.test2"() : () -> (index)
34   cf.br ^bb3(%1: index)
35 ^bb2:
36   %2 = "test.test3"() : () -> (index)
37   cf.br ^bb3(%2: index)
38 ^bb3(%3: index):
39   "test.test4"() : () -> ()
40   return %3 : index
43 // CHECK-LABEL: func @if_with_block_args
44 // CHECK:      %[[COND:.*]] = "test.test1"()
45 // CHECK-NEXT: %[[RES:.*]] = scf.if %[[COND]]
46 // CHECK-NEXT:   %[[VAL1:.*]]  = "test.test2"()
47 // CHECK-NEXT:   scf.yield %[[VAL1]]
48 // CHECK-NEXT: else
49 // CHECK-NEXT:   %[[VAL2:.*]]  = "test.test3"()
50 // CHECK-NEXT:   scf.yield %[[VAL2]]
51 // CHECK:      "test.test4"()
52 // CHECK-NEXT: return %[[RES]]
54 // -----
56 func.func @empty_else() {
57   %cond = "test.test1"() : () -> i1
58   cf.cond_br %cond, ^bb1, ^bb3
59 ^bb1:
60   "test.test2"() : () -> ()
61   cf.br ^bb3
62 ^bb3:
63   "test.test4"() : () -> ()
64   return
67 // CHECK-LABEL: func @empty_else
68 // CHECK:      %[[COND:.*]] = "test.test1"()
69 // CHECK-NEXT: scf.if %[[COND]]
70 // CHECK-NEXT:   "test.test2"()
71 // CHECK:      else
72 // CHECK-NEXT:      }
73 // CHECK-NEXT: "test.test4"()
74 // CHECK-NEXT: return
76 // -----
78 func.func @while_loop() {
79   "test.test1"() : () -> ()
80   cf.br ^bb1
81 ^bb1:
82   %cond = "test.test2"() : () -> i1
83   cf.cond_br %cond, ^bb2, ^bb3
84 ^bb2:
85   "test.test3"() : () -> ()
86   cf.br ^bb1
87 ^bb3:
88   "test.test4"() : () -> ()
89   return
92 // CHECK-LABEL: func @while_loop
93 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
94 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
95 // CHECK-NEXT: "test.test1"()
96 // CHECK-NEXT: scf.while
97 // CHECK-NEXT:   %[[COND:.*]] = "test.test2"()
98 // CHECK-NEXT:   %[[RES:.*]]:2 = scf.if %[[COND]]
99 // CHECK-NEXT:     "test.test3"()
100 // CHECK-NEXT:     scf.yield %[[C0]], %[[C1]]
101 // CHECK-NEXT:   else
102 // CHECK-NEXT:     scf.yield %[[C1]], %[[C0]]
103 // CHECK:        %[[COND:.*]] = arith.trunci %[[RES]]#1
104 // CHECK-NEXT:   scf.condition(%[[COND]])
105 // CHECK-NEXT: do
106 // CHECK-NEXT:   scf.yield
107 // CHECK:      "test.test4"()
108 // CHECK-NEXT: return
110 // -----
112 func.func @while_loop_with_block_args() -> i64{
113   %1 = "test.test1"() : () -> index
114   cf.br ^bb1(%1: index)
115 ^bb1(%2: index):
116   %cond:2 = "test.test2"() : () -> (i1, i64)
117   cf.cond_br %cond#0, ^bb2(%cond#1: i64), ^bb3(%cond#1: i64)
118 ^bb2(%3: i64):
119   %4 = "test.test3"(%3) : (i64) -> index
120   cf.br ^bb1(%4: index)
121 ^bb3(%5: i64):
122   "test.test4"() : () -> ()
123   return %5 : i64
126 // CHECK-LABEL: func @while_loop_with_block_args
127 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
128 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
129 // CHECK-DAG: %[[POISON_i64:.*]] = ub.poison : i64
130 // CHECK-DAG: %[[POISON_index:.*]] = ub.poison : index
131 // CHECK-NEXT: %[[VAL1:.*]] = "test.test1"()
132 // CHECK-NEXT: %[[RES:.*]]:2 = scf.while (%[[ARG0:.*]] = %[[VAL1]], %[[ARG1:.*]] = %[[POISON_i64]])
133 // CHECK-NEXT:   %[[COND:.*]]:2 = "test.test2"()
134 // CHECK-NEXT:   %[[IF_VALS:.*]]:4 = scf.if %[[COND]]#0
135 // CHECK-NEXT:     %[[VAL:.*]] = "test.test3"(%[[COND]]#1)
136 // CHECK-NEXT:     scf.yield %[[VAL]], %[[POISON_i64]], %[[C0]], %[[C1]]
137 // CHECK-NEXT:   else
138 // CHECK-NEXT:     scf.yield %[[POISON_index]], %[[COND]]#1, %[[C1]], %[[C0]]
139 // CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_VALS]]#3
140 // CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[IF_VALS]]#0, %[[IF_VALS]]#1
141 // CHECK-NEXT: do
142 // CHECK-NEXT:   ^{{.+}}(
143 // CHECK-SAME: [[ARG0:[[:alnum:]]+]]:
144 // CHECK-SAME: [[ARG1:[[:alnum:]]+]]:
145 // CHECK-NEXT:   scf.yield %[[ARG0]], %[[ARG1]]
146 // CHECK:      "test.test4"() : () -> ()
147 // CHECK-NEXT: return %[[RES]]#1 : i64
149 // -----
151 func.func @multi_exit_loop() {
152   "test.test1"() : () -> ()
153   cf.br ^bb1
154 ^bb1:
155   %cond = "test.test2"() : () -> i1
156   cf.cond_br %cond, ^bb2, ^bb3
157 ^bb2:
158   %cond2 = "test.test3"() : () -> i1
159   cf.cond_br %cond2, ^bb3, ^bb1
160 ^bb3:
161   "test.test4"() : () -> ()
162   return
165 // CHECK-LABEL: func @multi_exit_loop
166 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
167 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
168 // CHECK-NEXT: "test.test1"()
169 // CHECK-NEXT: scf.while
170 // CHECK-NEXT:   %[[COND:.*]] = "test.test2"()
171 // CHECK-NEXT:   %[[IF_PAIR:.*]]:2 = scf.if %[[COND]]
172 // CHECK-NEXT:     %[[COND2:.*]] = "test.test3"()
173 // CHECK-NEXT:     %[[IF_PAIR2:.*]]:2 = scf.if %[[COND2]]
174 // CHECK-NEXT:       scf.yield %[[C1]], %[[C0]]
175 // CHECK-NEXT:     else
176 // CHECK-NEXT:       scf.yield %[[C0]], %[[C1]]
177 // CHECK:          scf.yield %[[IF_PAIR2]]#0, %[[IF_PAIR2]]#1
178 // CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_PAIR]]#1
179 // CHECK-NEXT:   scf.condition(%[[TRUNC]])
180 // CHECK-NEXT: do
181 // CHECK-NEXT:   scf.yield
182 // CHECK:      "test.test4"()
183 // CHECK-NEXT: return
185 // -----
187 func.func private @foo(%arg: f32) -> f32
188 func.func private @bar(%arg: f32)
190 func.func @switch_with_fallthrough(%flag: i32, %arg1 : f32, %arg2 : f32) {
191   cf.switch %flag : i32, [
192     default: ^bb1(%arg1 : f32),
193     0: ^bb2(%arg2 : f32),
194     1: ^bb3
195   ]
197 ^bb1(%arg3 : f32):
198   %0 = call @foo(%arg3) : (f32) -> f32
199   cf.br ^bb2(%0 : f32)
201 ^bb2(%arg4 : f32):
202   call @bar(%arg4) : (f32) -> ()
203   cf.br ^bb3
205 ^bb3:
206   return
209 // CHECK-LABEL: func @switch_with_fallthrough
210 // CHECK-SAME: %[[ARG0:[[:alnum:]]+]]
211 // CHECK-SAME: %[[ARG1:[[:alnum:]]+]]
212 // CHECK-SAME: %[[ARG2:[[:alnum:]]+]]
213 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
214 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
215 // CHECK-DAG: %[[POISON:.*]] = ub.poison
216 // CHECK-NEXT: %[[INDEX_CAST:.*]] = arith.index_castui %[[ARG0]]
217 // CHECK-NEXT: %[[SWITCH_PAIR:.*]]:2 = scf.index_switch %[[INDEX_CAST]]
218 // CHECK-NEXT: case 0
219 // CHECK-NEXT:   scf.yield %[[ARG2]], %[[C0]]
220 // CHECK:      case 1
221 // CHECK-NEXT:   scf.yield %[[POISON]], %[[C1]]
222 // CHECK:      default
223 // CHECK-NEXT:   %[[RES:.*]] = func.call @foo(%[[ARG1]])
224 // CHECK-NEXT:   scf.yield %[[RES]], %[[C0]]
225 // CHECK:      %[[INDEX_CAST:.*]] = arith.index_castui %[[SWITCH_PAIR]]#1
226 // CHECK-NEXT: scf.index_switch %[[INDEX_CAST]]
227 // CHECK-NEXT: case 0
228 // CHECK-NEXT:   call @bar(%[[SWITCH_PAIR]]#0)
229 // CHECK-NEXT:   scf.yield
230 // CHECK:      default {
231 // CHECK-NEXT: }
232 // CHECK-NEXT: return
234 // -----
236 func.func private @bar(%arg: f32) -> (i1, f32)
238 func.func @already_structured_loop(%arg: f32) -> f32 {
239   cf.br ^bb0
241 ^bb0:
242   %cond, %value = call @bar(%arg) : (f32) -> (i1, f32)
243   cf.cond_br %cond, ^bb1, ^bb0
245 ^bb1:
246   return %value : f32
249 // CHECK-LABEL: @already_structured_loop
250 // CHECK-SAME: %[[ARG:.*]]: f32
251 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
252 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
253 // CHECK-DAG: %[[POISON:.*]] = ub.poison
254 // CHECK-NEXT: %[[RES:.*]] = scf.while (%[[ARG1:.*]] = %[[POISON]])
255 // CHECK-NEXT:   %[[CALL_PAIR:.*]]:2 = func.call @bar(%[[ARG]])
256 // CHECK-NEXT:   %[[IF_PAIR:.*]]:2 = scf.if %[[CALL_PAIR]]#0
257 // CHECK-NEXT:     scf.yield %[[C1]], %[[C0]]
258 // CHECK-NEXT:   else
259 // CHECK-NEXT:     scf.yield %[[C0]], %[[C1]]
260 // CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_PAIR]]#1
261 // CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[CALL_PAIR]]#1
262 // CHECK: return %[[RES]]
264 // -----
266 func.func private @bar(%arg: f32) -> (i1, f32)
268 // This test makes sure that the exit block using an iteration variable works
269 // correctly.
271 func.func @exit_loop_iter_use(%arg: f32) -> f32 {
272   cf.br ^bb0(%arg : f32)
274 ^bb0(%arg1: f32):
275   %cond, %value = call @bar(%arg1) : (f32) -> (i1, f32)
276   cf.cond_br %cond, ^bb1, ^bb0(%value : f32)
278 ^bb1:
279   return %arg1 : f32
282 // CHECK-LABEL: @exit_loop_iter_use
283 // CHECK-SAME: %[[ARG:.*]]:
284 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
285 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
286 // CHECK-DAG: %[[POISON:.*]] = ub.poison
287 // CHECK-NEXT: %[[RES:.*]]:2 = scf.while
288 // CHECK-SAME:   %[[ARG1:.*]] = %[[ARG]]
289 // CHECK-SAME:   %[[ARG2:.*]] = %[[POISON]]
290 // CHECK-NEXT:   %[[CALL_PAIR:.*]]:2 = func.call @bar(%[[ARG1]])
291 // CHECK-NEXT:   %[[IF_RES:.*]]:3 = scf.if %[[CALL_PAIR]]#0
292 // CHECK-NEXT:     scf.yield %[[POISON]], %[[C1]], %[[C0]]
293 // CHECK-NEXT:   else
294 // CHECK-NEXT:     scf.yield %[[CALL_PAIR]]#1, %[[C0]], %[[C1]]
295 // CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_RES]]#2
296 // CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[IF_RES]]#0, %[[ARG1]]
297 // CHECK: return %[[RES]]#1
299 // -----
301 func.func private @bar(%arg: f32) -> f32
303 func.func @infinite_loop(%arg: f32) -> f32 {
304   cf.br ^bb1(%arg: f32)
306 ^bb1(%arg1: f32):
307   %0 = call @bar(%arg1) : (f32) -> f32
308   cf.br ^bb1(%0 : f32)
311 // CHECK-LABEL: @infinite_loop
312 // CHECK-SAME: %[[ARG:.*]]:
313 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
314 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
315 // CHECK-NEXT: scf.while
316 // CHECK-SAME:   %[[ARG1:.*]] = %[[ARG]]
317 // CHECK-NEXT:   %[[CALL:.*]] = func.call @bar(%[[ARG1]])
318 // CHECK-NEXT:   %[[TRUNC:.*]] = arith.trunci %[[C1]]
319 // CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[CALL]]
320 // CHECK: %[[POISON:.*]] = ub.poison
321 // CHECK: return %[[POISON]]
323 // -----
325 func.func @multi_return() -> i32 {
326   %cond = "test.test1"() : () -> i1
327   cf.cond_br %cond, ^bb1, ^bb3
328 ^bb1:
329   %0 = "test.test2"() : () -> i32
330   return %0 : i32
331 ^bb3:
332   %1 = "test.test4"() : () -> i32
333   return %1 : i32
336 // CHECK-LABEL: func @multi_return
337 // CHECK:      %[[COND:.*]] = "test.test1"()
338 // CHECK-NEXT: %[[RES:.*]] = scf.if %[[COND]]
339 // CHECK-NEXT:   %[[VAL2:.*]] = "test.test2"()
340 // CHECK:        scf.yield %[[VAL2]]
341 // CHECK-NEXT: else
342 // CHECK-NEXT:   %[[VAL4:.*]] = "test.test4"()
343 // CHECK:        scf.yield %[[VAL4]]
344 // CHECK:      return %[[RES]]
346 // -----
348 func.func private @bar(%arg: f32) -> f32
350 func.func @conditional_infinite_loop(%arg: f32, %cond: i1) -> f32 {
351   cf.cond_br %cond, ^bb1(%arg: f32), ^bb2
353 ^bb1(%arg1: f32):
354   %0 = call @bar(%arg1) : (f32) -> f32
355   cf.br ^bb1(%0 : f32)
357 ^bb2:
358   return %arg : f32
361 // CHECK-LABEL: @conditional_infinite_loop
362 // CHECK-SAME: %[[ARG0:[[:alnum:]]+]]:
363 // CHECK-SAME: %[[ARG1:[[:alnum:]]+]]:
364 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
365 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
366 // CHECK-NEXT: %[[RES:.*]] = scf.if %[[ARG1]]
367 // CHECK-NEXT:   scf.while
368 // CHECK-SAME:     %[[ARG2:.*]] = %[[ARG0]]
369 // CHECK-NEXT:     %[[CALL:.*]] = func.call @bar(%[[ARG2]])
370 // CHECK-NEXT:     %[[TRUNC:.*]] = arith.trunci %[[C1]]
371 // CHECK-NEXT:     scf.condition(%[[TRUNC]]) %[[CALL]]
372 // CHECK:      else
373 // CHECK:        scf.yield %[[ARG0]]
374 // CHECK:      return %[[RES]]
376 // -----
378 // Different return-like terminators lead one control flow op remaining in the top level region.
379 // Each of the blocks the control flow op leads to are transformed into regions nevertheless.
381 func.func private @bar(%arg: i32)
383 func.func @mixing_return_like(%cond: i1, %cond2: i1, %cond3: i1) {
384   %0 = arith.constant 0 : i32
385   %1 = arith.constant 1 : i32
386   cf.cond_br %cond, ^bb1, ^bb3
388 ^bb1:
389   cf.cond_br %cond2, ^bb2(%0 : i32), ^bb2(%1 : i32)
390 ^bb2(%arg: i32):
391   call @bar(%arg) : (i32) -> ()
392   "test.returnLike"() : () -> ()
394 ^bb3:
395   cf.cond_br %cond3, ^bb4(%1 : i32), ^bb4(%0 : i32)
396 ^bb4(%arg2: i32):
397   call @bar(%arg2) : (i32) -> ()
398   return
401 // CHECK-LABEL: @mixing_return_like
402 // CHECK-SAME: %[[COND1:[[:alnum:]]+]]:
403 // CHECK-SAME: %[[COND2:[[:alnum:]]+]]:
404 // CHECK-SAME: %[[COND3:[[:alnum:]]+]]:
405 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
406 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
407 // CHECK: cf.cond_br %[[COND1]], ^[[BB1:.*]], ^[[BB2:[[:alnum:]]+]]
409 // CHECK: ^[[BB1]]:
410 // CHECK: scf.if
411 // CHECK-NOT: cf.{{(switch|(cond_)?br)}}
412 // CHECK: call @bar
413 // CHECK: "test.returnLike"
415 // CHECK: ^[[BB2]]:
416 // CHECK: scf.if
417 // CHECK-NOT: cf.{{(switch|(cond_)?br)}}
418 // CHECK: call @bar
419 // CHECK: return
421 // -----
423 // cf.switch here only has some successors with different return-like ops.
424 // This test makes sure that if there are at least two successors branching to
425 // the same region, that this region gets properly turned to structured control
426 // flow.
428 func.func @some_successors_with_different_return(%flag: i32) -> i32 {
429   %0 = arith.constant 5 : i32
430   %1 = arith.constant 6 : i32
431   cf.switch %flag : i32, [
432     default: ^bb1,
433     0: ^bb3(%0 : i32),
434     1: ^bb3(%1 : i32)
435   ]
437 ^bb1:
438   "test.returnLike"() : () -> ()
440 ^bb3(%arg: i32):
441   cf.br ^bb3(%arg : i32)
444 // CHECK-LABEL: @some_successors_with_different_return
445 // CHECK-SAME: %[[FLAG:[[:alnum:]]+]]:
446 // CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32
447 // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : i32
448 // CHECK-DAG: %[[POISON:.*]] = ub.poison
449 // CHECK-DAG: %[[C5:.*]] = arith.constant 5 : i32
450 // CHECK-DAG: %[[C6:.*]] = arith.constant 6 : i32
451 // CHECK:      %[[INDEX_CAST:.*]] = arith.index_castui %[[FLAG]]
452 // CHECK-NEXT: %[[INDEX_SWITCH:.*]]:2 = scf.index_switch %[[INDEX_CAST]]
453 // CHECK:      case 0
454 // CHECK-NEXT:   scf.yield %[[C5]], %[[C1]]
455 // CHECK:      case 1
456 // CHECK-NEXT:   scf.yield %[[C6]], %[[C1]]
457 // CHECK:      default
458 // CHECK-NEXT:   scf.yield %[[POISON]], %[[C0]]
459 // CHECK:      cf.switch %[[INDEX_SWITCH]]#1
460 // CHECK-NEXT: default: ^[[BB2:[[:alnum:]]+]]
461 // CHECK-SAME: %[[INDEX_SWITCH]]#0
462 // CHECK-NEXT: 0: ^[[BB1:[[:alnum:]]+]]
463 // CHECK-NEXT: ]
465 // CHECK: ^[[BB2]]{{.*}}:
466 // CHECK: scf.while
467 // CHECK-NOT: cf.{{(switch|(cond_)?br)}}
468 // CHECK: return
470 // CHECK: ^[[BB1]]:
471 // CHECK-NEXT: "test.returnLike"
473 // -----
475 func.func @select_like(%cond: i1) -> i32 {
476   %0 = arith.constant 0 : i32
477   %1 = arith.constant 1 : i32
478   cf.cond_br %cond, ^bb0(%0 : i32), ^bb0(%1 : i32)
479 ^bb0(%arg: i32):
480   return %arg : i32
483 // CHECK-LABEL: func @select_like
484 // CHECK-SAME: %[[COND:.*]]: i1
485 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
486 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
487 // CHECK-NEXT: %[[RES:.*]] = scf.if %[[COND]]
488 // CHECK-NEXT:   scf.yield %[[C0]]
489 // CHECK-NEXT: else
490 // CHECK-NEXT:   scf.yield %[[C1]]
491 // CHECK:      return %[[RES]]
493 // -----
495 func.func @return_like_dominated_by_condition(%cond1: i1, %cond2: i1, %cond3: i1) {
496   cf.cond_br %cond1, ^bb1, ^bb2
498 ^bb1:
499   return
501 ^bb2:
502   cf.cond_br %cond2, ^bb3, ^bb4
504 ^bb3:
505   "test.unreachable"() : () -> ()
507 ^bb4:
508   cf.cond_br %cond3, ^bb3, ^bb5
510 ^bb5:
511   return
514 // CHECK-LABEL: func @return_like_dominated_by_condition
515 // CHECK-SAME: %[[COND1:[[:alnum:]]+]]
516 // CHECK-SAME: %[[COND2:[[:alnum:]]+]]
517 // CHECK-SAME: %[[COND3:[[:alnum:]]+]]
518 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
519 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
520 // CHECK: %[[IF:.*]] = scf.if %[[COND1]]
521 // CHECK-NEXT:   scf.yield
522 // CHECK: else
523 // CHECK:   scf.if %[[COND2]]
524 // CHECK-NEXT:   scf.yield
525 // CHECK:   else
526 // CHECK:      scf.if %[[COND3]]
527 // CHECK-NEXT:    scf.yield
528 // CHECK-NEXT: else
529 // CHECK-NEXT:    scf.yield
531 // CHECK: cf.switch %[[IF]]
532 // CHECK-NEXT: default: ^[[BB1:.*]],
533 // CHECK-NEXT: 0: ^[[BB2:[[:alnum:]]+]]
535 // CHECK: ^[[BB2]]:
536 // CHECK-NEXT: return
538 // CHECK: ^[[BB1]]:
539 // CHECK-NEXT: "test.unreachable"
541 // -----
543 func.func @dominator_issue(%cond: i1, %cond2: i1) -> i32 {
544   cf.cond_br %cond, ^bb1, ^bb2
546 ^bb1:
547   "test.unreachable"() : () -> ()
549 ^bb2:
550   %value = "test.def"() : () -> i32
551   cf.cond_br %cond2, ^bb1, ^bb4
553 ^bb4:
554   return %value : i32
557 // CHECK-LABEL: func @dominator_issue
558 // CHECK-SAME: %[[COND1:[[:alnum:]]+]]
559 // CHECK-SAME: %[[COND2:[[:alnum:]]+]]
560 // CHECK: %[[IF:.*]]:2 = scf.if %[[COND1]]
561 // CHECK: else
562 // CHECK:   %[[VALUE:.*]] = "test.def"
563 // CHECK:   %[[IF_RES:.*]]:2 = scf.if %[[COND2]]
564 // CHECK:   else
565 // CHECK-NEXT: scf.yield %[[VALUE]]
566 // CHECK:   scf.yield %[[IF_RES]]#0
567 // CHECK: cf.switch %[[IF]]#1
568 // CHECK-NEXT: default: ^[[BB2:[[:alnum:]]+]](
569 // CHECK-SAME: %[[IF]]#0
570 // CHECK-NEXT: 0: ^[[BB1:[[:alnum:]]+]]
571 // CHECK: ^[[BB1]]:
572 // CHECK-NEXT: "test.unreachable"
573 // CHECK: ^[[BB2]]
574 // CHECK-SAME: %[[ARG:[[:alnum:]]+]]
575 // CHECK-NEXT: return %[[ARG]]
577 // -----
579 // Test that %value gets properly passed to ^bb4.
581 func.func private @bar(i32)
583 func.func @dominator_issue_loop(%cond: i1, %cond2: i1) -> i32 {
584   %0 = arith.constant 5 : i32
585   cf.br ^bb0
587 ^bb0:
588   cf.cond_br %cond, ^bb1, ^bb3
590 ^bb1:
591   %value = "test.def"() : () -> i32
592   cf.cond_br %cond2, ^bb0, ^bb4
594 ^bb3:
595   return %0 : i32
597 ^bb4:
598   return %value : i32
601 // CHECK-LABEL: func @dominator_issue_loop
602 // CHECK-SAME: %[[COND1:[[:alnum:]]+]]
603 // CHECK-SAME: %[[COND2:[[:alnum:]]+]]
604 // CHECK: %[[WHILE:.*]]:2 = scf.while
605 // CHECK:   %[[IF:.*]]:3 = scf.if %[[COND1]]
606 // CHECK:     %[[DEF:.*]] = "test.def"
607 // CHECK:     %[[IF2:.*]]:3 = scf.if %[[COND2]]
608 // CHECK:       scf.yield
609 // CHECK-SAME:   %[[DEF]]
610 // CHECK:     else
611 // CHECK:       scf.yield %{{.*}}, %{{.*}}, %[[DEF]]
612 // CHECK:     scf.yield %[[IF2]]#0, %[[IF2]]#1, %[[IF2]]#2
613 // CHECK:   scf.condition(%{{.*}}) %[[IF]]#2, %[[IF]]#0
615 // CHECK: %[[SWITCH:.*]] = scf.index_switch
616 // CHECK:   scf.yield %[[WHILE]]#0
617 // CHECK: return %[[SWITCH]]
619 // -----
621 // Multi entry loops generally produce code in dire need of canonicalization.
623 func.func private @comp1(%arg: i32) -> i1
624 func.func private @comp2(%arg: i32) -> i1
625 func.func private @foo(%arg: i32)
627 func.func @multi_entry_loop(%cond: i1) {
628   %0 = arith.constant 6 : i32
629   %1 = arith.constant 5 : i32
630   cf.cond_br %cond, ^bb0, ^bb1
632 ^bb0:
633   %exit = call @comp1(%0) : (i32) -> i1
634   cf.cond_br %exit, ^bb2(%0 : i32), ^bb1
636 ^bb1:
637   %exit2 = call @comp2(%1) : (i32) -> i1
638   cf.cond_br %exit2, ^bb2(%1 : i32), ^bb0
640 ^bb2(%arg3 : i32):
641   call @foo(%arg3) : (i32) -> ()
642   return
645 // CHECK-LABEL: func @multi_entry_loop
646 // CHECK-SAME: %[[ARG0:[[:alnum:]]+]]
647 // CHECK-DAG: %[[C0:.*]] = arith.constant 0
648 // CHECK-DAG: %[[UB:.*]] = ub.poison
649 // CHECK-DAG: %[[C1:.*]] = arith.constant 1
650 // CHECK-DAG: %[[C6:.*]] = arith.constant 6
651 // CHECK-DAG: %[[C5:.*]] = arith.constant 5
652 // CHECK:      %[[IF:.*]]:{{.*}} = scf.if %[[ARG0]]
653 // CHECK-NEXT:   scf.yield %[[C1]], %[[UB]]
654 // CHECK-NEXT: else
655 // CHECK-NEXT:   scf.yield %[[C0]], %[[UB]]
656 // CHECK:      %[[WHILE:.*]]:{{.*}} = scf.while
657 // CHECK-SAME: %[[ARG1:.*]] = %[[IF]]#0
658 // CHECK-SAME: %[[ARG2:.*]] = %[[IF]]#1
659 // CHECK-NEXT:   %[[FLAG:.*]] = arith.index_castui %[[ARG1]]
660 // CHECK-NEXT:   %[[SWITCH:.*]]:{{.*}} = scf.index_switch %[[FLAG]]
661 // CHECK-NEXT:   case 0
662 // CHECK-NEXT:     %[[EXIT:.*]] = func.call @comp2(%[[C5]])
663 // CHECK-NEXT:     %[[IF_RES:.*]]:{{.*}} = scf.if %[[EXIT]]
664 // CHECK-NEXT:       scf.yield %[[UB]], %[[C5]], %[[C1]], %[[C0]]
665 // CHECK-NEXT:     else
666 // CHECK-NEXT:       scf.yield %[[C1]], %[[UB]], %[[C0]], %[[C1]]
667 // CHECK:          scf.yield %[[IF_RES]]#0, %[[IF_RES]]#1, %[[IF_RES]]#2, %[[IF_RES]]#3
668 // CHECK:        default
669 // CHECK-NEXT:     %[[EXIT:.*]] = func.call @comp1(%[[C6]])
670 // CHECK-NEXT:     %[[IF_RES:.*]]:{{.*}} = scf.if %[[EXIT]]
671 // CHECK-NEXT:       scf.yield %[[UB]], %[[C6]], %[[C1]], %[[C0]]
672 // CHECK-NEXT:     else
673 // CHECK-NEXT:       scf.yield %[[C0]], %[[UB]], %[[C0]], %[[C1]]
674 // CHECK:          scf.yield %[[IF_RES]]#0, %[[IF_RES]]#1, %[[IF_RES]]#2, %[[IF_RES]]#3
675 // CHECK:        %[[COND:.*]] = arith.trunci %[[SWITCH]]#3
676 // CHECK-NEXT:   scf.condition(%[[COND]]) %[[SWITCH]]#0, %[[SWITCH]]#1
677 // CHECK:      do
678 // CHECK:        scf.yield
679 // CHECK:      call @foo(%[[WHILE]]#1)
680 // CHECK-NEXT: return
682 // -----
684 func.func @nested_region() {
685   scf.execute_region {
686     %cond = "test.test1"() : () -> i1
687     cf.cond_br %cond, ^bb1, ^bb2
688   ^bb1:
689     "test.test2"() : () -> ()
690     cf.br ^bb3
691   ^bb2:
692     "test.test3"() : () -> ()
693     cf.br ^bb3
694   ^bb3:
695     "test.test4"() : () -> ()
696     scf.yield
697   }
698   return
701 // CHECK-LABEL: func @nested_region
702 // CHECK:      scf.execute_region {
703 // CHECK:      %[[COND:.*]] = "test.test1"()
704 // CHECK-NEXT: scf.if %[[COND]]
705 // CHECK-NEXT:   "test.test2"()
706 // CHECK-NEXT: else
707 // CHECK-NEXT:   "test.test3"()
708 // CHECK-NEXT: }
709 // CHECK-NEXT: "test.test4"()
710 // CHECK-NEXT: scf.yield
711 // CHECK-NEXT: }
712 // CHECK-NEXT: return
714 // -----
716 func.func @nested_region_inside_loop_use() {
717   cf.br ^bb1
719 ^bb1:
720   %3 = "test.test1"() : () -> i32
721   scf.execute_region {
722     "test.foo"(%3) : (i32) -> ()
723     scf.yield
724   }
725   cf.br ^bb1
728 // CHECK-LABEL: func @nested_region_inside_loop_use
729 // CHECK: scf.while
730 // CHECK-NEXT: %[[DEF:.*]] = "test.test1"()
731 // CHECK-NEXT: scf.execute_region
732 // CHECK-NEXT: "test.foo"(%[[DEF]])
734 // -----
736 func.func @nested_region_outside_loop_use() {
737   cf.br ^bb1
739 ^bb1:
740   %3 = "test.test1"() : () -> i32
741   %cond = "test.test2"() : () -> i1
742   cf.cond_br %cond, ^bb1, ^bb2
744 ^bb2:
745   scf.execute_region {
746     "test.foo"(%3) : (i32) -> ()
747     scf.yield
748   }
749   return
752 // CHECK-LABEL: func @nested_region_outside_loop_use
753 // CHECK: %[[RES:.*]] = scf.while
754 // CHECK: %[[DEF:.*]] = "test.test1"()
755 // CHECK: scf.condition(%{{.*}}) %[[DEF]]
757 // CHECK: scf.execute_region
758 // CHECK-NEXT: "test.foo"(%[[RES]])