1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=loop-idiom < %s -S | FileCheck %s
3 target 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"
5 %struct.foo = type { i32, i32 }
6 %struct.foo1 = type { i32, i32, i32 }
7 %struct.foo2 = type { i32, i16, i16 }
9 ;void bar1(foo_t *f, unsigned n) {
10 ; for (unsigned i = 0; i < n; ++i) {
15 define void @bar1(ptr %f, i32 %n) nounwind ssp {
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:%.*]]
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]]
34 ; CHECK-NEXT: ret void
37 %cmp1 = icmp eq i32 %n, 0
38 br i1 %cmp1, label %for.end, label %for.body.preheader
40 for.body.preheader: ; preds = %entry
43 for.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
53 for.end.loopexit: ; preds = %for.body
56 for.end: ; preds = %for.end.loopexit, %entry
60 ;void bar2(foo_t *f, unsigned n) {
61 ; for (unsigned i = 0; i < n; ++i) {
66 define void @bar2(ptr %f, i32 %n) nounwind ssp {
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:%.*]]
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]]
85 ; CHECK-NEXT: ret void
88 %cmp1 = icmp eq i32 %n, 0
89 br i1 %cmp1, label %for.end, label %for.body.preheader
91 for.body.preheader: ; preds = %entry
94 for.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
104 for.end.loopexit: ; preds = %for.body
107 for.end: ; preds = %for.end.loopexit, %entry
111 ;void bar3(foo_t *f, unsigned n) {
112 ; for (unsigned i = n; i > 0; --i) {
117 define void @bar3(ptr nocapture %f, i32 %n) nounwind ssp {
118 ; CHECK-LABEL: @bar3(
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:%.*]]
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]]
138 ; CHECK-NEXT: ret void
141 %cmp1 = icmp eq i32 %n, 0
142 br i1 %cmp1, label %for.end, label %for.body.preheader
144 for.body.preheader: ; preds = %entry
147 for.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
158 for.end.loopexit: ; preds = %for.body
161 for.end: ; preds = %for.end.loopexit, %entry
165 ;void bar4(foo_t *f, unsigned n) {
166 ; for (unsigned i = 0; i < n; ++i) {
171 define void @bar4(ptr nocapture %f, i32 %n) nounwind ssp {
172 ; CHECK-LABEL: @bar4(
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:%.*]]
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]]
190 ; CHECK-NEXT: ret void
193 %cmp1 = icmp eq i32 %n, 0
194 br i1 %cmp1, label %for.end, label %for.body.preheader
196 for.body.preheader: ; preds = %entry
199 for.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
209 for.end.loopexit: ; preds = %for.body
212 for.end: ; preds = %for.end.loopexit, %entry
216 ;void bar5(foo1_t *f, unsigned n) {
217 ; for (unsigned i = 0; i < n; ++i) {
222 define void @bar5(ptr nocapture %f, i32 %n) nounwind ssp {
223 ; CHECK-LABEL: @bar5(
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:%.*]]
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]]
241 ; CHECK-NEXT: ret void
244 %cmp1 = icmp eq i32 %n, 0
245 br i1 %cmp1, label %for.end, label %for.body.preheader
247 for.body.preheader: ; preds = %entry
250 for.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
260 for.end.loopexit: ; preds = %for.body
263 for.end: ; preds = %for.end.loopexit, %entry
267 ;void bar6(foo2_t *f, unsigned n) {
268 ; for (unsigned i = 0; i < n; ++i) {
274 define void @bar6(ptr nocapture %f, i32 %n) nounwind ssp {
275 ; CHECK-LABEL: @bar6(
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:%.*]]
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]]
294 ; CHECK-NEXT: ret void
297 %cmp1 = icmp eq i32 %n, 0
298 br i1 %cmp1, label %for.end, label %for.body.preheader
300 for.body.preheader: ; preds = %entry
303 for.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
315 for.end.loopexit: ; preds = %for.body
318 for.end: ; preds = %for.end.loopexit, %entry