[opaque pointer type] Add textual IR support for explicit type parameter to gep operator
[oota-llvm.git] / test / Transforms / LoopVectorize / global_alias.ll
1 ; RUN: opt < %s -O1 -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s
2
3 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32-S64"
4
5 %struct.anon = type { [100 x i32], i32, [100 x i32] }
6 %struct.anon.0 = type { [100 x [100 x i32]], i32, [100 x [100 x i32]] }
7
8 @Foo = common global %struct.anon zeroinitializer, align 4
9 @Bar = common global %struct.anon.0 zeroinitializer, align 4
10
11 @PB = external global i32*
12 @PA = external global i32*
13
14
15 ;; === First, the tests that should always vectorize, wither statically or by adding run-time checks ===
16
17
18 ; /// Different objects, positive induction, constant distance
19 ; int noAlias01 (int a) {
20 ;   int i;
21 ;   for (i=0; i<SIZE; i++)
22 ;     Foo.A[i] = Foo.B[i] + a;
23 ;   return Foo.A[a];
24 ; }
25 ; CHECK-LABEL: define i32 @noAlias01(
26 ; CHECK: add nsw <4 x i32>
27 ; CHECK: ret
28
29 define i32 @noAlias01(i32 %a) nounwind {
30 entry:
31   %a.addr = alloca i32, align 4
32   %i = alloca i32, align 4
33   store i32 %a, i32* %a.addr, align 4
34   store i32 0, i32* %i, align 4
35   br label %for.cond
36
37 for.cond:                                         ; preds = %for.inc, %entry
38   %0 = load i32, i32* %i, align 4
39   %cmp = icmp slt i32 %0, 100
40   br i1 %cmp, label %for.body, label %for.end
41
42 for.body:                                         ; preds = %for.cond
43   %1 = load i32, i32* %i, align 4
44   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %1
45   %2 = load i32, i32* %arrayidx, align 4
46   %3 = load i32, i32* %a.addr, align 4
47   %add = add nsw i32 %2, %3
48   %4 = load i32, i32* %i, align 4
49   %arrayidx1 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
50   store i32 %add, i32* %arrayidx1, align 4
51   br label %for.inc
52
53 for.inc:                                          ; preds = %for.body
54   %5 = load i32, i32* %i, align 4
55   %inc = add nsw i32 %5, 1
56   store i32 %inc, i32* %i, align 4
57   br label %for.cond
58
59 for.end:                                          ; preds = %for.cond
60   %6 = load i32, i32* %a.addr, align 4
61   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
62   %7 = load i32, i32* %arrayidx2, align 4
63   ret i32 %7
64 }
65
66 ; /// Different objects, positive induction with widening slide
67 ; int noAlias02 (int a) {
68 ;   int i;
69 ;   for (i=0; i<SIZE-10; i++)
70 ;     Foo.A[i] = Foo.B[i+10] + a;
71 ;   return Foo.A[a];
72 ; }
73 ; CHECK-LABEL: define i32 @noAlias02(
74 ; CHECK: add nsw <4 x i32>
75 ; CHECK: ret
76
77 define i32 @noAlias02(i32 %a) {
78 entry:
79   %a.addr = alloca i32, align 4
80   %i = alloca i32, align 4
81   store i32 %a, i32* %a.addr, align 4
82   store i32 0, i32* %i, align 4
83   br label %for.cond
84
85 for.cond:                                         ; preds = %for.inc, %entry
86   %0 = load i32, i32* %i, align 4
87   %cmp = icmp slt i32 %0, 90
88   br i1 %cmp, label %for.body, label %for.end
89
90 for.body:                                         ; preds = %for.cond
91   %1 = load i32, i32* %i, align 4
92   %add = add nsw i32 %1, 10
93   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %add
94   %2 = load i32, i32* %arrayidx, align 4
95   %3 = load i32, i32* %a.addr, align 4
96   %add1 = add nsw i32 %2, %3
97   %4 = load i32, i32* %i, align 4
98   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
99   store i32 %add1, i32* %arrayidx2, align 4
100   br label %for.inc
101
102 for.inc:                                          ; preds = %for.body
103   %5 = load i32, i32* %i, align 4
104   %inc = add nsw i32 %5, 1
105   store i32 %inc, i32* %i, align 4
106   br label %for.cond
107
108 for.end:                                          ; preds = %for.cond
109   %6 = load i32, i32* %a.addr, align 4
110   %arrayidx3 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
111   %7 = load i32, i32* %arrayidx3, align 4
112   ret i32 %7
113 }
114
115 ; /// Different objects, positive induction with shortening slide
116 ; int noAlias03 (int a) {
117 ;   int i;
118 ;   for (i=0; i<SIZE; i++)
119 ;     Foo.A[i+10] = Foo.B[i] + a;
120 ;   return Foo.A[a];
121 ; }
122 ; CHECK-LABEL: define i32 @noAlias03(
123 ; CHECK: add nsw <4 x i32>
124 ; CHECK: ret
125
126 define i32 @noAlias03(i32 %a) {
127 entry:
128   %a.addr = alloca i32, align 4
129   %i = alloca i32, align 4
130   store i32 %a, i32* %a.addr, align 4
131   store i32 0, i32* %i, align 4
132   br label %for.cond
133
134 for.cond:                                         ; preds = %for.inc, %entry
135   %0 = load i32, i32* %i, align 4
136   %cmp = icmp slt i32 %0, 100
137   br i1 %cmp, label %for.body, label %for.end
138
139 for.body:                                         ; preds = %for.cond
140   %1 = load i32, i32* %i, align 4
141   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %1
142   %2 = load i32, i32* %arrayidx, align 4
143   %3 = load i32, i32* %a.addr, align 4
144   %add = add nsw i32 %2, %3
145   %4 = load i32, i32* %i, align 4
146   %add1 = add nsw i32 %4, 10
147   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %add1
148   store i32 %add, i32* %arrayidx2, align 4
149   br label %for.inc
150
151 for.inc:                                          ; preds = %for.body
152   %5 = load i32, i32* %i, align 4
153   %inc = add nsw i32 %5, 1
154   store i32 %inc, i32* %i, align 4
155   br label %for.cond
156
157 for.end:                                          ; preds = %for.cond
158   %6 = load i32, i32* %a.addr, align 4
159   %arrayidx3 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
160   %7 = load i32, i32* %arrayidx3, align 4
161   ret i32 %7
162 }
163
164 ; /// Pointer access, positive stride, run-time check added
165 ; int noAlias04 (int a) {
166 ;   int i;
167 ;   for (i=0; i<SIZE; i++)
168 ;     *(PA+i) = *(PB+i) + a;
169 ;   return *(PA+a);
170 ; }
171 ; CHECK-LABEL: define i32 @noAlias04(
172 ; CHECK-NOT: add nsw <4 x i32>
173 ; CHECK: ret
174 ;
175 ; TODO: This test vectorizes (with run-time check) on real targets with -O3)
176 ; Check why it's not being vectorized even when forcing vectorization
177
178 define i32 @noAlias04(i32 %a) #0 {
179 entry:
180   %a.addr = alloca i32, align 4
181   %i = alloca i32, align 4
182   store i32 %a, i32* %a.addr, align 4
183   store i32 0, i32* %i, align 4
184   br label %for.cond
185
186 for.cond:                                         ; preds = %for.inc, %entry
187   %0 = load i32, i32* %i, align 4
188   %cmp = icmp slt i32 %0, 100
189   br i1 %cmp, label %for.body, label %for.end
190
191 for.body:                                         ; preds = %for.cond
192   %1 = load i32*, i32** @PB, align 4
193   %2 = load i32, i32* %i, align 4
194   %add.ptr = getelementptr inbounds i32, i32* %1, i32 %2
195   %3 = load i32, i32* %add.ptr, align 4
196   %4 = load i32, i32* %a.addr, align 4
197   %add = add nsw i32 %3, %4
198   %5 = load i32*, i32** @PA, align 4
199   %6 = load i32, i32* %i, align 4
200   %add.ptr1 = getelementptr inbounds i32, i32* %5, i32 %6
201   store i32 %add, i32* %add.ptr1, align 4
202   br label %for.inc
203
204 for.inc:                                          ; preds = %for.body
205   %7 = load i32, i32* %i, align 4
206   %inc = add nsw i32 %7, 1
207   store i32 %inc, i32* %i, align 4
208   br label %for.cond
209
210 for.end:                                          ; preds = %for.cond
211   %8 = load i32*, i32** @PA, align 4
212   %9 = load i32, i32* %a.addr, align 4
213   %add.ptr2 = getelementptr inbounds i32, i32* %8, i32 %9
214   %10 = load i32, i32* %add.ptr2, align 4
215   ret i32 %10
216 }
217
218 ; /// Different objects, positive induction, multi-array
219 ; int noAlias05 (int a) {
220 ;   int i, N=10;
221 ;   for (i=0; i<SIZE; i++)
222 ;     Bar.A[N][i] = Bar.B[N][i] + a;
223 ;   return Bar.A[N][a];
224 ; }
225 ; CHECK-LABEL: define i32 @noAlias05(
226 ; CHECK: add nsw <4 x i32>
227 ; CHECK: ret
228
229 define i32 @noAlias05(i32 %a) #0 {
230 entry:
231   %a.addr = alloca i32, align 4
232   %i = alloca i32, align 4
233   %N = alloca i32, align 4
234   store i32 %a, i32* %a.addr, align 4
235   store i32 10, i32* %N, align 4
236   store i32 0, i32* %i, align 4
237   br label %for.cond
238
239 for.cond:                                         ; preds = %for.inc, %entry
240   %0 = load i32, i32* %i, align 4
241   %cmp = icmp slt i32 %0, 100
242   br i1 %cmp, label %for.body, label %for.end
243
244 for.body:                                         ; preds = %for.cond
245   %1 = load i32, i32* %i, align 4
246   %2 = load i32, i32* %N, align 4
247   %arrayidx = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 2), i32 0, i32 %2
248   %arrayidx1 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx, i32 0, i32 %1
249   %3 = load i32, i32* %arrayidx1, align 4
250   %4 = load i32, i32* %a.addr, align 4
251   %add = add nsw i32 %3, %4
252   %5 = load i32, i32* %i, align 4
253   %6 = load i32, i32* %N, align 4
254   %arrayidx2 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %6
255   %arrayidx3 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx2, i32 0, i32 %5
256   store i32 %add, i32* %arrayidx3, align 4
257   br label %for.inc
258
259 for.inc:                                          ; preds = %for.body
260   %7 = load i32, i32* %i, align 4
261   %inc = add nsw i32 %7, 1
262   store i32 %inc, i32* %i, align 4
263   br label %for.cond
264
265 for.end:                                          ; preds = %for.cond
266   %8 = load i32, i32* %a.addr, align 4
267   %9 = load i32, i32* %N, align 4
268   %arrayidx4 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %9
269   %arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx4, i32 0, i32 %8
270   %10 = load i32, i32* %arrayidx5, align 4
271   ret i32 %10
272 }
273
274 ; /// Same objects, positive induction, multi-array, different sub-elements
275 ; int noAlias06 (int a) {
276 ;   int i, N=10;
277 ;   for (i=0; i<SIZE; i++)
278 ;     Bar.A[N][i] = Bar.A[N+1][i] + a;
279 ;   return Bar.A[N][a];
280 ; }
281 ; CHECK-LABEL: define i32 @noAlias06(
282 ; CHECK: add nsw <4 x i32>
283 ; CHECK: ret
284
285 define i32 @noAlias06(i32 %a) #0 {
286 entry:
287   %a.addr = alloca i32, align 4
288   %i = alloca i32, align 4
289   %N = alloca i32, align 4
290   store i32 %a, i32* %a.addr, align 4
291   store i32 10, i32* %N, align 4
292   store i32 0, i32* %i, align 4
293   br label %for.cond
294
295 for.cond:                                         ; preds = %for.inc, %entry
296   %0 = load i32, i32* %i, align 4
297   %cmp = icmp slt i32 %0, 100
298   br i1 %cmp, label %for.body, label %for.end
299
300 for.body:                                         ; preds = %for.cond
301   %1 = load i32, i32* %i, align 4
302   %2 = load i32, i32* %N, align 4
303   %add = add nsw i32 %2, 1
304   %arrayidx = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %add
305   %arrayidx1 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx, i32 0, i32 %1
306   %3 = load i32, i32* %arrayidx1, align 4
307   %4 = load i32, i32* %a.addr, align 4
308   %add2 = add nsw i32 %3, %4
309   %5 = load i32, i32* %i, align 4
310   %6 = load i32, i32* %N, align 4
311   %arrayidx3 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %6
312   %arrayidx4 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx3, i32 0, i32 %5
313   store i32 %add2, i32* %arrayidx4, align 4
314   br label %for.inc
315
316 for.inc:                                          ; preds = %for.body
317   %7 = load i32, i32* %i, align 4
318   %inc = add nsw i32 %7, 1
319   store i32 %inc, i32* %i, align 4
320   br label %for.cond
321
322 for.end:                                          ; preds = %for.cond
323   %8 = load i32, i32* %a.addr, align 4
324   %9 = load i32, i32* %N, align 4
325   %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %9
326   %arrayidx6 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx5, i32 0, i32 %8
327   %10 = load i32, i32* %arrayidx6, align 4
328   ret i32 %10
329 }
330
331 ; /// Different objects, negative induction, constant distance
332 ; int noAlias07 (int a) {
333 ;   int i;
334 ;   for (i=0; i<SIZE; i++)
335 ;     Foo.A[SIZE-i-1] = Foo.B[SIZE-i-1] + a;
336 ;   return Foo.A[a];
337 ; }
338 ; CHECK-LABEL: define i32 @noAlias07(
339 ; CHECK: store <4 x i32>
340 ; CHECK: ret
341 define i32 @noAlias07(i32 %a) #0 {
342 entry:
343   %a.addr = alloca i32, align 4
344   %i = alloca i32, align 4
345   store i32 %a, i32* %a.addr, align 4
346   store i32 0, i32* %i, align 4
347   br label %for.cond
348
349 for.cond:                                         ; preds = %for.inc, %entry
350   %0 = load i32, i32* %i, align 4
351   %cmp = icmp slt i32 %0, 100
352   br i1 %cmp, label %for.body, label %for.end
353
354 for.body:                                         ; preds = %for.cond
355   %1 = load i32, i32* %i, align 4
356   %sub = sub nsw i32 100, %1
357   %sub1 = sub nsw i32 %sub, 1
358   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
359   %2 = load i32, i32* %arrayidx, align 4
360   %3 = load i32, i32* %a.addr, align 4
361   %add = add nsw i32 %2, %3
362   %4 = load i32, i32* %i, align 4
363   %sub2 = sub nsw i32 100, %4
364   %sub3 = sub nsw i32 %sub2, 1
365   %arrayidx4 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub3
366   store i32 %add, i32* %arrayidx4, align 4
367   br label %for.inc
368
369 for.inc:                                          ; preds = %for.body
370   %5 = load i32, i32* %i, align 4
371   %inc = add nsw i32 %5, 1
372   store i32 %inc, i32* %i, align 4
373   br label %for.cond
374
375 for.end:                                          ; preds = %for.cond
376   %6 = load i32, i32* %a.addr, align 4
377   %arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
378   %7 = load i32, i32* %arrayidx5, align 4
379   ret i32 %7
380 }
381
382 ; /// Different objects, negative induction, shortening slide
383 ; int noAlias08 (int a) {
384 ;   int i;
385 ;   for (i=0; i<SIZE-10; i++)
386 ;     Foo.A[SIZE-i-1] = Foo.B[SIZE-i-10] + a;
387 ;   return Foo.A[a];
388 ; }
389 ; CHECK-LABEL: define i32 @noAlias08(
390 ; CHECK: sub <4 x i32>
391 ; CHECK: ret
392
393 define i32 @noAlias08(i32 %a) #0 {
394 entry:
395   %a.addr = alloca i32, align 4
396   %i = alloca i32, align 4
397   store i32 %a, i32* %a.addr, align 4
398   store i32 0, i32* %i, align 4
399   br label %for.cond
400
401 for.cond:                                         ; preds = %for.inc, %entry
402   %0 = load i32, i32* %i, align 4
403   %cmp = icmp slt i32 %0, 90
404   br i1 %cmp, label %for.body, label %for.end
405
406 for.body:                                         ; preds = %for.cond
407   %1 = load i32, i32* %i, align 4
408   %sub = sub nsw i32 100, %1
409   %sub1 = sub nsw i32 %sub, 10
410   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
411   %2 = load i32, i32* %arrayidx, align 4
412   %3 = load i32, i32* %a.addr, align 4
413   %add = add nsw i32 %2, %3
414   %4 = load i32, i32* %i, align 4
415   %sub2 = sub nsw i32 100, %4
416   %sub3 = sub nsw i32 %sub2, 1
417   %arrayidx4 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub3
418   store i32 %add, i32* %arrayidx4, align 4
419   br label %for.inc
420
421 for.inc:                                          ; preds = %for.body
422   %5 = load i32, i32* %i, align 4
423   %inc = add nsw i32 %5, 1
424   store i32 %inc, i32* %i, align 4
425   br label %for.cond
426
427 for.end:                                          ; preds = %for.cond
428   %6 = load i32, i32* %a.addr, align 4
429   %arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
430   %7 = load i32, i32* %arrayidx5, align 4
431   ret i32 %7
432 }
433
434 ; /// Different objects, negative induction, widening slide
435 ; int noAlias09 (int a) {
436 ;   int i;
437 ;   for (i=0; i<SIZE; i++)
438 ;     Foo.A[SIZE-i-10] = Foo.B[SIZE-i-1] + a;
439 ;   return Foo.A[a];
440 ; }
441 ; CHECK-LABEL: define i32 @noAlias09(
442 ; CHECK: sub <4 x i32>
443 ; CHECK: ret
444
445 define i32 @noAlias09(i32 %a) #0 {
446 entry:
447   %a.addr = alloca i32, align 4
448   %i = alloca i32, align 4
449   store i32 %a, i32* %a.addr, align 4
450   store i32 0, i32* %i, align 4
451   br label %for.cond
452
453 for.cond:                                         ; preds = %for.inc, %entry
454   %0 = load i32, i32* %i, align 4
455   %cmp = icmp slt i32 %0, 100
456   br i1 %cmp, label %for.body, label %for.end
457
458 for.body:                                         ; preds = %for.cond
459   %1 = load i32, i32* %i, align 4
460   %sub = sub nsw i32 100, %1
461   %sub1 = sub nsw i32 %sub, 1
462   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
463   %2 = load i32, i32* %arrayidx, align 4
464   %3 = load i32, i32* %a.addr, align 4
465   %add = add nsw i32 %2, %3
466   %4 = load i32, i32* %i, align 4
467   %sub2 = sub nsw i32 100, %4
468   %sub3 = sub nsw i32 %sub2, 10
469   %arrayidx4 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub3
470   store i32 %add, i32* %arrayidx4, align 4
471   br label %for.inc
472
473 for.inc:                                          ; preds = %for.body
474   %5 = load i32, i32* %i, align 4
475   %inc = add nsw i32 %5, 1
476   store i32 %inc, i32* %i, align 4
477   br label %for.cond
478
479 for.end:                                          ; preds = %for.cond
480   %6 = load i32, i32* %a.addr, align 4
481   %arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
482   %7 = load i32, i32* %arrayidx5, align 4
483   ret i32 %7
484 }
485
486 ; /// Pointer access, negative stride, run-time check added
487 ; int noAlias10 (int a) {
488 ;   int i;
489 ;   for (i=0; i<SIZE; i++)
490 ;     *(PA+SIZE-i-1) = *(PB+SIZE-i-1) + a;
491 ;   return *(PA+a);
492 ; }
493 ; CHECK-LABEL: define i32 @noAlias10(
494 ; CHECK-NOT: sub {{.*}} <4 x i32>
495 ; CHECK: ret
496 ;
497 ; TODO: This test vectorizes (with run-time check) on real targets with -O3)
498 ; Check why it's not being vectorized even when forcing vectorization
499
500 define i32 @noAlias10(i32 %a) #0 {
501 entry:
502   %a.addr = alloca i32, align 4
503   %i = alloca i32, align 4
504   store i32 %a, i32* %a.addr, align 4
505   store i32 0, i32* %i, align 4
506   br label %for.cond
507
508 for.cond:                                         ; preds = %for.inc, %entry
509   %0 = load i32, i32* %i, align 4
510   %cmp = icmp slt i32 %0, 100
511   br i1 %cmp, label %for.body, label %for.end
512
513 for.body:                                         ; preds = %for.cond
514   %1 = load i32*, i32** @PB, align 4
515   %add.ptr = getelementptr inbounds i32, i32* %1, i32 100
516   %2 = load i32, i32* %i, align 4
517   %idx.neg = sub i32 0, %2
518   %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %idx.neg
519   %add.ptr2 = getelementptr inbounds i32, i32* %add.ptr1, i32 -1
520   %3 = load i32, i32* %add.ptr2, align 4
521   %4 = load i32, i32* %a.addr, align 4
522   %add = add nsw i32 %3, %4
523   %5 = load i32*, i32** @PA, align 4
524   %add.ptr3 = getelementptr inbounds i32, i32* %5, i32 100
525   %6 = load i32, i32* %i, align 4
526   %idx.neg4 = sub i32 0, %6
527   %add.ptr5 = getelementptr inbounds i32, i32* %add.ptr3, i32 %idx.neg4
528   %add.ptr6 = getelementptr inbounds i32, i32* %add.ptr5, i32 -1
529   store i32 %add, i32* %add.ptr6, align 4
530   br label %for.inc
531
532 for.inc:                                          ; preds = %for.body
533   %7 = load i32, i32* %i, align 4
534   %inc = add nsw i32 %7, 1
535   store i32 %inc, i32* %i, align 4
536   br label %for.cond
537
538 for.end:                                          ; preds = %for.cond
539   %8 = load i32*, i32** @PA, align 4
540   %9 = load i32, i32* %a.addr, align 4
541   %add.ptr7 = getelementptr inbounds i32, i32* %8, i32 %9
542   %10 = load i32, i32* %add.ptr7, align 4
543   ret i32 %10
544 }
545
546 ; /// Different objects, negative induction, multi-array
547 ; int noAlias11 (int a) {
548 ;   int i, N=10;
549 ;   for (i=0; i<SIZE; i++)
550 ;     Bar.A[N][SIZE-i-1] = Bar.B[N][SIZE-i-1] + a;
551 ;   return Bar.A[N][a];
552 ; }
553 ; CHECK-LABEL: define i32 @noAlias11(
554 ; CHECK: store <4 x i32>
555 ; CHECK: ret
556
557 define i32 @noAlias11(i32 %a) #0 {
558 entry:
559   %a.addr = alloca i32, align 4
560   %i = alloca i32, align 4
561   %N = alloca i32, align 4
562   store i32 %a, i32* %a.addr, align 4
563   store i32 10, i32* %N, align 4
564   store i32 0, i32* %i, align 4
565   br label %for.cond
566
567 for.cond:                                         ; preds = %for.inc, %entry
568   %0 = load i32, i32* %i, align 4
569   %cmp = icmp slt i32 %0, 100
570   br i1 %cmp, label %for.body, label %for.end
571
572 for.body:                                         ; preds = %for.cond
573   %1 = load i32, i32* %i, align 4
574   %sub = sub nsw i32 100, %1
575   %sub1 = sub nsw i32 %sub, 1
576   %2 = load i32, i32* %N, align 4
577   %arrayidx = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 2), i32 0, i32 %2
578   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx, i32 0, i32 %sub1
579   %3 = load i32, i32* %arrayidx2, align 4
580   %4 = load i32, i32* %a.addr, align 4
581   %add = add nsw i32 %3, %4
582   %5 = load i32, i32* %i, align 4
583   %sub3 = sub nsw i32 100, %5
584   %sub4 = sub nsw i32 %sub3, 1
585   %6 = load i32, i32* %N, align 4
586   %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %6
587   %arrayidx6 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx5, i32 0, i32 %sub4
588   store i32 %add, i32* %arrayidx6, align 4
589   br label %for.inc
590
591 for.inc:                                          ; preds = %for.body
592   %7 = load i32, i32* %i, align 4
593   %inc = add nsw i32 %7, 1
594   store i32 %inc, i32* %i, align 4
595   br label %for.cond
596
597 for.end:                                          ; preds = %for.cond
598   %8 = load i32, i32* %a.addr, align 4
599   %9 = load i32, i32* %N, align 4
600   %arrayidx7 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %9
601   %arrayidx8 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx7, i32 0, i32 %8
602   %10 = load i32, i32* %arrayidx8, align 4
603   ret i32 %10
604 }
605
606 ; /// Same objects, negative induction, multi-array, different sub-elements
607 ; int noAlias12 (int a) {
608 ;   int i, N=10;
609 ;   for (i=0; i<SIZE; i++)
610 ;     Bar.A[N][SIZE-i-1] = Bar.A[N+1][SIZE-i-1] + a;
611 ;   return Bar.A[N][a];
612 ; }
613 ; CHECK-LABEL: define i32 @noAlias12(
614 ; CHECK: store <4 x i32>
615 ; CHECK: ret
616
617 define i32 @noAlias12(i32 %a) #0 {
618 entry:
619   %a.addr = alloca i32, align 4
620   %i = alloca i32, align 4
621   %N = alloca i32, align 4
622   store i32 %a, i32* %a.addr, align 4
623   store i32 10, i32* %N, align 4
624   store i32 0, i32* %i, align 4
625   br label %for.cond
626
627 for.cond:                                         ; preds = %for.inc, %entry
628   %0 = load i32, i32* %i, align 4
629   %cmp = icmp slt i32 %0, 100
630   br i1 %cmp, label %for.body, label %for.end
631
632 for.body:                                         ; preds = %for.cond
633   %1 = load i32, i32* %i, align 4
634   %sub = sub nsw i32 100, %1
635   %sub1 = sub nsw i32 %sub, 1
636   %2 = load i32, i32* %N, align 4
637   %add = add nsw i32 %2, 1
638   %arrayidx = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %add
639   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx, i32 0, i32 %sub1
640   %3 = load i32, i32* %arrayidx2, align 4
641   %4 = load i32, i32* %a.addr, align 4
642   %add3 = add nsw i32 %3, %4
643   %5 = load i32, i32* %i, align 4
644   %sub4 = sub nsw i32 100, %5
645   %sub5 = sub nsw i32 %sub4, 1
646   %6 = load i32, i32* %N, align 4
647   %arrayidx6 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %6
648   %arrayidx7 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx6, i32 0, i32 %sub5
649   store i32 %add3, i32* %arrayidx7, align 4
650   br label %for.inc
651
652 for.inc:                                          ; preds = %for.body
653   %7 = load i32, i32* %i, align 4
654   %inc = add nsw i32 %7, 1
655   store i32 %inc, i32* %i, align 4
656   br label %for.cond
657
658 for.end:                                          ; preds = %for.cond
659   %8 = load i32, i32* %a.addr, align 4
660   %9 = load i32, i32* %N, align 4
661   %arrayidx8 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0, %struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %9
662   %arrayidx9 = getelementptr inbounds [100 x i32], [100 x i32]* %arrayidx8, i32 0, i32 %8
663   %10 = load i32, i32* %arrayidx9, align 4
664   ret i32 %10
665 }
666
667 ; /// Same objects, positive induction, constant distance, just enough for vector size
668 ; int noAlias13 (int a) {
669 ;   int i;
670 ;   for (i=0; i<SIZE; i++)
671 ;     Foo.A[i] = Foo.A[i+4] + a;
672 ;   return Foo.A[a];
673 ; }
674 ; CHECK-LABEL: define i32 @noAlias13(
675 ; CHECK: add nsw <4 x i32>
676 ; CHECK: ret
677
678 define i32 @noAlias13(i32 %a) #0 {
679 entry:
680   %a.addr = alloca i32, align 4
681   %i = alloca i32, align 4
682   store i32 %a, i32* %a.addr, align 4
683   store i32 0, i32* %i, align 4
684   br label %for.cond
685
686 for.cond:                                         ; preds = %for.inc, %entry
687   %0 = load i32, i32* %i, align 4
688   %cmp = icmp slt i32 %0, 100
689   br i1 %cmp, label %for.body, label %for.end
690
691 for.body:                                         ; preds = %for.cond
692   %1 = load i32, i32* %i, align 4
693   %add = add nsw i32 %1, 4
694   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %add
695   %2 = load i32, i32* %arrayidx, align 4
696   %3 = load i32, i32* %a.addr, align 4
697   %add1 = add nsw i32 %2, %3
698   %4 = load i32, i32* %i, align 4
699   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
700   store i32 %add1, i32* %arrayidx2, align 4
701   br label %for.inc
702
703 for.inc:                                          ; preds = %for.body
704   %5 = load i32, i32* %i, align 4
705   %inc = add nsw i32 %5, 1
706   store i32 %inc, i32* %i, align 4
707   br label %for.cond
708
709 for.end:                                          ; preds = %for.cond
710   %6 = load i32, i32* %a.addr, align 4
711   %arrayidx3 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
712   %7 = load i32, i32* %arrayidx3, align 4
713   ret i32 %7
714 }
715
716 ; /// Same objects, negative induction, constant distance, just enough for vector size
717 ; int noAlias14 (int a) {
718 ;   int i;
719 ;   for (i=0; i<SIZE; i++)
720 ;     Foo.A[SIZE-i-1] = Foo.A[SIZE-i-5] + a;
721 ;   return Foo.A[a];
722 ; }
723 ; CHECK-LABEL: define i32 @noAlias14(
724 ; CHECK: sub <4 x i32>
725 ; CHECK: ret
726
727 define i32 @noAlias14(i32 %a) #0 {
728 entry:
729   %a.addr = alloca i32, align 4
730   %i = alloca i32, align 4
731   store i32 %a, i32* %a.addr, align 4
732   store i32 0, i32* %i, align 4
733   br label %for.cond
734
735 for.cond:                                         ; preds = %for.inc, %entry
736   %0 = load i32, i32* %i, align 4
737   %cmp = icmp slt i32 %0, 100
738   br i1 %cmp, label %for.body, label %for.end
739
740 for.body:                                         ; preds = %for.cond
741   %1 = load i32, i32* %i, align 4
742   %sub = sub nsw i32 100, %1
743   %sub1 = sub nsw i32 %sub, 5
744   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub1
745   %2 = load i32, i32* %arrayidx, align 4
746   %3 = load i32, i32* %a.addr, align 4
747   %add = add nsw i32 %2, %3
748   %4 = load i32, i32* %i, align 4
749   %sub2 = sub nsw i32 100, %4
750   %sub3 = sub nsw i32 %sub2, 1
751   %arrayidx4 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub3
752   store i32 %add, i32* %arrayidx4, align 4
753   br label %for.inc
754
755 for.inc:                                          ; preds = %for.body
756   %5 = load i32, i32* %i, align 4
757   %inc = add nsw i32 %5, 1
758   store i32 %inc, i32* %i, align 4
759   br label %for.cond
760
761 for.end:                                          ; preds = %for.cond
762   %6 = load i32, i32* %a.addr, align 4
763   %arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
764   %7 = load i32, i32* %arrayidx5, align 4
765   ret i32 %7
766 }
767
768
769 ;; === Now, the tests that we could vectorize with induction changes or run-time checks ===
770
771
772 ; /// Different objects, swapped induction, alias at the end
773 ; int mayAlias01 (int a) {
774 ;   int i;
775 ;   for (i=0; i<SIZE; i++)
776 ;     Foo.A[i] = Foo.B[SIZE-i-1] + a;
777 ;   return Foo.A[a];
778 ; }
779 ; CHECK-LABEL: define i32 @mayAlias01(
780 ; CHECK-NOT: add nsw <4 x i32>
781 ; CHECK: ret
782
783 define i32 @mayAlias01(i32 %a) nounwind {
784 entry:
785   %a.addr = alloca i32, align 4
786   %i = alloca i32, align 4
787   store i32 %a, i32* %a.addr, align 4
788   store i32 0, i32* %i, align 4
789   br label %for.cond
790
791 for.cond:                                         ; preds = %for.inc, %entry
792   %0 = load i32, i32* %i, align 4
793   %cmp = icmp slt i32 %0, 100
794   br i1 %cmp, label %for.body, label %for.end
795
796 for.body:                                         ; preds = %for.cond
797   %1 = load i32, i32* %i, align 4
798   %sub = sub nsw i32 100, %1
799   %sub1 = sub nsw i32 %sub, 1
800   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
801   %2 = load i32, i32* %arrayidx, align 4
802   %3 = load i32, i32* %a.addr, align 4
803   %add = add nsw i32 %2, %3
804   %4 = load i32, i32* %i, align 4
805   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
806   store i32 %add, i32* %arrayidx2, align 4
807   br label %for.inc
808
809 for.inc:                                          ; preds = %for.body
810   %5 = load i32, i32* %i, align 4
811   %inc = add nsw i32 %5, 1
812   store i32 %inc, i32* %i, align 4
813   br label %for.cond
814
815 for.end:                                          ; preds = %for.cond
816   %6 = load i32, i32* %a.addr, align 4
817   %arrayidx3 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
818   %7 = load i32, i32* %arrayidx3, align 4
819   ret i32 %7
820 }
821
822 ; /// Different objects, swapped induction, alias at the beginning
823 ; int mayAlias02 (int a) {
824 ;   int i;
825 ;   for (i=0; i<SIZE; i++)
826 ;     Foo.A[SIZE-i-1] = Foo.B[i] + a;
827 ;   return Foo.A[a];
828 ; }
829 ; CHECK-LABEL: define i32 @mayAlias02(
830 ; CHECK-NOT: add nsw <4 x i32>
831 ; CHECK: ret
832
833 define i32 @mayAlias02(i32 %a) nounwind {
834 entry:
835   %a.addr = alloca i32, align 4
836   %i = alloca i32, align 4
837   store i32 %a, i32* %a.addr, align 4
838   store i32 0, i32* %i, align 4
839   br label %for.cond
840
841 for.cond:                                         ; preds = %for.inc, %entry
842   %0 = load i32, i32* %i, align 4
843   %cmp = icmp slt i32 %0, 100
844   br i1 %cmp, label %for.body, label %for.end
845
846 for.body:                                         ; preds = %for.cond
847   %1 = load i32, i32* %i, align 4
848   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %1
849   %2 = load i32, i32* %arrayidx, align 4
850   %3 = load i32, i32* %a.addr, align 4
851   %add = add nsw i32 %2, %3
852   %4 = load i32, i32* %i, align 4
853   %sub = sub nsw i32 100, %4
854   %sub1 = sub nsw i32 %sub, 1
855   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub1
856   store i32 %add, i32* %arrayidx2, align 4
857   br label %for.inc
858
859 for.inc:                                          ; preds = %for.body
860   %5 = load i32, i32* %i, align 4
861   %inc = add nsw i32 %5, 1
862   store i32 %inc, i32* %i, align 4
863   br label %for.cond
864
865 for.end:                                          ; preds = %for.cond
866   %6 = load i32, i32* %a.addr, align 4
867   %arrayidx3 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
868   %7 = load i32, i32* %arrayidx3, align 4
869   ret i32 %7
870 }
871
872 ; /// Pointer access, run-time check added
873 ; int mayAlias03 (int a) {
874 ;   int i;
875 ;   for (i=0; i<SIZE; i++)
876 ;     *(PA+i) = *(PB+SIZE-i-1) + a;
877 ;   return *(PA+a);
878 ; }
879 ; CHECK-LABEL: define i32 @mayAlias03(
880 ; CHECK-NOT: add nsw <4 x i32>
881 ; CHECK: ret
882
883 define i32 @mayAlias03(i32 %a) nounwind {
884 entry:
885   %a.addr = alloca i32, align 4
886   %i = alloca i32, align 4
887   store i32 %a, i32* %a.addr, align 4
888   store i32 0, i32* %i, align 4
889   br label %for.cond
890
891 for.cond:                                         ; preds = %for.inc, %entry
892   %0 = load i32, i32* %i, align 4
893   %cmp = icmp slt i32 %0, 100
894   br i1 %cmp, label %for.body, label %for.end
895
896 for.body:                                         ; preds = %for.cond
897   %1 = load i32*, i32** @PB, align 4
898   %add.ptr = getelementptr inbounds i32, i32* %1, i32 100
899   %2 = load i32, i32* %i, align 4
900   %idx.neg = sub i32 0, %2
901   %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %idx.neg
902   %add.ptr2 = getelementptr inbounds i32, i32* %add.ptr1, i32 -1
903   %3 = load i32, i32* %add.ptr2, align 4
904   %4 = load i32, i32* %a.addr, align 4
905   %add = add nsw i32 %3, %4
906   %5 = load i32*, i32** @PA, align 4
907   %6 = load i32, i32* %i, align 4
908   %add.ptr3 = getelementptr inbounds i32, i32* %5, i32 %6
909   store i32 %add, i32* %add.ptr3, align 4
910   br label %for.inc
911
912 for.inc:                                          ; preds = %for.body
913   %7 = load i32, i32* %i, align 4
914   %inc = add nsw i32 %7, 1
915   store i32 %inc, i32* %i, align 4
916   br label %for.cond
917
918 for.end:                                          ; preds = %for.cond
919   %8 = load i32*, i32** @PA, align 4
920   %9 = load i32, i32* %a.addr, align 4
921   %add.ptr4 = getelementptr inbounds i32, i32* %8, i32 %9
922   %10 = load i32, i32* %add.ptr4, align 4
923   ret i32 %10
924 }
925
926
927 ;; === Finally, the tests that should only vectorize with care (or if we ignore undefined behaviour at all) ===
928
929
930 ; int mustAlias01 (int a) {
931 ;   int i;
932 ;   for (i=0; i<SIZE; i++)
933 ;     Foo.A[i+10] = Foo.B[SIZE-i-1] + a;
934 ;   return Foo.A[a];
935 ; }
936 ; CHECK-LABEL: define i32 @mustAlias01(
937 ; CHECK-NOT: add nsw <4 x i32>
938 ; CHECK: ret
939
940 define i32 @mustAlias01(i32 %a) nounwind {
941 entry:
942   %a.addr = alloca i32, align 4
943   %i = alloca i32, align 4
944   store i32 %a, i32* %a.addr, align 4
945   store i32 0, i32* %i, align 4
946   br label %for.cond
947
948 for.cond:                                         ; preds = %for.inc, %entry
949   %0 = load i32, i32* %i, align 4
950   %cmp = icmp slt i32 %0, 100
951   br i1 %cmp, label %for.body, label %for.end
952
953 for.body:                                         ; preds = %for.cond
954   %1 = load i32, i32* %i, align 4
955   %sub = sub nsw i32 100, %1
956   %sub1 = sub nsw i32 %sub, 1
957   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
958   %2 = load i32, i32* %arrayidx, align 4
959   %3 = load i32, i32* %a.addr, align 4
960   %add = add nsw i32 %2, %3
961   %4 = load i32, i32* %i, align 4
962   %add2 = add nsw i32 %4, 10
963   %arrayidx3 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %add2
964   store i32 %add, i32* %arrayidx3, align 4
965   br label %for.inc
966
967 for.inc:                                          ; preds = %for.body
968   %5 = load i32, i32* %i, align 4
969   %inc = add nsw i32 %5, 1
970   store i32 %inc, i32* %i, align 4
971   br label %for.cond
972
973 for.end:                                          ; preds = %for.cond
974   %6 = load i32, i32* %a.addr, align 4
975   %arrayidx4 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
976   %7 = load i32, i32* %arrayidx4, align 4
977   ret i32 %7
978 }
979
980 ; int mustAlias02 (int a) {
981 ;   int i;
982 ;   for (i=0; i<SIZE; i++)
983 ;     Foo.A[i] = Foo.B[SIZE-i-10] + a;
984 ;   return Foo.A[a];
985 ; }
986 ; CHECK-LABEL: define i32 @mustAlias02(
987 ; CHECK-NOT: add nsw <4 x i32>
988 ; CHECK: ret
989
990 define i32 @mustAlias02(i32 %a) nounwind {
991 entry:
992   %a.addr = alloca i32, align 4
993   %i = alloca i32, align 4
994   store i32 %a, i32* %a.addr, align 4
995   store i32 0, i32* %i, align 4
996   br label %for.cond
997
998 for.cond:                                         ; preds = %for.inc, %entry
999   %0 = load i32, i32* %i, align 4
1000   %cmp = icmp slt i32 %0, 100
1001   br i1 %cmp, label %for.body, label %for.end
1002
1003 for.body:                                         ; preds = %for.cond
1004   %1 = load i32, i32* %i, align 4
1005   %sub = sub nsw i32 100, %1
1006   %sub1 = sub nsw i32 %sub, 10
1007   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
1008   %2 = load i32, i32* %arrayidx, align 4
1009   %3 = load i32, i32* %a.addr, align 4
1010   %add = add nsw i32 %2, %3
1011   %4 = load i32, i32* %i, align 4
1012   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
1013   store i32 %add, i32* %arrayidx2, align 4
1014   br label %for.inc
1015
1016 for.inc:                                          ; preds = %for.body
1017   %5 = load i32, i32* %i, align 4
1018   %inc = add nsw i32 %5, 1
1019   store i32 %inc, i32* %i, align 4
1020   br label %for.cond
1021
1022 for.end:                                          ; preds = %for.cond
1023   %6 = load i32, i32* %a.addr, align 4
1024   %arrayidx3 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
1025   %7 = load i32, i32* %arrayidx3, align 4
1026   ret i32 %7
1027 }
1028
1029 ; int mustAlias03 (int a) {
1030 ;   int i;
1031 ;   for (i=0; i<SIZE; i++)
1032 ;     Foo.A[i+10] = Foo.B[SIZE-i-10] + a;
1033 ;   return Foo.A[a];
1034 ; }
1035 ; CHECK-LABEL: define i32 @mustAlias03(
1036 ; CHECK-NOT: add nsw <4 x i32>
1037 ; CHECK: ret
1038
1039 define i32 @mustAlias03(i32 %a) nounwind {
1040 entry:
1041   %a.addr = alloca i32, align 4
1042   %i = alloca i32, align 4
1043   store i32 %a, i32* %a.addr, align 4
1044   store i32 0, i32* %i, align 4
1045   br label %for.cond
1046
1047 for.cond:                                         ; preds = %for.inc, %entry
1048   %0 = load i32, i32* %i, align 4
1049   %cmp = icmp slt i32 %0, 100
1050   br i1 %cmp, label %for.body, label %for.end
1051
1052 for.body:                                         ; preds = %for.cond
1053   %1 = load i32, i32* %i, align 4
1054   %sub = sub nsw i32 100, %1
1055   %sub1 = sub nsw i32 %sub, 10
1056   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
1057   %2 = load i32, i32* %arrayidx, align 4
1058   %3 = load i32, i32* %a.addr, align 4
1059   %add = add nsw i32 %2, %3
1060   %4 = load i32, i32* %i, align 4
1061   %add2 = add nsw i32 %4, 10
1062   %arrayidx3 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %add2
1063   store i32 %add, i32* %arrayidx3, align 4
1064   br label %for.inc
1065
1066 for.inc:                                          ; preds = %for.body
1067   %5 = load i32, i32* %i, align 4
1068   %inc = add nsw i32 %5, 1
1069   store i32 %inc, i32* %i, align 4
1070   br label %for.cond
1071
1072 for.end:                                          ; preds = %for.cond
1073   %6 = load i32, i32* %a.addr, align 4
1074   %arrayidx4 = getelementptr inbounds [100 x i32], [100 x i32]* getelementptr inbounds (%struct.anon, %struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
1075   %7 = load i32, i32* %arrayidx4, align 4
1076   ret i32 %7
1077 }