xref: /llvm-project/llvm/test/Transforms/LoopVectorize/global_alias.ll (revision fa8a7266724f26d27820f8876b504d7a4f166948)
1; RUN: opt -passes='loop-vectorize,dce,instcombine' -force-vector-interleave=1 -force-vector-width=4 -S %s | FileCheck %s
2
3target 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 ptr
12@PA = external global ptr
13
14
15;; === First, the tests that should always vectorize, whether 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
29define i32 @noAlias01(i32 %a) nounwind {
30entry:
31  br label %for.body
32
33for.body:                                         ; preds = %entry, %for.body
34  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
35  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %i.05
36  %0 = load i32, ptr %arrayidx, align 4
37  %add = add nsw i32 %0, %a
38  %arrayidx1 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %i.05
39  store i32 %add, ptr %arrayidx1, align 4
40  %inc = add nuw nsw i32 %i.05, 1
41  %exitcond.not = icmp eq i32 %inc, 100
42  br i1 %exitcond.not, label %for.end, label %for.body
43
44for.end:                                          ; preds = %for.body
45  %arrayidx2 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
46  %1 = load i32, ptr %arrayidx2, align 4
47  ret i32 %1
48}
49
50; /// Different objects, positive induction with widening slide
51; int noAlias02 (int a) {
52;   int i;
53;   for (i=0; i<SIZE-10; i++)
54;     Foo.A[i] = Foo.B[i+10] + a;
55;   return Foo.A[a];
56; }
57; CHECK-LABEL: define i32 @noAlias02(
58; CHECK: add nsw <4 x i32>
59; CHECK: ret
60
61define i32 @noAlias02(i32 %a) {
62entry:
63  br label %for.body
64
65for.body:                                         ; preds = %entry, %for.body
66  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
67  %add = add nuw nsw i32 %i.05, 10
68  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %add
69  %0 = load i32, ptr %arrayidx, align 4
70  %add1 = add nsw i32 %0, %a
71  %arrayidx2 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %i.05
72  store i32 %add1, ptr %arrayidx2, align 4
73  %inc = add nuw nsw i32 %i.05, 1
74  %exitcond.not = icmp eq i32 %inc, 90
75  br i1 %exitcond.not, label %for.end, label %for.body
76
77for.end:                                          ; preds = %for.body
78  %arrayidx3 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
79  %1 = load i32, ptr %arrayidx3, align 4
80  ret i32 %1
81}
82
83; /// Different objects, positive induction with shortening slide
84; int noAlias03 (int a) {
85;   int i;
86;   for (i=0; i<SIZE; i++)
87;     Foo.A[i+10] = Foo.B[i] + a;
88;   return Foo.A[a];
89; }
90; CHECK-LABEL: define i32 @noAlias03(
91; CHECK: add nsw <4 x i32>
92; CHECK: ret
93
94define i32 @noAlias03(i32 %a) {
95entry:
96  br label %for.body
97
98for.body:                                         ; preds = %entry, %for.body
99  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
100  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %i.05
101  %0 = load i32, ptr %arrayidx, align 4
102  %add = add nsw i32 %0, %a
103  %add1 = add nuw nsw i32 %i.05, 10
104  %arrayidx2 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %add1
105  store i32 %add, ptr %arrayidx2, align 4
106  %inc = add nuw nsw i32 %i.05, 1
107  %exitcond.not = icmp eq i32 %inc, 100
108  br i1 %exitcond.not, label %for.end, label %for.body
109
110for.end:                                          ; preds = %for.body
111  %arrayidx3 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
112  %1 = load i32, ptr %arrayidx3, align 4
113  ret i32 %1
114}
115
116; /// Pointer access, positive stride, run-time check added
117; int noAlias04 (int a) {
118;   int i;
119;   for (i=0; i<SIZE; i++)
120;     *(PA+i) = *(PB+i) + a;
121;   return *(PA+a);
122; }
123; CHECK-LABEL: define i32 @noAlias04(
124; CHECK-NOT: add nsw <4 x i32>
125; CHECK: ret
126;
127; TODO: This test vectorizes (with run-time check) on real targets with -O3)
128; Check why it's not being vectorized even when forcing vectorization
129
130define i32 @noAlias04(i32 %a) #0 {
131entry:
132  br label %for.body
133
134for.body:                                         ; preds = %entry, %for.body
135  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
136  %0 = load ptr, ptr @PB, align 4
137  %add.ptr = getelementptr inbounds i32, ptr %0, i32 %i.05
138  %1 = load i32, ptr %add.ptr, align 4
139  %add = add nsw i32 %1, %a
140  %2 = load ptr, ptr @PA, align 4
141  %add.ptr1 = getelementptr inbounds i32, ptr %2, i32 %i.05
142  store i32 %add, ptr %add.ptr1, align 4
143  %inc = add nuw nsw i32 %i.05, 1
144  %exitcond.not = icmp eq i32 %inc, 100
145  br i1 %exitcond.not, label %for.end, label %for.body
146
147for.end:                                          ; preds = %for.body
148  %3 = load ptr, ptr @PA, align 4
149  %add.ptr2 = getelementptr inbounds i32, ptr %3, i32 %a
150  %4 = load i32, ptr %add.ptr2, align 4
151  ret i32 %4
152}
153
154; /// Different objects, positive induction, multi-array
155; int noAlias05 (int a) {
156;   int i, N=10;
157;   for (i=0; i<SIZE; i++)
158;     Bar.A[N][i] = Bar.B[N][i] + a;
159;   return Bar.A[N][a];
160; }
161; CHECK-LABEL: define i32 @noAlias05(
162; CHECK: add nsw <4 x i32>
163; CHECK: ret
164
165define i32 @noAlias05(i32 %a) #0 {
166entry:
167  br label %for.body
168
169for.body:                                         ; preds = %entry, %for.body
170  %i.07 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
171  %arrayidx1 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 2, i32 10, i32 %i.07
172  %0 = load i32, ptr %arrayidx1, align 4
173  %add = add nsw i32 %0, %a
174  %arrayidx3 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 10, i32 %i.07
175  store i32 %add, ptr %arrayidx3, align 4
176  %inc = add nuw nsw i32 %i.07, 1
177  %exitcond.not = icmp eq i32 %inc, 100
178  br i1 %exitcond.not, label %for.end, label %for.body
179
180for.end:                                          ; preds = %for.body
181  %arrayidx5 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 10, i32 %a
182  %1 = load i32, ptr %arrayidx5, align 4
183  ret i32 %1
184}
185
186; /// Same objects, positive induction, multi-array, different sub-elements
187; int noAlias06 (int a) {
188;   int i, N=10;
189;   for (i=0; i<SIZE; i++)
190;     Bar.A[N][i] = Bar.A[N+1][i] + a;
191;   return Bar.A[N][a];
192; }
193; CHECK-LABEL: define i32 @noAlias06(
194; CHECK: add nsw <4 x i32>
195; CHECK: ret
196
197define i32 @noAlias06(i32 %a) #0 {
198entry:
199  br label %for.body
200
201for.body:                                         ; preds = %entry, %for.body
202  %i.07 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
203  %arrayidx1 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 11, i32 %i.07
204  %0 = load i32, ptr %arrayidx1, align 4
205  %add2 = add nsw i32 %0, %a
206  %arrayidx4 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 10, i32 %i.07
207  store i32 %add2, ptr %arrayidx4, align 4
208  %inc = add nuw nsw i32 %i.07, 1
209  %exitcond.not = icmp eq i32 %inc, 100
210  br i1 %exitcond.not, label %for.end, label %for.body
211
212for.end:                                          ; preds = %for.body
213  %arrayidx6 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 10, i32 %a
214  %1 = load i32, ptr %arrayidx6, align 4
215  ret i32 %1
216}
217
218; /// Different objects, negative induction, constant distance
219; int noAlias07 (int a) {
220;   int i;
221;   for (i=0; i<SIZE; i++)
222;     Foo.A[SIZE-i-1] = Foo.B[SIZE-i-1] + a;
223;   return Foo.A[a];
224; }
225; CHECK-LABEL: define i32 @noAlias07(
226; CHECK: store <4 x i32>
227; CHECK: ret
228define i32 @noAlias07(i32 %a) #0 {
229entry:
230  br label %for.body
231
232for.body:                                         ; preds = %entry, %for.body
233  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
234  %sub1 = sub nuw nsw i32 99, %i.05
235  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %sub1
236  %0 = load i32, ptr %arrayidx, align 4
237  %add = add nsw i32 %0, %a
238  %arrayidx4 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %sub1
239  store i32 %add, ptr %arrayidx4, align 4
240  %inc = add nuw nsw i32 %i.05, 1
241  %exitcond.not = icmp eq i32 %inc, 100
242  br i1 %exitcond.not, label %for.end, label %for.body
243
244for.end:                                          ; preds = %for.body
245  %arrayidx5 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
246  %1 = load i32, ptr %arrayidx5, align 4
247  ret i32 %1
248}
249
250; /// Different objects, negative induction, shortening slide
251; int noAlias08 (int a) {
252;   int i;
253;   for (i=0; i<SIZE-10; i++)
254;     Foo.A[SIZE-i-1] = Foo.B[SIZE-i-10] + a;
255;   return Foo.A[a];
256; }
257; CHECK-LABEL: define i32 @noAlias08(
258; CHECK: load <4 x i32>
259; CHECK: ret
260
261define i32 @noAlias08(i32 %a) #0 {
262entry:
263  br label %for.body
264
265for.body:                                         ; preds = %entry, %for.body
266  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
267  %sub1 = sub nuw nsw i32 90, %i.05
268  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %sub1
269  %0 = load i32, ptr %arrayidx, align 4
270  %add = add nsw i32 %0, %a
271  %sub3 = sub nuw nsw i32 99, %i.05
272  %arrayidx4 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %sub3
273  store i32 %add, ptr %arrayidx4, align 4
274  %inc = add nuw nsw i32 %i.05, 1
275  %exitcond.not = icmp eq i32 %inc, 90
276  br i1 %exitcond.not, label %for.end, label %for.body
277
278for.end:                                          ; preds = %for.body
279  %arrayidx5 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
280  %1 = load i32, ptr %arrayidx5, align 4
281  ret i32 %1
282}
283
284; /// Different objects, negative induction, widening slide
285; int noAlias09 (int a) {
286;   int i;
287;   for (i=0; i<SIZE; i++)
288;     Foo.A[SIZE-i-10] = Foo.B[SIZE-i-1] + a;
289;   return Foo.A[a];
290; }
291; CHECK-LABEL: define i32 @noAlias09(
292; CHECK: load <4 x i32>
293; CHECK: ret
294
295define i32 @noAlias09(i32 %a) #0 {
296entry:
297  br label %for.body
298
299for.body:                                         ; preds = %entry, %for.body
300  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
301  %sub1 = sub nuw nsw i32 99, %i.05
302  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %sub1
303  %0 = load i32, ptr %arrayidx, align 4
304  %add = add nsw i32 %0, %a
305  %sub3 = sub nsw i32 90, %i.05
306  %arrayidx4 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %sub3
307  store i32 %add, ptr %arrayidx4, align 4
308  %inc = add nuw nsw i32 %i.05, 1
309  %exitcond.not = icmp eq i32 %inc, 100
310  br i1 %exitcond.not, label %for.end, label %for.body
311
312for.end:                                          ; preds = %for.body
313  %arrayidx5 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
314  %1 = load i32, ptr %arrayidx5, align 4
315  ret i32 %1
316}
317
318; /// Pointer access, negative stride, run-time check added
319; int noAlias10 (int a) {
320;   int i;
321;   for (i=0; i<SIZE; i++)
322;     *(PA+SIZE-i-1) = *(PB+SIZE-i-1) + a;
323;   return *(PA+a);
324; }
325; CHECK-LABEL: define i32 @noAlias10(
326; CHECK-NOT: sub {{.*}} <4 x i32>
327; CHECK: ret
328;
329; TODO: This test vectorizes (with run-time check) on real targets with -O3)
330; Check why it's not being vectorized even when forcing vectorization
331
332define i32 @noAlias10(i32 %a) #0 {
333entry:
334  br label %for.body
335
336for.body:                                         ; preds = %entry, %for.body
337  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
338  %0 = load ptr, ptr @PB, align 4
339  %add.ptr = getelementptr inbounds i8, ptr %0, i32 400
340  %idx.neg = sub nsw i32 0, %i.05
341  %add.ptr1 = getelementptr inbounds i32, ptr %add.ptr, i32 %idx.neg
342  %add.ptr2 = getelementptr inbounds i8, ptr %add.ptr1, i32 -4
343  %1 = load i32, ptr %add.ptr2, align 4
344  %add = add nsw i32 %1, %a
345  %2 = load ptr, ptr @PA, align 4
346  %add.ptr3 = getelementptr inbounds i8, ptr %2, i32 400
347  %add.ptr5 = getelementptr inbounds i32, ptr %add.ptr3, i32 %idx.neg
348  %add.ptr6 = getelementptr inbounds i8, ptr %add.ptr5, i32 -4
349  store i32 %add, ptr %add.ptr6, align 4
350  %inc = add nuw nsw i32 %i.05, 1
351  %exitcond.not = icmp eq i32 %inc, 100
352  br i1 %exitcond.not, label %for.end, label %for.body
353
354for.end:                                          ; preds = %for.body
355  %3 = load ptr, ptr @PA, align 4
356  %add.ptr7 = getelementptr inbounds i32, ptr %3, i32 %a
357  %4 = load i32, ptr %add.ptr7, align 4
358  ret i32 %4
359}
360
361; /// Different objects, negative induction, multi-array
362; int noAlias11 (int a) {
363;   int i, N=10;
364;   for (i=0; i<SIZE; i++)
365;     Bar.A[N][SIZE-i-1] = Bar.B[N][SIZE-i-1] + a;
366;   return Bar.A[N][a];
367; }
368; CHECK-LABEL: define i32 @noAlias11(
369; CHECK: store <4 x i32>
370; CHECK: ret
371
372define i32 @noAlias11(i32 %a) #0 {
373entry:
374  br label %for.body
375
376for.body:                                         ; preds = %entry, %for.body
377  %i.07 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
378  %sub1 = sub nuw nsw i32 99, %i.07
379  %arrayidx2 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 2, i32 10, i32 %sub1
380  %0 = load i32, ptr %arrayidx2, align 4
381  %add = add nsw i32 %0, %a
382  %arrayidx6 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 10, i32 %sub1
383  store i32 %add, ptr %arrayidx6, align 4
384  %inc = add nuw nsw i32 %i.07, 1
385  %exitcond.not = icmp eq i32 %inc, 100
386  br i1 %exitcond.not, label %for.end, label %for.body
387
388for.end:                                          ; preds = %for.body
389  %arrayidx8 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 10, i32 %a
390  %1 = load i32, ptr %arrayidx8, align 4
391  ret i32 %1
392}
393
394; /// Same objects, negative induction, multi-array, different sub-elements
395; int noAlias12 (int a) {
396;   int i, N=10;
397;   for (i=0; i<SIZE; i++)
398;     Bar.A[N][SIZE-i-1] = Bar.A[N+1][SIZE-i-1] + a;
399;   return Bar.A[N][a];
400; }
401; CHECK-LABEL: define i32 @noAlias12(
402; CHECK: store <4 x i32>
403; CHECK: ret
404
405define i32 @noAlias12(i32 %a) #0 {
406entry:
407  br label %for.body
408
409for.body:                                         ; preds = %entry, %for.body
410  %i.07 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
411  %sub1 = sub nuw nsw i32 99, %i.07
412  %arrayidx2 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 11, i32 %sub1
413  %0 = load i32, ptr %arrayidx2, align 4
414  %add3 = add nsw i32 %0, %a
415  %arrayidx7 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 10, i32 %sub1
416  store i32 %add3, ptr %arrayidx7, align 4
417  %inc = add nuw nsw i32 %i.07, 1
418  %exitcond.not = icmp eq i32 %inc, 100
419  br i1 %exitcond.not, label %for.end, label %for.body
420
421for.end:                                          ; preds = %for.body
422  %arrayidx9 = getelementptr inbounds %struct.anon.0, ptr @Bar, i32 0, i32 0, i32 10, i32 %a
423  %1 = load i32, ptr %arrayidx9, align 4
424  ret i32 %1
425}
426
427; /// Same objects, positive induction, constant distance, just enough for vector size
428; int noAlias13 (int a) {
429;   int i;
430;   for (i=0; i<SIZE; i++)
431;     Foo.A[i] = Foo.A[i+4] + a;
432;   return Foo.A[a];
433; }
434; CHECK-LABEL: define i32 @noAlias13(
435; CHECK: add nsw <4 x i32>
436; CHECK: ret
437
438define i32 @noAlias13(i32 %a) #0 {
439entry:
440  br label %for.body
441
442for.body:                                         ; preds = %entry, %for.body
443  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
444  %add = add nuw nsw i32 %i.05, 4
445  %arrayidx = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %add
446  %0 = load i32, ptr %arrayidx, align 4
447  %add1 = add nsw i32 %0, %a
448  %arrayidx2 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %i.05
449  store i32 %add1, ptr %arrayidx2, align 4
450  %inc = add nuw nsw i32 %i.05, 1
451  %exitcond.not = icmp eq i32 %inc, 100
452  br i1 %exitcond.not, label %for.end, label %for.body
453
454for.end:                                          ; preds = %for.body
455  %arrayidx3 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
456  %1 = load i32, ptr %arrayidx3, align 4
457  ret i32 %1
458}
459
460; /// Same objects, negative induction, constant distance, just enough for vector size
461; int noAlias14 (int a) {
462;   int i;
463;   for (i=0; i<SIZE; i++)
464;     Foo.A[SIZE-i-1] = Foo.A[SIZE-i-5] + a;
465;   return Foo.A[a];
466; }
467; CHECK-LABEL: define i32 @noAlias14(
468; CHECK: load <4 x i32>
469; CHECK: ret
470
471define i32 @noAlias14(i32 %a) #0 {
472entry:
473  br label %for.body
474
475for.body:                                         ; preds = %entry, %for.body
476  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
477  %sub1 = sub nsw i32 95, %i.05
478  %arrayidx = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %sub1
479  %0 = load i32, ptr %arrayidx, align 4
480  %add = add nsw i32 %0, %a
481  %sub3 = sub nuw nsw i32 99, %i.05
482  %arrayidx4 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %sub3
483  store i32 %add, ptr %arrayidx4, align 4
484  %inc = add nuw nsw i32 %i.05, 1
485  %exitcond.not = icmp eq i32 %inc, 100
486  br i1 %exitcond.not, label %for.end, label %for.body
487
488for.end:                                          ; preds = %for.body
489  %arrayidx5 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
490  %1 = load i32, ptr %arrayidx5, align 4
491  ret i32 %1
492}
493
494
495;; === Now, the tests that we could vectorize with induction changes or run-time checks ===
496
497
498; /// Different objects, swapped induction, alias at the end
499; int mayAlias01 (int a) {
500;   int i;
501;   for (i=0; i<SIZE; i++)
502;     Foo.A[i] = Foo.B[SIZE-i-1] + a;
503;   return Foo.A[a];
504; }
505; CHECK-LABEL: define i32 @mayAlias01(
506; CHECK-NOT: add nsw <4 x i32>
507; CHECK: ret
508
509define i32 @mayAlias01(i32 %a) nounwind {
510entry:
511  br label %for.body
512
513for.body:                                         ; preds = %entry, %for.body
514  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
515  %sub1 = sub nuw nsw i32 99, %i.05
516  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %sub1
517  %0 = load i32, ptr %arrayidx, align 4
518  %add = add nsw i32 %0, %a
519  %arrayidx2 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %i.05
520  store i32 %add, ptr %arrayidx2, align 4
521  %inc = add nuw nsw i32 %i.05, 1
522  %exitcond.not = icmp eq i32 %inc, 100
523  br i1 %exitcond.not, label %for.end, label %for.body
524
525for.end:                                          ; preds = %for.body
526  %arrayidx3 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
527  %1 = load i32, ptr %arrayidx3, align 4
528  ret i32 %1
529}
530
531; /// Different objects, swapped induction, alias at the beginning
532; int mayAlias02 (int a) {
533;   int i;
534;   for (i=0; i<SIZE; i++)
535;     Foo.A[SIZE-i-1] = Foo.B[i] + a;
536;   return Foo.A[a];
537; }
538; CHECK-LABEL: define i32 @mayAlias02(
539; CHECK-NOT: add nsw <4 x i32>
540; CHECK: ret
541
542define i32 @mayAlias02(i32 %a) nounwind {
543entry:
544  br label %for.body
545
546for.body:                                         ; preds = %entry, %for.body
547  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
548  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %i.05
549  %0 = load i32, ptr %arrayidx, align 4
550  %add = add nsw i32 %0, %a
551  %sub1 = sub nuw nsw i32 99, %i.05
552  %arrayidx2 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %sub1
553  store i32 %add, ptr %arrayidx2, align 4
554  %inc = add nuw nsw i32 %i.05, 1
555  %exitcond.not = icmp eq i32 %inc, 100
556  br i1 %exitcond.not, label %for.end, label %for.body
557
558for.end:                                          ; preds = %for.body
559  %arrayidx3 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
560  %1 = load i32, ptr %arrayidx3, align 4
561  ret i32 %1
562}
563
564; /// Pointer access, run-time check added
565; int mayAlias03 (int a) {
566;   int i;
567;   for (i=0; i<SIZE; i++)
568;     *(PA+i) = *(PB+SIZE-i-1) + a;
569;   return *(PA+a);
570; }
571; CHECK-LABEL: define i32 @mayAlias03(
572; CHECK-NOT: add nsw <4 x i32>
573; CHECK: ret
574
575define i32 @mayAlias03(i32 %a) nounwind {
576entry:
577  br label %for.body
578
579for.body:                                         ; preds = %entry, %for.body
580  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
581  %0 = load ptr, ptr @PB, align 4
582  %add.ptr = getelementptr inbounds i8, ptr %0, i32 400
583  %idx.neg = sub nsw i32 0, %i.05
584  %add.ptr1 = getelementptr inbounds i32, ptr %add.ptr, i32 %idx.neg
585  %add.ptr2 = getelementptr inbounds i8, ptr %add.ptr1, i32 -4
586  %1 = load i32, ptr %add.ptr2, align 4
587  %add = add nsw i32 %1, %a
588  %2 = load ptr, ptr @PA, align 4
589  %add.ptr3 = getelementptr inbounds i32, ptr %2, i32 %i.05
590  store i32 %add, ptr %add.ptr3, align 4
591  %inc = add nuw nsw i32 %i.05, 1
592  %exitcond.not = icmp eq i32 %inc, 100
593  br i1 %exitcond.not, label %for.end, label %for.body
594
595for.end:                                          ; preds = %for.body
596  %3 = load ptr, ptr @PA, align 4
597  %add.ptr4 = getelementptr inbounds i32, ptr %3, i32 %a
598  %4 = load i32, ptr %add.ptr4, align 4
599  ret i32 %4
600}
601
602;; === Finally, the tests that should only vectorize with care (or if we ignore undefined behaviour at all) ===
603
604
605; int mustAlias01 (int a) {
606;   int i;
607;   for (i=0; i<SIZE; i++)
608;     Foo.A[i+10] = Foo.B[SIZE-i-1] + a;
609;   return Foo.A[a];
610; }
611; CHECK-LABEL: define i32 @mustAlias01(
612; CHECK-NOT: add nsw <4 x i32>
613; CHECK: ret
614
615define i32 @mustAlias01(i32 %a) nounwind {
616entry:
617  br label %for.body
618
619for.body:                                         ; preds = %entry, %for.body
620  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
621  %sub1 = sub nuw nsw i32 99, %i.05
622  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %sub1
623  %0 = load i32, ptr %arrayidx, align 4
624  %add = add nsw i32 %0, %a
625  %add2 = add nuw nsw i32 %i.05, 10
626  %arrayidx3 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %add2
627  store i32 %add, ptr %arrayidx3, align 4
628  %inc = add nuw nsw i32 %i.05, 1
629  %exitcond.not = icmp eq i32 %inc, 100
630  br i1 %exitcond.not, label %for.end, label %for.body
631
632for.end:                                          ; preds = %for.body
633  %arrayidx4 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
634  %1 = load i32, ptr %arrayidx4, align 4
635  ret i32 %1
636}
637
638; int mustAlias02 (int a) {
639;   int i;
640;   for (i=0; i<SIZE; i++)
641;     Foo.A[i] = Foo.B[SIZE-i-10] + a;
642;   return Foo.A[a];
643; }
644; CHECK-LABEL: define i32 @mustAlias02(
645; CHECK-NOT: add nsw <4 x i32>
646; CHECK: ret
647
648define i32 @mustAlias02(i32 %a) nounwind {
649entry:
650  br label %for.body
651
652for.body:                                         ; preds = %entry, %for.body
653  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
654  %sub1 = sub nsw i32 90, %i.05
655  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %sub1
656  %0 = load i32, ptr %arrayidx, align 4
657  %add = add nsw i32 %0, %a
658  %arrayidx2 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %i.05
659  store i32 %add, ptr %arrayidx2, align 4
660  %inc = add nuw nsw i32 %i.05, 1
661  %exitcond.not = icmp eq i32 %inc, 100
662  br i1 %exitcond.not, label %for.end, label %for.body
663
664for.end:                                          ; preds = %for.body
665  %arrayidx3 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
666  %1 = load i32, ptr %arrayidx3, align 4
667  ret i32 %1
668}
669
670; int mustAlias03 (int a) {
671;   int i;
672;   for (i=0; i<SIZE; i++)
673;     Foo.A[i+10] = Foo.B[SIZE-i-10] + a;
674;   return Foo.A[a];
675; }
676; CHECK-LABEL: define i32 @mustAlias03(
677; CHECK-NOT: add nsw <4 x i32>
678; CHECK: ret
679
680define i32 @mustAlias03(i32 %a) nounwind {
681entry:
682  br label %for.body
683
684for.body:                                         ; preds = %entry, %for.body
685  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
686  %sub1 = sub nsw i32 90, %i.05
687  %arrayidx = getelementptr inbounds %struct.anon, ptr @Foo, i32 0, i32 2, i32 %sub1
688  %0 = load i32, ptr %arrayidx, align 4
689  %add = add nsw i32 %0, %a
690  %add2 = add nuw nsw i32 %i.05, 10
691  %arrayidx3 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %add2
692  store i32 %add, ptr %arrayidx3, align 4
693  %inc = add nuw nsw i32 %i.05, 1
694  %exitcond.not = icmp eq i32 %inc, 100
695  br i1 %exitcond.not, label %for.end, label %for.body
696
697for.end:                                          ; preds = %for.body
698  %arrayidx4 = getelementptr inbounds [100 x i32], ptr @Foo, i32 0, i32 %a
699  %1 = load i32, ptr %arrayidx4, align 4
700  ret i32 %1
701}
702