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