1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -loop-idiom < %s -S | FileCheck %s
4 ; CHECK: source_filename
8 target 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"
10 define i1 @three_blocks_and_two_latches_in_loop(i8* %ptr0, i8* %ptr1) {
15 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ], [ 0, %for.passthrough ]
16 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
17 %v0 = load i8, i8* %arrayidx
18 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
19 %v1 = load i8, i8* %arrayidx1
20 %cmp3 = icmp eq i8 %v0, %v1
21 %inc = add nuw nsw i64 %i.08, 1
22 br i1 %cmp3, label %for.passthrough, label %cleanup
25 br i1 true, label %for.cond, label %for.body
28 %cmp = icmp ult i64 %inc, 8
29 br i1 %cmp, label %for.body, label %cleanup
32 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
36 define i1 @three_blocks_in_loop(i8* %ptr0, i8* %ptr1) {
41 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
42 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
43 %v0 = load i8, i8* %arrayidx
44 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
45 %v1 = load i8, i8* %arrayidx1
46 %cmp3 = icmp eq i8 %v0, %v1
47 %inc = add nuw nsw i64 %i.08, 1
48 br i1 %cmp3, label %for.passthrough, label %cleanup
54 %cmp = icmp ult i64 %inc, 8
55 br i1 %cmp, label %for.body, label %cleanup
58 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
62 define i1 @exit_block_is_not_dedicated(i8* %ptr0, i8* %ptr1) {
64 br i1 true, label %for.body, label %cleanup
67 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
68 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
69 %v0 = load i8, i8* %arrayidx
70 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
71 %v1 = load i8, i8* %arrayidx1
72 %cmp3 = icmp eq i8 %v0, %v1
73 %inc = add nuw nsw i64 %i.08, 1
74 br i1 %cmp3, label %for.cond, label %cleanup
77 %cmp = icmp ult i64 %inc, 8
78 br i1 %cmp, label %for.body, label %cleanup
81 %res = phi i1 [ false, %for.body ], [ true, %for.cond ], [ false, %entry ]
85 define i1 @body_cmp_is_not_equality(i8* %ptr0, i8* %ptr1) {
90 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
91 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
92 %v0 = load i8, i8* %arrayidx
93 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
94 %v1 = load i8, i8* %arrayidx1
95 %cmp3 = icmp ult i8 %v0, %v1
96 %inc = add nuw nsw i64 %i.08, 1
97 br i1 %cmp3, label %for.cond, label %cleanup
100 %cmp = icmp ult i64 %inc, 8
101 br i1 %cmp, label %for.body, label %cleanup
104 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
108 define i1 @only_one_load(i8* %ptr0, i8* %ptr1) {
113 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
114 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
115 %v0 = load i8, i8* %arrayidx
116 %cmp3 = icmp eq i8 %v0, 0
117 %inc = add nuw nsw i64 %i.08, 1
118 br i1 %cmp3, label %for.cond, label %cleanup
121 %cmp = icmp ult i64 %inc, 8
122 br i1 %cmp, label %for.body, label %cleanup
125 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
129 define i1 @loads_of_less_than_byte(i7* %ptr0, i7* %ptr1) {
134 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
135 %arrayidx = getelementptr inbounds i7, i7* %ptr0, i64 %i.08
136 %v0 = load i7, i7* %arrayidx
137 %arrayidx1 = getelementptr inbounds i7, i7* %ptr1, i64 %i.08
138 %v1 = load i7, i7* %arrayidx1
139 %cmp3 = icmp ult i7 %v0, %v1
140 %inc = add nuw nsw i64 %i.08, 1
141 br i1 %cmp3, label %for.cond, label %cleanup
144 %cmp = icmp ult i64 %inc, 8
145 br i1 %cmp, label %for.body, label %cleanup
148 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
152 define i1 @loads_of_not_multiple_of_a_byte(i9* %ptr0, i9* %ptr1) {
157 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
158 %arrayidx = getelementptr inbounds i9, i9* %ptr0, i64 %i.08
159 %v0 = load i9, i9* %arrayidx
160 %arrayidx1 = getelementptr inbounds i9, i9* %ptr1, i64 %i.08
161 %v1 = load i9, i9* %arrayidx1
162 %cmp3 = icmp ult i9 %v0, %v1
163 %inc = add nuw nsw i64 %i.08, 1
164 br i1 %cmp3, label %for.cond, label %cleanup
167 %cmp = icmp ult i64 %inc, 8
168 br i1 %cmp, label %for.body, label %cleanup
171 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
175 define i1 @loop_instruction_used_in_phi_node_outside_loop(i8* %ptr0, i8* %ptr1) {
180 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
181 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
182 %v0 = load i8, i8* %arrayidx
183 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
184 %v1 = load i8, i8* %arrayidx1
185 %cmp3 = icmp eq i8 %v0, %v1
186 %inc = add nuw nsw i64 %i.08, 1
187 br i1 %cmp3, label %for.cond, label %cleanup
190 %cmp = icmp ult i64 %inc, 8
191 br i1 %cmp, label %for.body, label %cleanup
194 %res = phi i1 [ %cmp3, %for.body ], [ true, %for.cond ]
198 define i1 @loop_has_write(i8* %ptr0, i8* %ptr1, i32* %write) {
203 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
204 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
205 %v0 = load i8, i8* %arrayidx
206 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
207 %v1 = load i8, i8* %arrayidx1
208 %cmp3 = icmp eq i8 %v0, %v1
209 %inc = add nuw nsw i64 %i.08, 1
210 br i1 %cmp3, label %for.cond, label %cleanup
213 %cmp = icmp ult i64 %inc, 8
214 store i32 0, i32* %write
215 br i1 %cmp, label %for.body, label %cleanup
218 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
223 define i1 @loop_has_call(i8* %ptr0, i8* %ptr1, i32* %load) {
228 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
229 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
230 %v0 = load i8, i8* %arrayidx
231 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
232 %v1 = load i8, i8* %arrayidx1
233 %cmp3 = icmp eq i8 %v0, %v1
234 %inc = add nuw nsw i64 %i.08, 1
235 br i1 %cmp3, label %for.cond, label %cleanup
238 %cmp = icmp ult i64 %inc, 8
239 tail call void @sink()
240 br i1 %cmp, label %for.body, label %cleanup
243 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
247 define i1 @loop_has_atomic_load(i8* %ptr0, i8* %ptr1, i32* %load) {
252 %i.08 = phi i64 [ 0, %entry ], [ %inc, %for.cond ]
253 %arrayidx = getelementptr inbounds i8, i8* %ptr0, i64 %i.08
254 %v0 = load i8, i8* %arrayidx
255 %arrayidx1 = getelementptr inbounds i8, i8* %ptr1, i64 %i.08
256 %v1 = load i8, i8* %arrayidx1
257 %cmp3 = icmp eq i8 %v0, %v1
258 %inc = add nuw nsw i64 %i.08, 1
259 br i1 %cmp3, label %for.cond, label %cleanup
262 %cmp = icmp ult i64 %inc, 8
263 %tmp = load atomic i32, i32* %load unordered, align 1
264 br i1 %cmp, label %for.body, label %cleanup
267 %res = phi i1 [ false, %for.body ], [ true, %for.cond ]
271 define i1 @different_load_step(i8* %ptr) {
273 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
277 %i.015 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
278 %ptr1.014 = phi i8* [ %add.ptr, %entry ], [ %add.ptr3, %for.inc ]
279 %ptr0.013 = phi i8* [ %ptr, %entry ], [ %incdec.ptr, %for.inc ]
280 %v0 = load i8, i8* %ptr0.013
281 %v1 = load i8, i8* %ptr1.014
282 %cmp2 = icmp eq i8 %v0, %v1
283 br i1 %cmp2, label %for.inc, label %cleanup
286 %inc = add nuw nsw i64 %i.015, 1
287 %incdec.ptr = getelementptr inbounds i8, i8* %ptr0.013, i64 1
288 %add.ptr3 = getelementptr inbounds i8, i8* %ptr1.014, i64 2
289 %cmp = icmp ult i64 %inc, 16
290 br i1 %cmp, label %for.body, label %cleanup
293 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
297 define i1 @step_is_variable(i8* %ptr, i64 %step) {
299 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
303 %i.015 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
304 %ptr1.014 = phi i8* [ %add.ptr, %entry ], [ %add.ptr3, %for.inc ]
305 %ptr0.013 = phi i8* [ %ptr, %entry ], [ %incdec.ptr, %for.inc ]
306 %v0 = load i8, i8* %ptr0.013
307 %v1 = load i8, i8* %ptr1.014
308 %cmp2 = icmp eq i8 %v0, %v1
309 br i1 %cmp2, label %for.inc, label %cleanup
312 %inc = add nuw nsw i64 %i.015, %step
313 %incdec.ptr = getelementptr inbounds i8, i8* %ptr0.013, i64 1
314 %add.ptr3 = getelementptr inbounds i8, i8* %ptr1.014, i64 1
315 %cmp = icmp ult i64 %inc, 16
316 br i1 %cmp, label %for.body, label %cleanup
319 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
323 define i1 @load_step_is_variable(i8* %ptr, i64 %step) {
325 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
329 %i.015 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
330 %ptr1.014 = phi i8* [ %add.ptr, %entry ], [ %add.ptr3, %for.inc ]
331 %ptr0.013 = phi i8* [ %ptr, %entry ], [ %incdec.ptr, %for.inc ]
332 %v0 = load i8, i8* %ptr0.013
333 %v1 = load i8, i8* %ptr1.014
334 %cmp2 = icmp eq i8 %v0, %v1
335 br i1 %cmp2, label %for.inc, label %cleanup
338 %inc = add nuw nsw i64 %i.015, 1
339 %incdec.ptr = getelementptr inbounds i8, i8* %ptr0.013, i64 %step
340 %add.ptr3 = getelementptr inbounds i8, i8* %ptr1.014, i64 %step
341 %cmp = icmp ult i64 %inc, 16
342 br i1 %cmp, label %for.body, label %cleanup
345 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
349 define i1 @step_and_load_step_is_variable(i8* %ptr, i64 %step) {
351 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
355 %i.015 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
356 %ptr1.014 = phi i8* [ %add.ptr, %entry ], [ %add.ptr3, %for.inc ]
357 %ptr0.013 = phi i8* [ %ptr, %entry ], [ %incdec.ptr, %for.inc ]
358 %v0 = load i8, i8* %ptr0.013
359 %v1 = load i8, i8* %ptr1.014
360 %cmp2 = icmp eq i8 %v0, %v1
361 br i1 %cmp2, label %for.inc, label %cleanup
364 %inc = add nuw nsw i64 %i.015, %step
365 %incdec.ptr = getelementptr inbounds i8, i8* %ptr0.013, i64 %step
366 %add.ptr3 = getelementptr inbounds i8, i8* %ptr1.014, i64 %step
367 %cmp = icmp ult i64 %inc, 16
368 br i1 %cmp, label %for.body, label %cleanup
371 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
375 define i1 @load_step_not_affine(i8* %ptr) {
377 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
381 %i.018 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
382 %ptr1.017 = phi i8* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
383 %ptr0.016 = phi i8* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
384 %v0 = load i8, i8* %ptr0.016
385 %v1 = load i8, i8* %ptr1.017
386 %cmp2 = icmp eq i8 %v0, %v1
387 br i1 %cmp2, label %for.inc, label %cleanup
390 %inc = add nuw nsw i64 %i.018, 1
391 %add.ptr3 = getelementptr inbounds i8, i8* %ptr0.016, i64 %inc
392 %add.ptr4 = getelementptr inbounds i8, i8* %ptr1.017, i64 %inc
393 %cmp = icmp ult i64 %inc, 16
394 br i1 %cmp, label %for.body, label %cleanup
397 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
401 define i1 @no_overlap_between_loads(i8* %ptr) {
403 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
407 %i.016 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
408 %ptr1.015 = phi i8* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
409 %ptr0.014 = phi i8* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
410 %v0 = load i8, i8* %ptr0.014
411 %v1 = load i8, i8* %ptr1.015
412 %cmp2 = icmp eq i8 %v0, %v1
413 br i1 %cmp2, label %for.inc, label %cleanup
416 %inc = add nuw nsw i64 %i.016, 1
417 %add.ptr3 = getelementptr inbounds i8, i8* %ptr0.014, i64 2
418 %add.ptr4 = getelementptr inbounds i8, i8* %ptr1.015, i64 2
419 %cmp = icmp ult i64 %inc, 16
420 br i1 %cmp, label %for.body, label %cleanup
423 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
427 define i1 @volatile_loads(i8* %ptr) {
429 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
433 %i.016 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
434 %ptr1.015 = phi i8* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
435 %ptr0.014 = phi i8* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
436 %v0 = load volatile i8, i8* %ptr0.014
437 %v1 = load volatile i8, i8* %ptr1.015
438 %cmp2 = icmp eq i8 %v0, %v1
439 br i1 %cmp2, label %for.inc, label %cleanup
442 %inc = add nuw nsw i64 %i.016, 1
443 %add.ptr3 = getelementptr inbounds i8, i8* %ptr0.014, i64 1
444 %add.ptr4 = getelementptr inbounds i8, i8* %ptr1.015, i64 1
445 %cmp = icmp ult i64 %inc, 16
446 br i1 %cmp, label %for.body, label %cleanup
449 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
453 define i1 @atomic_loads(i8* %ptr) {
455 %add.ptr = getelementptr inbounds i8, i8* %ptr, i64 8
459 %i.016 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
460 %ptr1.015 = phi i8* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
461 %ptr0.014 = phi i8* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
462 %v0 = load atomic i8, i8* %ptr0.014 unordered, align 1
463 %v1 = load atomic i8, i8* %ptr1.015 unordered, align 1
464 %cmp2 = icmp eq i8 %v0, %v1
465 br i1 %cmp2, label %for.inc, label %cleanup
468 %inc = add nuw nsw i64 %i.016, 1
469 %add.ptr3 = getelementptr inbounds i8, i8* %ptr0.014, i64 1
470 %add.ptr4 = getelementptr inbounds i8, i8* %ptr1.015, i64 1
471 %cmp = icmp ult i64 %inc, 16
472 br i1 %cmp, label %for.body, label %cleanup
475 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]
479 define i1 @address_space(i8 addrspace(1)* %ptr) {
481 %add.ptr = getelementptr inbounds i8, i8 addrspace(1)* %ptr, i64 8
485 %i.016 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
486 %ptr1.015 = phi i8 addrspace(1)* [ %add.ptr, %entry ], [ %add.ptr4, %for.inc ]
487 %ptr0.014 = phi i8 addrspace(1)* [ %ptr, %entry ], [ %add.ptr3, %for.inc ]
488 %v0 = load i8, i8 addrspace(1)* %ptr0.014
489 %v1 = load i8, i8 addrspace(1)* %ptr1.015
490 %cmp2 = icmp eq i8 %v0, %v1
491 br i1 %cmp2, label %for.inc, label %cleanup
494 %inc = add nuw nsw i64 %i.016, 1
495 %add.ptr3 = getelementptr inbounds i8, i8 addrspace(1)* %ptr0.014, i64 1
496 %add.ptr4 = getelementptr inbounds i8, i8 addrspace(1)* %ptr1.015, i64 1
497 %cmp = icmp ult i64 %inc, 16
498 br i1 %cmp, label %for.body, label %cleanup
501 %res = phi i1 [ false, %for.body ], [ true, %for.inc ]