| // RUN: mlir-opt %s -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: | |
| } |