xref: /llvm-project/llvm/test/Transforms/LoopDeletion/multiple-exits.ll (revision 3528e63d89305907b3d6e0f59f7b03b94a12dacc)
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