xref: /llvm-project/mlir/test/Interfaces/LoopLikeInterface/test-block-loop.mlir (revision 81a79ee446fe499e217144ae1cd505ede9021712)
1// RUN: mlir-opt %s --mlir-disable-threading -test-block-is-in-loop 2>&1 | FileCheck %s
2
3module {
4  // Test function with only one bb
5  func.func @simple() {
6    func.return
7  }
8// CHECK: Block is not in a loop
9// CHECK-NEXT: ^bb0:
10
11  // Test simple loop bb0 -> bb0
12  func.func @loopForever() {
13  ^bb0:
14    cf.br ^bb1
15  ^bb1:
16    cf.br ^bb1
17  }
18// CHECK: Block is not in a loop
19// CHECK-NEXT: ^bb0:
20// CHECK: Block is in a loop
21// CHECK-NEXT: ^bb1:
22
23  // Test bb0 -> bb1 -> bb2 -> bb1
24  func.func @loopForever2() {
25  ^bb0:
26    cf.br ^bb1
27  ^bb1:
28    cf.br ^bb2
29  ^bb2:
30    cf.br ^bb1
31  }
32// CHECK: Block is not in a loop
33// CHECK-NEXT: ^bb0:
34// CHECK: Block is in a loop
35// CHECK-NEXT: ^bb1:
36// CHECK: Block is in a loop
37// CHECK-NEXT: ^bb2:
38
39  // Test conditional branch without loop
40  // bb0 -> bb1 -> {bb2, bb3}
41  func.func @noLoop(%arg0: i1) {
42    cf.br ^bb1
43  ^bb1:
44    cf.cond_br %arg0, ^bb2, ^bb3
45  ^bb2:
46    func.return
47  ^bb3:
48    func.return
49  }
50// CHECK: Block is not in a loop
51// CHECK-NEXT: ^bb0(%arg0: i1)
52// CHECK: Block is not in a loop
53// CHECK-NEXT: ^bb1:
54// CHECK: Block is not in a loop
55// CHECK-NEXT: ^bb2:
56// CHECK: Block is not in a loop
57// CHECK-NEXT: ^bb3:
58
59  // test multiple loops
60  // bb0 -> bb1 -> bb2 -> bb3 { -> bb2} -> bb4 { -> bb1 } -> bb5
61  func.func @multipleLoops(%arg0: i1, %arg1: i1) {
62    cf.br ^bb1
63  ^bb1:
64    cf.br ^bb2
65  ^bb2:
66    cf.br ^bb3
67  ^bb3:
68    cf.cond_br %arg0, ^bb4, ^bb2
69  ^bb4:
70    cf.cond_br %arg1, ^bb1, ^bb5
71  ^bb5:
72    return
73  }
74// CHECK: Block is not in a loop
75// CHECK-NEXT: ^bb0(%arg0: i1, %arg1: i1)
76// CHECK: Block is in a loop
77// CHECK-NEXT: ^bb1:
78// CHECK: Block is in a loop
79// CHECK-NEXT: ^bb2:
80// CHECK: Block is in a loop
81// CHECK-NEXT: ^bb3:
82// CHECK: Block is in a loop
83// CHECK-NEXT: ^bb4:
84// CHECK: Block is not in a loop
85// CHECK-NEXT: ^bb5:
86
87  // test derived from real Flang output
88  func.func @_QPblockTest0(%arg0: i1, %arg1: i1) {
89    cf.br ^bb1
90  ^bb1:  // 2 preds: ^bb0, ^bb4
91    cf.cond_br %arg0, ^bb2, ^bb5
92  ^bb2:  // pred: ^bb1
93    cf.cond_br %arg1, ^bb3, ^bb4
94  ^bb3:  // pred: ^bb2
95    return
96  ^bb4:  // pred: ^bb2
97    cf.br ^bb1
98  ^bb5:  // pred: ^bb1
99    return
100  }
101// CHECK: Block is not in a loop
102// CHECK-NEXT: ^bb0(%arg0: i1, %arg1: i1)
103// CHECK: Block is in a loop
104// CHECK-NEXT: ^bb1:
105// CHECK: Block is in a loop
106// CHECK-NEXT: ^bb2:
107// CHECK: Block is not in a loop
108// CHECK-NEXT: ^bb3:
109// CHECK: Block is in a loop
110// CHECK-NEXT: ^bb4:
111// CHECK: Block is not in a loop
112// CHECK-NEXT: ^bb5:
113
114// check nested blocks
115  func.func @check_alloc_in_loop(%counter : i64) {
116    cf.br ^bb1(%counter: i64)
117    ^bb1(%lv : i64):
118      %cm1 = arith.constant -1 : i64
119      %rem = arith.addi %lv, %cm1 : i64
120      %zero = arith.constant 0 : i64
121      %p = arith.cmpi eq, %rem, %zero : i64
122      cf.cond_br %p, ^bb3, ^bb2
123    ^bb2:
124      scf.execute_region -> () {
125        %c1 = arith.constant 1 : i64
126        scf.yield
127      }
128      cf.br ^bb1(%rem: i64)
129    ^bb3:
130      return
131  }
132// CHECK: Block is not in a loop
133// CHECK-NEXT: ^bb0(%arg0: i64):
134// CHECK: Block is in a loop
135// CHECK-NEXT: ^bb1(%0: i64)
136// CHECK: Block is in a loop
137// CHECK-NEXT: ^bb0:
138// CHECK-NEXT: %c1_i64
139// CHECK: Block is in a loop
140// CHECK-NEXT: ^bb2:
141// CHECK: Block is not in a loop
142// CHECK-NEXT: ^bb3:
143}
144