]> granicus.if.org Git - llvm/blob
afea0e6
[llvm] /
1 ; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
2
3 ; Check that IRCE is able to deal with loops where the latch comparison is
4 ; done against current value of the IV, not the IV.next.
5
6 ; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
7 ; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
8 ; CHECK-NOT: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
9 ; CHECK-NOT: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
10
11 ; SLT condition for increasing loop from 0 to 100.
12 define void @test_01(i32* %arr, i32* %a_len_ptr) #0 {
13
14 ; CHECK:      test_01
15 ; CHECK:        entry:
16 ; CHECK-NEXT:     %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
17 ; CHECK-NEXT:     [[COND2:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
18 ; CHECK-NEXT:     br i1 [[COND2]], label %loop.preheader, label %main.pseudo.exit
19 ; CHECK:        loop:
20 ; CHECK-NEXT:     %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
21 ; CHECK-NEXT:     %idx.next = add nuw nsw i32 %idx, 1
22 ; CHECK-NEXT:     %abc = icmp slt i32 %idx, %exit.mainloop.at
23 ; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
24 ; CHECK:        in.bounds:
25 ; CHECK-NEXT:     %addr = getelementptr i32, i32* %arr, i32 %idx
26 ; CHECK-NEXT:     store i32 0, i32* %addr
27 ; CHECK-NEXT:     %next = icmp slt i32 %idx, 100
28 ; CHECK-NEXT:     [[COND3:%[^ ]+]] = icmp slt i32 %idx, %exit.mainloop.at
29 ; CHECK-NEXT:     br i1 [[COND3]], label %loop, label %main.exit.selector
30 ; CHECK:        main.exit.selector:
31 ; CHECK-NEXT:     %idx.lcssa = phi i32 [ %idx, %in.bounds ]
32 ; CHECK-NEXT:     [[COND4:%[^ ]+]] = icmp slt i32 %idx.lcssa, 100
33 ; CHECK-NEXT:     br i1 [[COND4]], label %main.pseudo.exit, label %exit
34 ; CHECK-NOT: loop.preloop:
35 ; CHECK:        loop.postloop:
36 ; CHECK-NEXT:    %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
37 ; CHECK-NEXT:     %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
38 ; CHECK-NEXT:     %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
39 ; CHECK-NEXT:     br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
40
41 entry:
42   %len = load i32, i32* %a_len_ptr, !range !0
43   br label %loop
44
45 loop:
46   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
47   %idx.next = add nsw nuw i32 %idx, 1
48   %abc = icmp slt i32 %idx, %len
49   br i1 %abc, label %in.bounds, label %out.of.bounds
50
51 in.bounds:
52   %addr = getelementptr i32, i32* %arr, i32 %idx
53   store i32 0, i32* %addr
54   %next = icmp slt i32 %idx, 100
55   br i1 %next, label %loop, label %exit
56
57 out.of.bounds:
58   ret void
59
60 exit:
61   ret void
62 }
63
64 ; ULT condition for increasing loop from 0 to 100.
65 define void @test_02(i32* %arr, i32* %a_len_ptr) #0 {
66
67 ; CHECK:      test_02
68 ; CHECK:        entry:
69 ; CHECK-NEXT:     %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
70 ; CHECK-NEXT:     [[COND2:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
71 ; CHECK-NEXT:     br i1 [[COND2]], label %loop.preheader, label %main.pseudo.exit
72 ; CHECK:        loop:
73 ; CHECK-NEXT:     %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
74 ; CHECK-NEXT:     %idx.next = add nuw nsw i32 %idx, 1
75 ; CHECK-NEXT:     %abc = icmp ult i32 %idx, %exit.mainloop.at
76 ; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
77 ; CHECK:        in.bounds:
78 ; CHECK-NEXT:     %addr = getelementptr i32, i32* %arr, i32 %idx
79 ; CHECK-NEXT:     store i32 0, i32* %addr
80 ; CHECK-NEXT:     %next = icmp ult i32 %idx, 100
81 ; CHECK-NEXT:     [[COND3:%[^ ]+]] = icmp ult i32 %idx, %exit.mainloop.at
82 ; CHECK-NEXT:     br i1 [[COND3]], label %loop, label %main.exit.selector
83 ; CHECK:        main.exit.selector:
84 ; CHECK-NEXT:     %idx.lcssa = phi i32 [ %idx, %in.bounds ]
85 ; CHECK-NEXT:     [[COND4:%[^ ]+]] = icmp ult i32 %idx.lcssa, 100
86 ; CHECK-NEXT:     br i1 [[COND4]], label %main.pseudo.exit, label %exit
87 ; CHECK-NOT: loop.preloop:
88 ; CHECK:        loop.postloop:
89 ; CHECK-NEXT:    %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
90 ; CHECK-NEXT:     %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
91 ; CHECK-NEXT:     %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
92 ; CHECK-NEXT:     br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
93
94 entry:
95   %len = load i32, i32* %a_len_ptr, !range !0
96   br label %loop
97
98 loop:
99   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
100   %idx.next = add nsw nuw i32 %idx, 1
101   %abc = icmp ult i32 %idx, %len
102   br i1 %abc, label %in.bounds, label %out.of.bounds
103
104 in.bounds:
105   %addr = getelementptr i32, i32* %arr, i32 %idx
106   store i32 0, i32* %addr
107   %next = icmp ult i32 %idx, 100
108   br i1 %next, label %loop, label %exit
109
110 out.of.bounds:
111   ret void
112
113 exit:
114   ret void
115 }
116
117 ; Same as test_01, but comparison happens against IV extended to a wider type.
118 ; This test ensures that IRCE rejects it and does not falsely assume that it was
119 ; a comparison against iv.next.
120 ; TODO: We can actually extend the recognition to cover this case.
121 define void @test_03(i32* %arr, i64* %a_len_ptr) #0 {
122
123 ; CHECK:      test_03
124
125 entry:
126   %len = load i64, i64* %a_len_ptr, !range !1
127   br label %loop
128
129 loop:
130   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
131   %idx.next = add nsw nuw i32 %idx, 1
132   %idx.ext = sext i32 %idx to i64
133   %abc = icmp slt i64 %idx.ext, %len
134   br i1 %abc, label %in.bounds, label %out.of.bounds
135
136 in.bounds:
137   %addr = getelementptr i32, i32* %arr, i32 %idx
138   store i32 0, i32* %addr
139   %next = icmp slt i32 %idx, 100
140   br i1 %next, label %loop, label %exit
141
142 out.of.bounds:
143   ret void
144
145 exit:
146   ret void
147 }
148
149 ; Same as test_02, but comparison happens against IV extended to a wider type.
150 ; This test ensures that IRCE rejects it and does not falsely assume that it was
151 ; a comparison against iv.next.
152 ; TODO: We can actually extend the recognition to cover this case.
153 define void @test_04(i32* %arr, i64* %a_len_ptr) #0 {
154
155 ; CHECK:      test_04
156
157 entry:
158   %len = load i64, i64* %a_len_ptr, !range !1
159   br label %loop
160
161 loop:
162   %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
163   %idx.next = add nsw nuw i32 %idx, 1
164   %idx.ext = sext i32 %idx to i64
165   %abc = icmp ult i64 %idx.ext, %len
166   br i1 %abc, label %in.bounds, label %out.of.bounds
167
168 in.bounds:
169   %addr = getelementptr i32, i32* %arr, i32 %idx
170   store i32 0, i32* %addr
171   %next = icmp ult i32 %idx, 100
172   br i1 %next, label %loop, label %exit
173
174 out.of.bounds:
175   ret void
176
177 exit:
178   ret void
179 }
180
181 !0 = !{i32 0, i32 50}
182 !1 = !{i64 0, i64 50}