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