• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
13define void @foo(i64 %n, i64 %m) nounwind {
14; CHECK-LABEL: @foo(
15
16entry:
17  br label %bb
18; CHECK:       entry:
19; BEFORE-NEXT:   br label %bb
20; AFTER-NEXT:    br label %return
21
22bb:
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
32bb2:
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
40return:
41  ret void
42; CHECK:       return:
43; CHECK-NEXT:    ret void
44}
45
46define i64 @bar(i64 %n, i64 %m, i64 %maybe_zero) nounwind {
47; CHECK-LABEL: @bar(
48
49entry:
50  br label %bb
51; CHECK:       entry:
52; BEFORE-NEXT:   br label %bb
53; AFTER-NEXT:    br label %return
54
55bb:
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
65bb2:
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
76bb3:
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
87return:
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.
98define i64 @baz(i64 %n, i64 %m, i64 %maybe_zero) nounwind {
99; CHECK-LABEL:  @baz(
100
101entry:
102  br label %bb
103; CHECK:       entry:
104; CHECK-NEXT:    br label %bb
105
106bb:
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
114bb2:
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
123bb3:
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
132return:
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