// RUN: mlir-opt %s --mlir-disable-threading -test-block-is-in-loop 2>&1 | FileCheck %s
module {
// Test function with only one bb
func.func @simple() {
func.return
}
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb0:
// Test simple loop bb0 -> bb0
func.func @loopForever() {
^bb0:
cf.br ^bb1
^bb1:
cf.br ^bb1
}
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb0:
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb1:
// Test bb0 -> bb1 -> bb2 -> bb1
func.func @loopForever2() {
^bb0:
cf.br ^bb1
^bb1:
cf.br ^bb2
^bb2:
cf.br ^bb1
}
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb0:
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb1:
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb2:
// Test conditional branch without loop
// bb0 -> bb1 -> {bb2, bb3}
func.func @noLoop(%arg0: i1) {
cf.br ^bb1
^bb1:
cf.cond_br %arg0, ^bb2, ^bb3
^bb2:
func.return
^bb3:
func.return
}
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb0(%arg0: i1)
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb1:
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb2:
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb3:
// test multiple loops
// bb0 -> bb1 -> bb2 -> bb3 { -> bb2} -> bb4 { -> bb1 } -> bb5
func.func @multipleLoops(%arg0: i1, %arg1: i1) {
cf.br ^bb1
^bb1:
cf.br ^bb2
^bb2:
cf.br ^bb3
^bb3:
cf.cond_br %arg0, ^bb4, ^bb2
^bb4:
cf.cond_br %arg1, ^bb1, ^bb5
^bb5:
return
}
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb0(%arg0: i1, %arg1: i1)
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb1:
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb2:
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb3:
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb4:
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb5:
// test derived from real Flang output
func.func @_QPblockTest0(%arg0: i1, %arg1: i1) {
cf.br ^bb1
^bb1: // 2 preds: ^bb0, ^bb4
cf.cond_br %arg0, ^bb2, ^bb5
^bb2: // pred: ^bb1
cf.cond_br %arg1, ^bb3, ^bb4
^bb3: // pred: ^bb2
return
^bb4: // pred: ^bb2
cf.br ^bb1
^bb5: // pred: ^bb1
return
}
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb0(%arg0: i1, %arg1: i1)
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb1:
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb2:
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb3:
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb4:
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb5:
// check nested blocks
func.func @check_alloc_in_loop(%counter : i64) {
cf.br ^bb1(%counter: i64)
^bb1(%lv : i64):
%cm1 = arith.constant -1 : i64
%rem = arith.addi %lv, %cm1 : i64
%zero = arith.constant 0 : i64
%p = arith.cmpi eq, %rem, %zero : i64
cf.cond_br %p, ^bb3, ^bb2
^bb2:
scf.execute_region -> () {
%c1 = arith.constant 1 : i64
scf.yield
}
cf.br ^bb1(%rem: i64)
^bb3:
return
}
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb0(%arg0: i64):
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb1(%0: i64)
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb0:
// CHECK-NEXT: %c1_i64
// CHECK: Block is in a loop
// CHECK-NEXT: ^bb2:
// CHECK: Block is not in a loop
// CHECK-NEXT: ^bb3:
}