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