1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -basic-aa -loop-idiom < %s -S | FileCheck %s
3target datalayout = "e-p:40:64:64: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:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
4
5%struct.foo = type { i32, i32 }
6%struct.foo1 = type { i32, i32, i32 }
7%struct.foo2 = type { i32, i16, i16 }
8
9;void bar1(foo_t *f, unsigned n) {
10;  for (unsigned i = 0; i < n; ++i) {
11;    f[i].a = 0;
12;    f[i].b = 0;
13;  }
14;}
15define void @bar1(%struct.foo* %f, i32 %n) nounwind ssp {
16; CHECK-LABEL: @bar1(
17; CHECK-NEXT:  entry:
18; CHECK-NEXT:    [[F1:%.*]] = bitcast %struct.foo* [[F:%.*]] to i8*
19; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0
20; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
21; CHECK:       for.body.preheader:
22; CHECK-NEXT:    [[TMP0:%.*]] = shl nuw i32 [[N]], 3
23; CHECK-NEXT:    call void @llvm.memset.p0i8.i32(i8* align 4 [[F1]], i8 0, i32 [[TMP0]], i1 false)
24; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
25; CHECK:       for.body:
26; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
27; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 0
28; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 1
29; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1
30; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]]
31; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
32; CHECK:       for.end.loopexit:
33; CHECK-NEXT:    br label [[FOR_END]]
34; CHECK:       for.end:
35; CHECK-NEXT:    ret void
36;
37entry:
38  %cmp1 = icmp eq i32 %n, 0
39  br i1 %cmp1, label %for.end, label %for.body.preheader
40
41for.body.preheader:                               ; preds = %entry
42  br label %for.body
43
44for.body:                                         ; preds = %for.body.preheader, %for.body
45  %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
46  %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 0
47  store i32 0, i32* %a, align 4
48  %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 1
49  store i32 0, i32* %b, align 4
50  %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1
51  %exitcond = icmp ne i32 %indvars.iv.next, %n
52  br i1 %exitcond, label %for.body, label %for.end.loopexit
53
54for.end.loopexit:                                 ; preds = %for.body
55  br label %for.end
56
57for.end:                                          ; preds = %for.end.loopexit, %entry
58  ret void
59}
60
61;void bar2(foo_t *f, unsigned n) {
62;  for (unsigned i = 0; i < n; ++i) {
63;    f[i].b = 0;
64;    f[i].a = 0;
65;  }
66;}
67define void @bar2(%struct.foo* %f, i32 %n) nounwind ssp {
68; CHECK-LABEL: @bar2(
69; CHECK-NEXT:  entry:
70; CHECK-NEXT:    [[F1:%.*]] = bitcast %struct.foo* [[F:%.*]] to i8*
71; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0
72; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
73; CHECK:       for.body.preheader:
74; CHECK-NEXT:    [[TMP0:%.*]] = shl nuw i32 [[N]], 3
75; CHECK-NEXT:    call void @llvm.memset.p0i8.i32(i8* align 4 [[F1]], i8 0, i32 [[TMP0]], i1 false)
76; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
77; CHECK:       for.body:
78; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
79; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 1
80; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 0
81; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1
82; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]]
83; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
84; CHECK:       for.end.loopexit:
85; CHECK-NEXT:    br label [[FOR_END]]
86; CHECK:       for.end:
87; CHECK-NEXT:    ret void
88;
89entry:
90  %cmp1 = icmp eq i32 %n, 0
91  br i1 %cmp1, label %for.end, label %for.body.preheader
92
93for.body.preheader:                               ; preds = %entry
94  br label %for.body
95
96for.body:                                         ; preds = %for.body.preheader, %for.body
97  %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
98  %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 1
99  store i32 0, i32* %b, align 4
100  %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 0
101  store i32 0, i32* %a, align 4
102  %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1
103  %exitcond = icmp ne i32 %indvars.iv.next, %n
104  br i1 %exitcond, label %for.body, label %for.end.loopexit
105
106for.end.loopexit:                                 ; preds = %for.body
107  br label %for.end
108
109for.end:                                          ; preds = %for.end.loopexit, %entry
110  ret void
111}
112
113;void bar3(foo_t *f, unsigned n) {
114;  for (unsigned i = n; i > 0; --i) {
115;    f[i].a = 0;
116;    f[i].b = 0;
117;  }
118;}
119define void @bar3(%struct.foo* nocapture %f, i32 %n) nounwind ssp {
120; CHECK-LABEL: @bar3(
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0
123; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
124; CHECK:       for.body.preheader:
125; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr [[STRUCT_FOO:%.*]], %struct.foo* [[F:%.*]], i32 1
126; CHECK-NEXT:    [[SCEVGEP1:%.*]] = bitcast %struct.foo* [[SCEVGEP]] to i8*
127; CHECK-NEXT:    [[TMP0:%.*]] = shl nuw i32 [[N]], 3
128; CHECK-NEXT:    call void @llvm.memset.p0i8.i32(i8* align 4 [[SCEVGEP1]], i8 0, i32 [[TMP0]], i1 false)
129; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
130; CHECK:       for.body:
131; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i32 [ [[N]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
132; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 0
133; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 1
134; CHECK-NEXT:    [[DEC:%.*]] = add i32 [[INDVARS_IV]], -1
135; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[DEC]], 0
136; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nsw i32 [[INDVARS_IV]], -1
137; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
138; CHECK:       for.end.loopexit:
139; CHECK-NEXT:    br label [[FOR_END]]
140; CHECK:       for.end:
141; CHECK-NEXT:    ret void
142;
143entry:
144  %cmp1 = icmp eq i32 %n, 0
145  br i1 %cmp1, label %for.end, label %for.body.preheader
146
147for.body.preheader:                               ; preds = %entry
148  br label %for.body
149
150for.body:                                         ; preds = %for.body.preheader, %for.body
151  %indvars.iv = phi i32 [ %n, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
152  %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 0
153  store i32 0, i32* %a, align 4
154  %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 1
155  store i32 0, i32* %b, align 4
156  %dec = add i32 %indvars.iv, -1
157  %cmp = icmp eq i32 %dec, 0
158  %indvars.iv.next = add nsw i32 %indvars.iv, -1
159  br i1 %cmp, label %for.end.loopexit, label %for.body
160
161for.end.loopexit:                                 ; preds = %for.body
162  br label %for.end
163
164for.end:                                          ; preds = %for.end.loopexit, %entry
165  ret void
166}
167
168;void bar4(foo_t *f, unsigned n) {
169;  for (unsigned i = 0; i < n; ++i) {
170;    f[i].a = 0;
171;    f[i].b = 1;
172;  }
173;}
174define void @bar4(%struct.foo* nocapture %f, i32 %n) nounwind ssp {
175; CHECK-LABEL: @bar4(
176; CHECK-NEXT:  entry:
177; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0
178; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
179; CHECK:       for.body.preheader:
180; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
181; CHECK:       for.body:
182; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
183; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], %struct.foo* [[F:%.*]], i32 [[INDVARS_IV]], i32 0
184; CHECK-NEXT:    store i32 0, i32* [[A]], align 4
185; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO]], %struct.foo* [[F]], i32 [[INDVARS_IV]], i32 1
186; CHECK-NEXT:    store i32 1, i32* [[B]], align 4
187; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1
188; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]]
189; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
190; CHECK:       for.end.loopexit:
191; CHECK-NEXT:    br label [[FOR_END]]
192; CHECK:       for.end:
193; CHECK-NEXT:    ret void
194;
195entry:
196  %cmp1 = icmp eq i32 %n, 0
197  br i1 %cmp1, label %for.end, label %for.body.preheader
198
199for.body.preheader:                               ; preds = %entry
200  br label %for.body
201
202for.body:                                         ; preds = %for.body.preheader, %for.body
203  %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
204  %a = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 0
205  store i32 0, i32* %a, align 4
206  %b = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 %indvars.iv, i32 1
207  store i32 1, i32* %b, align 4
208  %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1
209  %exitcond = icmp ne i32 %indvars.iv.next, %n
210  br i1 %exitcond, label %for.body, label %for.end.loopexit
211
212for.end.loopexit:                                 ; preds = %for.body
213  br label %for.end
214
215for.end:                                          ; preds = %for.end.loopexit, %entry
216  ret void
217}
218
219;void bar5(foo1_t *f, unsigned n) {
220;  for (unsigned i = 0; i < n; ++i) {
221;    f[i].a = 0;
222;    f[i].b = 0;
223;  }
224;}
225define void @bar5(%struct.foo1* nocapture %f, i32 %n) nounwind ssp {
226; CHECK-LABEL: @bar5(
227; CHECK-NEXT:  entry:
228; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0
229; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
230; CHECK:       for.body.preheader:
231; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
232; CHECK:       for.body:
233; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
234; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO1:%.*]], %struct.foo1* [[F:%.*]], i32 [[INDVARS_IV]], i32 0
235; CHECK-NEXT:    store i32 0, i32* [[A]], align 4
236; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO1]], %struct.foo1* [[F]], i32 [[INDVARS_IV]], i32 1
237; CHECK-NEXT:    store i32 0, i32* [[B]], align 4
238; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1
239; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]]
240; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
241; CHECK:       for.end.loopexit:
242; CHECK-NEXT:    br label [[FOR_END]]
243; CHECK:       for.end:
244; CHECK-NEXT:    ret void
245;
246entry:
247  %cmp1 = icmp eq i32 %n, 0
248  br i1 %cmp1, label %for.end, label %for.body.preheader
249
250for.body.preheader:                               ; preds = %entry
251  br label %for.body
252
253for.body:                                         ; preds = %for.body.preheader, %for.body
254  %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
255  %a = getelementptr inbounds %struct.foo1, %struct.foo1* %f, i32 %indvars.iv, i32 0
256  store i32 0, i32* %a, align 4
257  %b = getelementptr inbounds %struct.foo1, %struct.foo1* %f, i32 %indvars.iv, i32 1
258  store i32 0, i32* %b, align 4
259  %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1
260  %exitcond = icmp ne i32 %indvars.iv.next, %n
261  br i1 %exitcond, label %for.body, label %for.end.loopexit
262
263for.end.loopexit:                                 ; preds = %for.body
264  br label %for.end
265
266for.end:                                          ; preds = %for.end.loopexit, %entry
267  ret void
268}
269
270;void bar6(foo2_t *f, unsigned n) {
271;  for (unsigned i = 0; i < n; ++i) {
272;    f[i].a = 0;
273;    f[i].b = 0;
274;    f[i].c = 0;
275;  }
276;}
277define void @bar6(%struct.foo2* nocapture %f, i32 %n) nounwind ssp {
278; CHECK-LABEL: @bar6(
279; CHECK-NEXT:  entry:
280; CHECK-NEXT:    [[F1:%.*]] = bitcast %struct.foo2* [[F:%.*]] to i8*
281; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[N:%.*]], 0
282; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
283; CHECK:       for.body.preheader:
284; CHECK-NEXT:    [[TMP0:%.*]] = shl nuw i32 [[N]], 3
285; CHECK-NEXT:    call void @llvm.memset.p0i8.i32(i8* align 4 [[F1]], i8 0, i32 [[TMP0]], i1 false)
286; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
287; CHECK:       for.body:
288; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
289; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO2:%.*]], %struct.foo2* [[F]], i32 [[INDVARS_IV]], i32 0
290; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO2]], %struct.foo2* [[F]], i32 [[INDVARS_IV]], i32 1
291; CHECK-NEXT:    [[C:%.*]] = getelementptr inbounds [[STRUCT_FOO2]], %struct.foo2* [[F]], i32 [[INDVARS_IV]], i32 2
292; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1
293; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INDVARS_IV_NEXT]], [[N]]
294; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
295; CHECK:       for.end.loopexit:
296; CHECK-NEXT:    br label [[FOR_END]]
297; CHECK:       for.end:
298; CHECK-NEXT:    ret void
299;
300entry:
301  %cmp1 = icmp eq i32 %n, 0
302  br i1 %cmp1, label %for.end, label %for.body.preheader
303
304for.body.preheader:                               ; preds = %entry
305  br label %for.body
306
307for.body:                                         ; preds = %for.body.preheader, %for.body
308  %indvars.iv = phi i32 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
309  %a = getelementptr inbounds %struct.foo2, %struct.foo2* %f, i32 %indvars.iv, i32 0
310  store i32 0, i32* %a, align 4
311  %b = getelementptr inbounds %struct.foo2, %struct.foo2* %f, i32 %indvars.iv, i32 1
312  store i16 0, i16* %b, align 4
313  %c = getelementptr inbounds %struct.foo2, %struct.foo2* %f, i32 %indvars.iv, i32 2
314  store i16 0, i16* %c, align 2
315  %indvars.iv.next = add nuw nsw i32 %indvars.iv, 1
316  %exitcond = icmp ne i32 %indvars.iv.next, %n
317  br i1 %exitcond, label %for.body, label %for.end.loopexit
318
319for.end.loopexit:                                 ; preds = %for.body
320  br label %for.end
321
322for.end:                                          ; preds = %for.end.loopexit, %entry
323  ret void
324}
325