1 ; Checks whether dead loops with multiple exits can be eliminated. 2 ; Note that we loop simplify and LCSSA over the test cases to make sure the 3 ; critical components remain after those passes and are visible to the loop 4 ; deletion pass. 5 ; 6 ; RUN: opt < %s -loop-simplify -lcssa -S | FileCheck %s --check-prefixes=CHECK,BEFORE 7 ; RUN: opt < %s -loop-deletion -S | FileCheck %s --check-prefixes=CHECK,AFTER 8 ; 9 ; RUN: opt < %s -passes=no-op-loop -S | FileCheck %s --check-prefixes=CHECK,BEFORE 10 ; RUN: opt < %s -passes=loop-deletion -S | FileCheck %s --check-prefixes=CHECK,AFTER 11 12 13 define void @foo(i64 %n, i64 %m) nounwind { 14 ; CHECK-LABEL: @foo( 15 16 entry: 17 br label %bb 18 ; CHECK: entry: 19 ; BEFORE-NEXT: br label %bb 20 ; AFTER-NEXT: br label %return 21 22 bb: 23 %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb2 ] 24 %t0 = add i64 %x.0, 1 25 %t1 = icmp slt i64 %x.0, %n 26 br i1 %t1, label %bb2, label %return 27 ; BEFORE: bb: 28 ; BEFORE: br i1 {{.*}}, label %bb2, label %return 29 ; AFTER-NOT: bb: 30 ; AFTER-NOT: br 31 32 bb2: 33 %t2 = icmp slt i64 %x.0, %m 34 br i1 %t1, label %bb, label %return 35 ; BEFORE: bb2: 36 ; BEFORE: br i1 {{.*}}, label %bb, label %return 37 ; AFTER-NOT: bb2: 38 ; AFTER-NOT: br 39 40 return: 41 ret void 42 ; CHECK: return: 43 ; CHECK-NEXT: ret void 44 } 45 46 define i64 @bar(i64 %n, i64 %m, i64 %maybe_zero) nounwind { 47 ; CHECK-LABEL: @bar( 48 49 entry: 50 br label %bb 51 ; CHECK: entry: 52 ; BEFORE-NEXT: br label %bb 53 ; AFTER-NEXT: br label %return 54 55 bb: 56 %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb3 ] 57 %t0 = add i64 %x.0, 1 58 %t1 = icmp slt i64 %x.0, %n 59 br i1 %t1, label %bb2, label %return 60 ; BEFORE: bb: 61 ; BEFORE: br i1 {{.*}}, label %bb2, label %return 62 ; AFTER-NOT: bb: 63 ; AFTER-NOT: br 64 65 bb2: 66 %t2 = icmp slt i64 %x.0, %m 67 ; This unused division prevents unifying this loop exit path with others 68 ; because it can be deleted but cannot be hoisted. 69 %unused1 = udiv i64 42, %maybe_zero 70 br i1 %t2, label %bb3, label %return 71 ; BEFORE: bb2: 72 ; BEFORE: br i1 {{.*}}, label %bb3, label %return 73 ; AFTER-NOT: bb2: 74 ; AFTER-NOT: br 75 76 bb3: 77 %t3 = icmp slt i64 %x.0, %m 78 ; This unused division prevents unifying this loop exit path with others 79 ; because it can be deleted but cannot be hoisted. 80 %unused2 = sdiv i64 42, %maybe_zero 81 br i1 %t3, label %bb, label %return 82 ; BEFORE: bb3: 83 ; BEFORE: br i1 {{.*}}, label %bb, label %return 84 ; AFTER-NOT: bb3: 85 ; AFTER-NOT: br 86 87 return: 88 %x.lcssa = phi i64 [ 10, %bb ], [ 10, %bb2 ], [ 10, %bb3 ] 89 ret i64 %x.lcssa 90 ; CHECK: return: 91 ; BEFORE-NEXT: %[[X:.*]] = phi i64 [ 10, %bb ], [ 10, %bb2 ], [ 10, %bb3 ] 92 ; AFTER-NEXT: %[[X:.*]] = phi i64 [ 10, %entry ] 93 ; CHECK-NEXT: ret i64 %[[X]] 94 } 95 96 ; This function has a loop which looks like @bar's but that cannot be deleted 97 ; because which path we exit through determines which value is selected. 98 define i64 @baz(i64 %n, i64 %m, i64 %maybe_zero) nounwind { 99 ; CHECK-LABEL: @baz( 100 101 entry: 102 br label %bb 103 ; CHECK: entry: 104 ; CHECK-NEXT: br label %bb 105 106 bb: 107 %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb3 ] 108 %t0 = add i64 %x.0, 1 109 %t1 = icmp slt i64 %x.0, %n 110 br i1 %t1, label %bb2, label %return 111 ; CHECK: bb: 112 ; CHECK: br i1 {{.*}}, label %bb2, label %return 113 114 bb2: 115 %t2 = icmp slt i64 %x.0, %m 116 ; This unused division prevents unifying this loop exit path with others 117 ; because it can be deleted but cannot be hoisted. 118 %unused1 = udiv i64 42, %maybe_zero 119 br i1 %t2, label %bb3, label %return 120 ; CHECK: bb2: 121 ; CHECK: br i1 {{.*}}, label %bb3, label %return 122 123 bb3: 124 %t3 = icmp slt i64 %x.0, %m 125 ; This unused division prevents unifying this loop exit path with others 126 ; because it can be deleted but cannot be hoisted. 127 %unused2 = sdiv i64 42, %maybe_zero 128 br i1 %t3, label %bb, label %return 129 ; CHECK: bb3: 130 ; CHECK: br i1 {{.*}}, label %bb, label %return 131 132 return: 133 %x.lcssa = phi i64 [ 12, %bb ], [ 10, %bb2 ], [ 10, %bb3 ] 134 ret i64 %x.lcssa 135 ; CHECK: return: 136 ; CHECK-NEXT: %[[X:.*]] = phi i64 [ 12, %bb ], [ 10, %bb2 ], [ 10, %bb3 ] 137 ; CHECK-NEXT: ret i64 %[[X]] 138 } 139