1; RUN: opt -basicaa -loop-idiom < %s -S | FileCheck %s
2target datalayout = "e-p:64:64:64-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:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
3
4; CHECK: @.memset_pattern = private unnamed_addr constant [4 x i32] [i32 2, i32 2, i32 2, i32 2], align 16
5; CHECK: @.memset_pattern.1 = private unnamed_addr constant [4 x i32] [i32 2, i32 2, i32 2, i32 2], align 16
6; CHECK: @.memset_pattern.2 = private unnamed_addr constant [4 x i32] [i32 2, i32 2, i32 2, i32 2], align 16
7
8target triple = "x86_64-apple-darwin10.0.0"
9
10%struct.foo = type { i32, i32 }
11%struct.foo1 = type { i32, i32, i32 }
12
13;void bar1(foo_t *f, unsigned n) {
14;  for (unsigned i = 0; i < n; ++i) {
15;    f[i].a = 2;
16;    f[i].b = 2;
17;  }
18;}
19define void @bar1(%struct.foo* %f, i32 %n) nounwind ssp {
20entry:
21  %cmp1 = icmp eq i32 %n, 0
22  br i1 %cmp1, label %for.end, label %for.body.preheader
23
24for.body.preheader:                               ; preds = %entry
25  br label %for.body
26
27for.body:                                         ; preds = %for.body.preheader, %for.body
28  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
29  %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 %indvars.iv, i32 0
30  store i32 2, i32* %a, align 4
31  %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 %indvars.iv, i32 1
32  store i32 2, i32* %b, align 4
33  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
34  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
35  %exitcond = icmp ne i32 %lftr.wideiv, %n
36  br i1 %exitcond, label %for.body, label %for.end.loopexit
37
38for.end.loopexit:                                 ; preds = %for.body
39  br label %for.end
40
41for.end:                                          ; preds = %for.end.loopexit, %entry
42  ret void
43; CHECK-LABEL: @bar1(
44; CHECK: call void @memset_pattern16
45; CHECK-NOT: store
46}
47
48;void bar2(foo_t *f, unsigned n) {
49;  for (unsigned i = 0; i < n; ++i) {
50;    f[i].b = 2;
51;    f[i].a = 2;
52;  }
53;}
54define void @bar2(%struct.foo* %f, i32 %n) nounwind ssp {
55entry:
56  %cmp1 = icmp eq i32 %n, 0
57  br i1 %cmp1, label %for.end, label %for.body.preheader
58
59for.body.preheader:                               ; preds = %entry
60  br label %for.body
61
62for.body:                                         ; preds = %for.body.preheader, %for.body
63  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
64  %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 %indvars.iv, i32 1
65  store i32 2, i32* %b, align 4
66  %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 %indvars.iv, i32 0
67  store i32 2, i32* %a, align 4
68  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
69  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
70  %exitcond = icmp ne i32 %lftr.wideiv, %n
71  br i1 %exitcond, label %for.body, label %for.end.loopexit
72
73for.end.loopexit:                                 ; preds = %for.body
74  br label %for.end
75
76for.end:                                          ; preds = %for.end.loopexit, %entry
77  ret void
78; CHECK-LABEL: @bar2(
79; CHECK: call void @memset_pattern16
80; CHECK-NOT: store
81}
82
83;void bar3(foo_t *f, unsigned n) {
84;  for (unsigned i = n; i > 0; --i) {
85;    f[i].a = 2;
86;    f[i].b = 2;
87;  }
88;}
89define void @bar3(%struct.foo* nocapture %f, i32 %n) nounwind ssp {
90entry:
91  %cmp1 = icmp eq i32 %n, 0
92  br i1 %cmp1, label %for.end, label %for.body.preheader
93
94for.body.preheader:                               ; preds = %entry
95  %0 = zext i32 %n to i64
96  br label %for.body
97
98for.body:                                         ; preds = %for.body.preheader, %for.body
99  %indvars.iv = phi i64 [ %0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
100  %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 %indvars.iv, i32 0
101  store i32 2, i32* %a, align 4
102  %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 %indvars.iv, i32 1
103  store i32 2, i32* %b, align 4
104  %1 = trunc i64 %indvars.iv to i32
105  %dec = add i32 %1, -1
106  %cmp = icmp eq i32 %dec, 0
107  %indvars.iv.next = add nsw i64 %indvars.iv, -1
108  br i1 %cmp, label %for.end.loopexit, label %for.body
109
110for.end.loopexit:                                 ; preds = %for.body
111  br label %for.end
112
113for.end:                                          ; preds = %for.end.loopexit, %entry
114  ret void
115; CHECK-LABEL: @bar3(
116; CHECK: call void @memset_pattern16
117; CHECK-NOT: store
118}
119
120;void bar4(foo_t *f, unsigned n) {
121;  for (unsigned i = 0; i < n; ++i) {
122;    f[i].a = 0;
123;    f[i].b = 1;
124;  }
125;}
126define void @bar4(%struct.foo* nocapture %f, i32 %n) nounwind ssp {
127entry:
128  %cmp1 = icmp eq i32 %n, 0
129  br i1 %cmp1, label %for.end, label %for.body.preheader
130
131for.body.preheader:                               ; preds = %entry
132  br label %for.body
133
134for.body:                                         ; preds = %for.body.preheader, %for.body
135  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
136  %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 %indvars.iv, i32 0
137  store i32 0, i32* %a, align 4
138  %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 %indvars.iv, i32 1
139  store i32 1, i32* %b, align 4
140  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
141  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
142  %exitcond = icmp ne i32 %lftr.wideiv, %n
143  br i1 %exitcond, label %for.body, label %for.end.loopexit
144
145for.end.loopexit:                                 ; preds = %for.body
146  br label %for.end
147
148for.end:                                          ; preds = %for.end.loopexit, %entry
149  ret void
150; CHECK-LABEL: @bar4(
151; CHECK-NOT: call void @memset_pattern16
152}
153
154;void bar5(foo1_t *f, unsigned n) {
155;  for (unsigned i = 0; i < n; ++i) {
156;    f[i].a = 1;
157;    f[i].b = 1;
158;  }
159;}
160define void @bar5(%struct.foo1* nocapture %f, i32 %n) nounwind ssp {
161entry:
162  %cmp1 = icmp eq i32 %n, 0
163  br i1 %cmp1, label %for.end, label %for.body.preheader
164
165for.body.preheader:                               ; preds = %entry
166  br label %for.body
167
168for.body:                                         ; preds = %for.body.preheader, %for.body
169  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
170  %a = getelementptr inbounds %struct.foo1, %struct.foo1* %f, i64 %indvars.iv, i32 0
171  store i32 1, i32* %a, align 4
172  %b = getelementptr inbounds %struct.foo1, %struct.foo1* %f, i64 %indvars.iv, i32 1
173  store i32 1, i32* %b, align 4
174  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
175  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
176  %exitcond = icmp ne i32 %lftr.wideiv, %n
177  br i1 %exitcond, label %for.body, label %for.end.loopexit
178
179for.end.loopexit:                                 ; preds = %for.body
180  br label %for.end
181
182for.end:                                          ; preds = %for.end.loopexit, %entry
183  ret void
184; CHECK-LABEL: @bar5(
185; CHECK-NOT: call void @memset_pattern16
186}
187