blob: d859eb28e78d59d33473b14fdd82a77b6dc1b62d [file] [log] [blame]
Artur Pilipenkof2d5dc52016-10-19 18:59:03 +00001; RUN: opt < %s -indvars -indvars-post-increment-ranges -S | FileCheck %s
2
3target datalayout = "p:64:64:64-n32:64"
4
5; When the IV in this loop is widened we want to widen this use as well:
6; icmp slt i32 %i.inc, %limit
7; In order to do this indvars need to prove that the narrow IV def (%i.inc)
8; is not-negative from the range check inside of the loop.
9define void @test(i32* %base, i32 %limit, i32 %start) {
10; CHECK-LABEL: @test(
11; CHECK-NOT: trunc
12
13for.body.lr.ph:
14 br label %for.body
15
16for.body:
17 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
18 %within_limits = icmp ult i32 %i, 64
19 br i1 %within_limits, label %continue, label %for.end
20
21continue:
22 %i.i64 = zext i32 %i to i64
23 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
24 %val = load i32, i32* %arrayidx, align 4
25 br label %for.inc
26
27for.inc:
28 %i.inc = add nsw nuw i32 %i, 1
29 %cmp = icmp slt i32 %i.inc, %limit
30 br i1 %cmp, label %for.body, label %for.end
31
32for.end:
33 br label %exit
34
35exit:
36 ret void
37}
38
39define void @test_false_edge(i32* %base, i32 %limit, i32 %start) {
40; CHECK-LABEL: @test_false_edge(
41; CHECK-NOT: trunc
42
43for.body.lr.ph:
44 br label %for.body
45
46for.body:
47 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
48 %out_of_bounds = icmp ugt i32 %i, 64
49 br i1 %out_of_bounds, label %for.end, label %continue
50
51continue:
52 %i.i64 = zext i32 %i to i64
53 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
54 %val = load i32, i32* %arrayidx, align 4
55 br label %for.inc
56
57for.inc:
58 %i.inc = add nsw nuw i32 %i, 1
59 %cmp = icmp slt i32 %i.inc, %limit
60 br i1 %cmp, label %for.body, label %for.end
61
62for.end:
63 br label %exit
64
65exit:
66 ret void
67}
68
69define void @test_range_metadata(i32* %array_length_ptr, i32* %base,
70 i32 %limit, i32 %start) {
71; CHECK-LABEL: @test_range_metadata(
72; CHECK-NOT: trunc
73
74for.body.lr.ph:
75 br label %for.body
76
77for.body:
78 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
79 %array_length = load i32, i32* %array_length_ptr, !range !{i32 0, i32 64 }
80 %within_limits = icmp ult i32 %i, %array_length
81 br i1 %within_limits, label %continue, label %for.end
82
83continue:
84 %i.i64 = zext i32 %i to i64
85 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
86 %val = load i32, i32* %arrayidx, align 4
87 br label %for.inc
88
89for.inc:
90 %i.inc = add nsw nuw i32 %i, 1
91 %cmp = icmp slt i32 %i.inc, %limit
92 br i1 %cmp, label %for.body, label %for.end
93
94for.end:
95 br label %exit
96
97exit:
98 ret void
99}
100
101; Negative version of the test above, we don't know anything about
102; array_length_ptr range.
103define void @test_neg(i32* %array_length_ptr, i32* %base,
104 i32 %limit, i32 %start) {
105; CHECK-LABEL: @test_neg(
106; CHECK: trunc i64
107
108for.body.lr.ph:
109 br label %for.body
110
111for.body:
112 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
113 %array_length = load i32, i32* %array_length_ptr
114 %within_limits = icmp ult i32 %i, %array_length
115 br i1 %within_limits, label %continue, label %for.end
116
117continue:
118 %i.i64 = zext i32 %i to i64
119 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
120 %val = load i32, i32* %arrayidx, align 4
121 br label %for.inc
122
123for.inc:
124 %i.inc = add nsw nuw i32 %i, 1
125 %cmp = icmp slt i32 %i.inc, %limit
126 br i1 %cmp, label %for.body, label %for.end
127
128for.end:
129 br label %exit
130
131exit:
132 ret void
133}
134
135define void @test_transitive_use(i32* %base, i32 %limit, i32 %start) {
136; CHECK-LABEL: @test_transitive_use(
137; CHECK-NOT: trunc
138; CHECK: %result = icmp slt i64
139
140for.body.lr.ph:
141 br label %for.body
142
143for.body:
144 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
145 %within_limits = icmp ult i32 %i, 64
146 br i1 %within_limits, label %continue, label %for.end
147
148continue:
149 %i.mul.3 = mul nsw nuw i32 %i, 3
150 %mul_within = icmp ult i32 %i.mul.3, 64
151 br i1 %mul_within, label %guarded, label %continue.2
152
153guarded:
154 %i.mul.3.inc = add nsw nuw i32 %i.mul.3, 1
155 %result = icmp slt i32 %i.mul.3.inc, %limit
156 br i1 %result, label %continue.2, label %for.end
157
158continue.2:
159 %i.i64 = zext i32 %i to i64
160 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
161 %val = load i32, i32* %arrayidx, align 4
162 br label %for.inc
163
164for.inc:
165 %i.inc = add nsw nuw i32 %i, 1
166 %cmp = icmp slt i32 %i.inc, %limit
167 br i1 %cmp, label %for.body, label %for.end
168
169
170for.end:
171 br label %exit
172
173exit:
174 ret void
175}
Artur Pilipenko5c6ef752016-10-19 19:43:54 +0000176
177declare void @llvm.experimental.guard(i1, ...)
178
179define void @test_guard_one_bb(i32* %base, i32 %limit, i32 %start) {
180; CHECK-LABEL: @test_guard_one_bb(
181; CHECK-NOT: trunc
182; CHECK-NOT: icmp slt i32
183
184for.body.lr.ph:
185 br label %for.body
186
187for.body:
188 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
189 %within_limits = icmp ult i32 %i, 64
190 %i.i64 = zext i32 %i to i64
191 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
192 %val = load i32, i32* %arrayidx, align 4
193 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
194 %i.inc = add nsw nuw i32 %i, 1
195 %cmp = icmp slt i32 %i.inc, %limit
196 br i1 %cmp, label %for.body, label %for.end
197
198for.end:
199 br label %exit
200
201exit:
202 ret void
203}
204
205define void @test_guard_in_the_same_bb(i32* %base, i32 %limit, i32 %start) {
206; CHECK-LABEL: @test_guard_in_the_same_bb(
207; CHECK-NOT: trunc
208; CHECK-NOT: icmp slt i32
209
210for.body.lr.ph:
211 br label %for.body
212
213for.body:
214 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
215 %within_limits = icmp ult i32 %i, 64
216 %i.i64 = zext i32 %i to i64
217 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
218 %val = load i32, i32* %arrayidx, align 4
219 br label %for.inc
220
221for.inc:
222 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
223 %i.inc = add nsw nuw i32 %i, 1
224 %cmp = icmp slt i32 %i.inc, %limit
225 br i1 %cmp, label %for.body, label %for.end
226
227for.end:
228 br label %exit
229
230exit:
231 ret void
232}
233
234define void @test_guard_in_idom(i32* %base, i32 %limit, i32 %start) {
235; CHECK-LABEL: @test_guard_in_idom(
236; CHECK-NOT: trunc
237; CHECK-NOT: icmp slt i32
238
239for.body.lr.ph:
240 br label %for.body
241
242for.body:
243 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
244 %within_limits = icmp ult i32 %i, 64
245 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
246 %i.i64 = zext i32 %i to i64
247 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
248 %val = load i32, i32* %arrayidx, align 4
249 br label %for.inc
250
251for.inc:
252 %i.inc = add nsw nuw i32 %i, 1
253 %cmp = icmp slt i32 %i.inc, %limit
254 br i1 %cmp, label %for.body, label %for.end
255
256for.end:
257 br label %exit
258
259exit:
260 ret void
261}
262
263define void @test_guard_merge_ranges(i32* %base, i32 %limit, i32 %start) {
264; CHECK-LABEL: @test_guard_merge_ranges(
265; CHECK-NOT: trunc
266; CHECK-NOT: icmp slt i32
267
268for.body.lr.ph:
269 br label %for.body
270
271for.body:
272 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
273 %within_limits.1 = icmp ult i32 %i, 64
274 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.1) [ "deopt"() ]
275 %within_limits.2 = icmp ult i32 %i, 2147483647
276 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.2) [ "deopt"() ]
277 %i.i64 = zext i32 %i to i64
278 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
279 %val = load i32, i32* %arrayidx, align 4
280 %i.inc = add nsw nuw i32 %i, 1
281 %cmp = icmp slt i32 %i.inc, %limit
282 br i1 %cmp, label %for.body, label %for.end
283
284for.end:
285 br label %exit
286
287exit:
288 ret void
289}