2 ; RUN: opt %s -passes=loop-vectorize,instcombine -force-vector-width=4 -force-vector-interleave=1 -debug-only=loop-vectorize -disable-output -print-after=instcombine 2>&1 | FileCheck %s
3 ; RUN: opt %s -passes=loop-vectorize,instcombine -force-vector-width=4 -force-vector-interleave=1 -enable-interleaved-mem-accesses -debug-only=loop-vectorize -disable-output -print-after=instcombine 2>&1 | FileCheck %s --check-prefix=INTER
5 target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
7 %pair = type { i32, i32 }
9 ; CHECK-LABEL: consecutive_ptr_forward
11 ; Check that a forward consecutive pointer is recognized as uniform and remains
12 ; uniform after vectorization.
14 ; CHECK: LV: Found uniform instruction: %tmp1 = getelementptr inbounds i32, ptr %a, i64 %i
16 ; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
17 ; CHECK-NOT: getelementptr
18 ; CHECK: getelementptr inbounds i32, ptr %a, i64 %index
19 ; CHECK-NOT: getelementptr
20 ; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
22 define i32 @consecutive_ptr_forward(ptr %a, i64 %n) {
27 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]
28 %tmp0 = phi i32 [ %tmp3, %for.body ], [ 0, %entry ]
29 %tmp1 = getelementptr inbounds i32, ptr %a, i64 %i
30 %tmp2 = load i32, ptr %tmp1, align 8
31 %tmp3 = add i32 %tmp0, %tmp2
32 %i.next = add nuw nsw i64 %i, 1
33 %cond = icmp slt i64 %i.next, %n
34 br i1 %cond, label %for.body, label %for.end
37 %tmp4 = phi i32 [ %tmp3, %for.body ]
41 ; CHECK-LABEL: consecutive_ptr_reverse
43 ; Check that a reverse consecutive pointer is recognized as uniform and remains
44 ; uniform after vectorization.
46 ; CHECK: LV: Found uniform instruction: %tmp1 = getelementptr inbounds i32, ptr %a, i64 %i
48 ; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
49 ; CHECK: [[OFFSET_IDX:%.+]] = sub i64 %n, %index
50 ; CHECK-NOT: getelementptr
51 ; CHECK: %[[G0:.+]] = getelementptr inbounds i32, ptr %a, i64 [[OFFSET_IDX]]
52 ; CHECK: getelementptr inbounds i8, ptr %[[G0]], i64 -12
53 ; CHECK-NOT: getelementptr
54 ; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
56 define i32 @consecutive_ptr_reverse(ptr %a, i64 %n) {
61 %i = phi i64 [ %i.next, %for.body ], [ %n, %entry ]
62 %tmp0 = phi i32 [ %tmp3, %for.body ], [ 0, %entry ]
63 %tmp1 = getelementptr inbounds i32, ptr %a, i64 %i
64 %tmp2 = load i32, ptr %tmp1, align 8
65 %tmp3 = add i32 %tmp0, %tmp2
66 %i.next = add nsw i64 %i, -1
67 %cond = icmp sgt i64 %i.next, 0
68 br i1 %cond, label %for.body, label %for.end
71 %tmp4 = phi i32 [ %tmp3, %for.body ]
75 ; CHECK-LABEL: interleaved_access_forward
76 ; INTER-LABEL: interleaved_access_forward
78 ; Check that a consecutive-like pointer used by a forward interleaved group is
79 ; recognized as uniform and remains uniform after vectorization. When
80 ; interleaved memory accesses aren't enabled, the pointer should not be
81 ; recognized as uniform, and it should not be uniform after vectorization.
83 ; CHECK-NOT: LV: Found uniform instruction: %tmp1 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 0
84 ; CHECK-NOT: LV: Found uniform instruction: %tmp2 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 1
86 ; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
87 ; CHECK: %[[I1:.+]] = or disjoint i64 %index, 1
88 ; CHECK: %[[I2:.+]] = or disjoint i64 %index, 2
89 ; CHECK: %[[I3:.+]] = or disjoint i64 %index, 3
90 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %index, i32 0
91 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I1]], i32 0
92 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I2]], i32 0
93 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I3]], i32 0
94 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %index, i32 1
95 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I1]], i32 1
96 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I2]], i32 1
97 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I3]], i32 1
98 ; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
100 ; INTER: LV: Found uniform instruction: %tmp1 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 0
101 ; INTER: LV: Found uniform instruction: %tmp2 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 1
103 ; INTER: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
104 ; INTER-NOT: getelementptr
105 ; INTER: getelementptr inbounds %pair, ptr %p, i64 %index, i32 0
106 ; INTER-NOT: getelementptr
107 ; INTER: br i1 {{.*}}, label %middle.block, label %vector.body
109 define i32 @interleaved_access_forward(ptr %p, i64 %n) {
114 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]
115 %tmp0 = phi i32 [ %tmp6, %for.body ], [ 0, %entry ]
116 %tmp1 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 0
117 %tmp2 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 1
118 %tmp3 = load i32, ptr %tmp1, align 8
119 %tmp4 = load i32, ptr %tmp2, align 8
120 %tmp5 = add i32 %tmp3, %tmp4
121 %tmp6 = add i32 %tmp0, %tmp5
122 %i.next = add nuw nsw i64 %i, 1
123 %cond = icmp slt i64 %i.next, %n
124 br i1 %cond, label %for.body, label %for.end
127 %tmp14 = phi i32 [ %tmp6, %for.body ]
131 ; CHECK-LABEL: interleaved_access_reverse
132 ; INTER-LABEL: interleaved_access_reverse
134 ; Check that a consecutive-like pointer used by a reverse interleaved group is
135 ; recognized as uniform and remains uniform after vectorization. When
136 ; interleaved memory accesses aren't enabled, the pointer should not be
137 ; recognized as uniform, and it should not be uniform after vectorization.
139 ; recognized as uniform, and it should not be uniform after vectorization.
140 ; CHECK-NOT: LV: Found uniform instruction: %tmp1 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 0
141 ; CHECK-NOT: LV: Found uniform instruction: %tmp2 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 1
143 ; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
144 ; CHECK: [[OFFSET_IDX:%.+]] = sub i64 %n, %index
145 ; CHECK: %[[I1:.+]] = add i64 [[OFFSET_IDX]], -1
146 ; CHECK: %[[I2:.+]] = add i64 [[OFFSET_IDX]], -2
147 ; CHECK: %[[I3:.+]] = add i64 [[OFFSET_IDX]], -3
148 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 [[OFFSET_IDX]], i32 0
149 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I1]], i32 0
150 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I2]], i32 0
151 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I3]], i32 0
152 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 [[OFFSET_IDX]], i32 1
153 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I1]], i32 1
154 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I2]], i32 1
155 ; CHECK: getelementptr inbounds %pair, ptr %p, i64 %[[I3]], i32 1
156 ; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
158 ; INTER: LV: Found uniform instruction: %tmp1 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 0
159 ; INTER: LV: Found uniform instruction: %tmp2 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 1
161 ; INTER: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
162 ; INTER: [[OFFSET_IDX:%.+]] = sub i64 %n, %index
163 ; INTER-NOT: getelementptr
164 ; INTER: %[[G0:.+]] = getelementptr inbounds %pair, ptr %p, i64 [[OFFSET_IDX]], i32 0
165 ; INTER: getelementptr inbounds i8, ptr %[[G0]], i64 -24
166 ; INTER-NOT: getelementptr
167 ; INTER: br i1 {{.*}}, label %middle.block, label %vector.body
169 define i32 @interleaved_access_reverse(ptr %p, i64 %n) {
174 %i = phi i64 [ %i.next, %for.body ], [ %n, %entry ]
175 %tmp0 = phi i32 [ %tmp6, %for.body ], [ 0, %entry ]
176 %tmp1 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 0
177 %tmp2 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 1
178 %tmp3 = load i32, ptr %tmp1, align 8
179 %tmp4 = load i32, ptr %tmp2, align 8
180 %tmp5 = add i32 %tmp3, %tmp4
181 %tmp6 = add i32 %tmp0, %tmp5
182 %i.next = add nsw i64 %i, -1
183 %cond = icmp sgt i64 %i.next, 0
184 br i1 %cond, label %for.body, label %for.end
187 %tmp14 = phi i32 [ %tmp6, %for.body ]
191 ; INTER-LABEL: predicated_store
193 ; Check that a consecutive-like pointer used by a forward interleaved group and
194 ; scalarized store is not recognized as uniform and is not uniform after
195 ; vectorization. The store is scalarized because it's in a predicated block.
196 ; Even though the load in this example is vectorized and only uses the pointer
197 ; as if it were uniform, the store is scalarized, making the pointer
200 ; INTER-NOT: LV: Found uniform instruction: %tmp0 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 0
202 ; INTER: %index = phi i64 [ 0, %vector.ph ], [ %index.next, {{.*}} ]
203 ; INTER: %[[G0:.+]] = getelementptr inbounds %pair, ptr %p, i64 %index, i32 0
204 ; INTER: %wide.vec = load <8 x i32>, ptr %[[G0]], align 8
205 ; INTER: %[[I1:.+]] = or disjoint i64 %index, 1
206 ; INTER: getelementptr inbounds %pair, ptr %p, i64 %[[I1]], i32 0
207 ; INTER: %[[I2:.+]] = or disjoint i64 %index, 2
208 ; INTER: getelementptr inbounds %pair, ptr %p, i64 %[[I2]], i32 0
209 ; INTER: %[[I3:.+]] = or disjoint i64 %index, 3
210 ; INTER: getelementptr inbounds %pair, ptr %p, i64 %[[I3]], i32 0
211 ; INTER: br i1 {{.*}}, label %middle.block, label %vector.body
213 define void @predicated_store(ptr %p, i32 %x, i64 %n) {
218 %i = phi i64 [ %i.next, %if.merge ], [ 0, %entry ]
219 %tmp0 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 0
220 %tmp1 = load i32, ptr %tmp0, align 8
221 %tmp2 = icmp eq i32 %tmp1, %x
222 br i1 %tmp2, label %if.then, label %if.merge
225 store i32 %tmp1, ptr %tmp0, align 8
229 %i.next = add nuw nsw i64 %i, 1
230 %cond = icmp slt i64 %i.next, %n
231 br i1 %cond, label %for.body, label %for.end
237 ; CHECK-LABEL: irregular_type
239 ; Check that a consecutive pointer used by a scalarized store is not recognized
240 ; as uniform and is not uniform after vectorization. The store is scalarized
241 ; because the stored type may required padding.
243 ; CHECK-NOT: LV: Found uniform instruction: %tmp1 = getelementptr inbounds x86_fp80, ptr %a, i64 %i
245 ; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
246 ; CHECK: %[[I1:.+]] = or disjoint i64 %index, 1
247 ; CHECK: %[[I2:.+]] = or disjoint i64 %index, 2
248 ; CHECK: %[[I3:.+]] = or disjoint i64 %index, 3
249 ; CHECK: getelementptr inbounds x86_fp80, ptr %a, i64 %index
250 ; CHECK: getelementptr inbounds x86_fp80, ptr %a, i64 %[[I1]]
251 ; CHECK: getelementptr inbounds x86_fp80, ptr %a, i64 %[[I2]]
252 ; CHECK: getelementptr inbounds x86_fp80, ptr %a, i64 %[[I3]]
253 ; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
255 define void @irregular_type(ptr %a, i64 %n) {
260 %i = phi i64 [ 0, %entry ], [ %i.next, %for.body ]
261 %tmp0 = sitofp i32 1 to x86_fp80
262 %tmp1 = getelementptr inbounds x86_fp80, ptr %a, i64 %i
263 store x86_fp80 %tmp0, ptr %tmp1, align 16
264 %i.next = add i64 %i, 1
265 %cond = icmp slt i64 %i.next, %n
266 br i1 %cond, label %for.body, label %for.end
272 ; CHECK-LABEL: pointer_iv_uniform
274 ; Check that a pointer induction variable is recognized as uniform and remains
275 ; uniform after vectorization.
277 ; CHECK: LV: Found uniform instruction: %p = phi ptr [ %tmp03, %for.body ], [ %a, %entry ]
279 ; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
280 ; CHECK-NOT: getelementptr
281 ; CHECK: [[SHL:%.+]] = shl i64 %index, 2
282 ; CHECK: %next.gep = getelementptr i8, ptr %a, i64 [[SHL]]
283 ; CHECK-NOT: getelementptr
284 ; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
286 define void @pointer_iv_uniform(ptr %a, i32 %x, i64 %n) {
291 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]
292 %p = phi ptr [ %tmp03, %for.body ], [ %a, %entry ]
293 store i32 %x, ptr %p, align 8
294 %tmp03 = getelementptr inbounds i32, ptr %p, i32 1
295 %i.next = add nuw nsw i64 %i, 1
296 %cond = icmp slt i64 %i.next, %n
297 br i1 %cond, label %for.body, label %for.end
303 ; INTER-LABEL: pointer_iv_non_uniform_0
305 ; Check that a pointer induction variable with a non-uniform user is not
306 ; recognized as uniform and is not uniform after vectorization. The pointer
307 ; induction variable is used by getelementptr instructions that are non-uniform
308 ; due to scalarization of the stores.
310 ; INTER-NOT: LV: Found uniform instruction: %p = phi ptr [ %tmp03, %for.body ], [ %a, %entry ]
312 ; INTER: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
313 ; INTER: %[[I0:.+]] = shl i64 %index, 4
314 ; INTER: %[[I1:.+]] = or disjoint i64 %[[I0]], 16
315 ; INTER: %[[I2:.+]] = or disjoint i64 %[[I0]], 32
316 ; INTER: %[[I3:.+]] = or disjoint i64 %[[I0]], 48
317 ; INTER: %next.gep = getelementptr i8, ptr %a, i64 %[[I0]]
318 ; INTER-NEXT: = getelementptr i8, ptr %a, i64 %[[I1]]
319 ; INTER-NEXT: = getelementptr i8, ptr %a, i64 %[[I2]]
320 ; INTER-NEXT: = getelementptr i8, ptr %a, i64 %[[I3]]
321 ; INTER: br i1 {{.*}}, label %middle.block, label %vector.body
323 define void @pointer_iv_non_uniform_0(ptr %a, i64 %n) {
328 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]
329 %p = phi ptr [ %tmp03, %for.body ], [ %a, %entry ]
330 %tmp00 = load i32, ptr %p, align 8
331 %tmp01 = getelementptr inbounds i32, ptr %p, i32 1
332 %tmp02 = load i32, ptr %tmp01, align 8
333 %tmp03 = getelementptr inbounds i32, ptr %p, i32 4
334 %tmp04 = load i32, ptr %tmp03, align 8
335 %tmp05 = getelementptr inbounds i32, ptr %p, i32 5
336 %tmp06 = load i32, ptr %tmp05, align 8
337 %tmp07 = sub i32 %tmp04, %tmp00
338 %tmp08 = sub i32 %tmp02, %tmp02
339 %tmp09 = getelementptr inbounds i32, ptr %p, i32 2
340 store i32 %tmp07, ptr %tmp09, align 8
341 %tmp10 = getelementptr inbounds i32, ptr %p, i32 3
342 store i32 %tmp08, ptr %tmp10, align 8
343 %i.next = add nuw nsw i64 %i, 1
344 %cond = icmp slt i64 %i.next, %n
345 br i1 %cond, label %for.body, label %for.end
351 ; CHECK-LABEL: pointer_iv_non_uniform_1
353 ; Check that a pointer induction variable with a non-uniform user is not
354 ; recognized as uniform and is not uniform after vectorization. The pointer
355 ; induction variable is used by a store that will be scalarized.
357 ; CHECK-NOT: LV: Found uniform instruction: %p = phi ptr [%tmp1, %for.body], [%a, %entry]
359 ; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
360 ; CHECK: [[SHL1:%.+]] = shl i64 %index, 4
361 ; CHECK: %[[I1:.+]] = or disjoint i64 [[SHL1]], 16
362 ; CHECK: %[[I2:.+]] = or disjoint i64 [[SHL1]], 32
363 ; CHECK: %[[I3:.+]] = or disjoint i64 [[SHL1]], 48
364 ; CHECK: %next.gep = getelementptr i8, ptr %a, i64 [[SHL1]]
365 ; CHECK: = getelementptr i8, ptr %a, i64 %[[I1]]
366 ; CHECK: = getelementptr i8, ptr %a, i64 %[[I2]]
367 ; CHECK: = getelementptr i8, ptr %a, i64 %[[I3]]
368 ; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
370 define void @pointer_iv_non_uniform_1(ptr %a, i64 %n) {
375 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]
376 %p = phi ptr [%tmp1, %for.body], [%a, %entry]
377 %tmp0 = sitofp i32 1 to x86_fp80
378 store x86_fp80 %tmp0, ptr %p, align 16
379 %tmp1 = getelementptr inbounds x86_fp80, ptr %p, i32 1
380 %i.next = add i64 %i, 1
381 %cond = icmp slt i64 %i.next, %n
382 br i1 %cond, label %for.body, label %for.end
388 ; CHECK-LABEL: pointer_iv_mixed
390 ; Check multiple pointer induction variables where only one is recognized as
391 ; uniform and remains uniform after vectorization. The other pointer induction
392 ; variable is not recognized as uniform and is not uniform after vectorization
393 ; because it is stored to memory.
395 ; CHECK-NOT: LV: Found uniform instruction: %p = phi ptr [ %tmp3, %for.body ], [ %a, %entry ]
396 ; CHECK: LV: Found uniform instruction: %q = phi ptr [ %tmp4, %for.body ], [ %b, %entry ]
398 ; CHECK: %pointer.phi = phi ptr [ %a, %vector.ph ], [ %ptr.ind, %vector.body ]
399 ; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
400 ; CHECK: %[[PTRVEC:.+]] = getelementptr i8, ptr %pointer.phi, <4 x i64> <i64 0, i64 4, i64 8, i64 12>
401 ; CHECK: [[SHL:%.+]] = shl i64 %index, 3
402 ; CHECK: %next.gep = getelementptr i8, ptr %b, i64 [[SHL]]
403 ; CHECK: store <4 x ptr> %[[PTRVEC]], ptr %next.gep, align 8
404 ; CHECK: %ptr.ind = getelementptr i8, ptr %pointer.phi, i64 16
405 ; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
407 define i32 @pointer_iv_mixed(ptr %a, ptr %b, i64 %n) {
412 %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ]
413 %p = phi ptr [ %tmp3, %for.body ], [ %a, %entry ]
414 %q = phi ptr [ %tmp4, %for.body ], [ %b, %entry ]
415 %tmp0 = phi i32 [ %tmp2, %for.body ], [ 0, %entry ]
416 %tmp1 = load i32, ptr %p, align 8
417 %tmp2 = add i32 %tmp1, %tmp0
418 store ptr %p, ptr %q, align 8
419 %tmp3 = getelementptr inbounds i32, ptr %p, i32 1
420 %tmp4 = getelementptr inbounds ptr, ptr %q, i32 1
421 %i.next = add nuw nsw i64 %i, 1
422 %cond = icmp slt i64 %i.next, %n
423 br i1 %cond, label %for.body, label %for.end
426 %tmp5 = phi i32 [ %tmp2, %for.body ]
430 ; INTER-LABEL: pointer_operand_geps_with_different_indexed_types
432 ; Check that a pointer operand having a user other than a memory access is
433 ; recognized as uniform after vectorization. In this test case, %tmp0 is a
434 ; GEP that is used by a load and a getelementptr instruction (%tmp2). Once
435 ; %tmp2 is marked uniform, %tmp0 should be marked uniform as well.
437 ; INTER: LV: Found uniform instruction: %cond = icmp slt i64 %i.next, %n
438 ; INTER-NEXT: LV: Found uniform instruction: %tmp2 = getelementptr inbounds i8, ptr %tmp0, i64 3
439 ; INTER-NEXT: LV: Found uniform instruction: %tmp6 = getelementptr inbounds i8, ptr %B, i64 %i
440 ; INTER-NEXT: LV: Found uniform instruction: %tmp0 = getelementptr inbounds i64, ptr %A, i64 %i
441 ; INTER-NEXT: LV: Found uniform instruction: %i = phi i64 [ 0, %entry ], [ %i.next, %for.body ]
442 ; INTER-NEXT: LV: Found uniform instruction: %i.next = add nuw nsw i64 %i, 1
443 ; INTER: define void @pointer_operand_geps_with_different_indexed_types(
444 ; INTER: vector.body:
445 ; INTER-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
446 ; INTER-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr %A, i64 [[INDEX]]
447 ; INTER-NEXT: [[WIDE_VEC:%.*]] = load <32 x i8>, ptr [[TMP4]], align 1
448 ; INTER-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <32 x i8> [[WIDE_VEC]], <32 x i8> poison, <4 x i32> <i32 0, i32 8, i32 16, i32 24>
449 ; INTER-NEXT: [[STRIDED_VEC3:%.*]] = shufflevector <32 x i8> [[WIDE_VEC]], <32 x i8> poison, <4 x i32> <i32 3, i32 11, i32 19, i32 27>
450 ; INTER-NEXT: [[TMP5:%.*]] = xor <4 x i8> [[STRIDED_VEC3]], [[STRIDED_VEC]]
451 ; INTER-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr %B, i64 [[INDEX]]
452 ; INTER-NEXT: store <4 x i8> [[TMP5]], ptr [[TMP6]], align 1
453 ; INTER-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
454 ; INTER: br i1 {{.*}}, label %middle.block, label %vector.body
456 define void @pointer_operand_geps_with_different_indexed_types(ptr %A, ptr %B, i64 %n) {
461 %i = phi i64 [ 0, %entry ], [ %i.next, %for.body ]
462 %tmp0 = getelementptr inbounds i64, ptr %A, i64 %i
463 %tmp2 = getelementptr inbounds i8, ptr %tmp0, i64 3
464 %tmp3 = load i8, ptr %tmp2, align 1
465 %tmp4 = load i8, ptr %tmp0, align 1
466 %tmp5 = xor i8 %tmp3, %tmp4
467 %tmp6 = getelementptr inbounds i8, ptr %B, i64 %i
468 store i8 %tmp5, ptr %tmp6
469 %i.next = add nuw nsw i64 %i, 1
470 %cond = icmp slt i64 %i.next, %n
471 br i1 %cond, label %for.body, label %for.end
477 ; CHECK-LABEL: pr61396_pointer_used_as_both_stored_value_and_pointer_operand_by_store
478 ; CHECK-NOT: LV: Found uniform instruction: %cur.ptr = getelementptr inbounds ptr, ptr %ary, i64 %iv
480 ; CHECK: define void @pr61396_pointer_used_as_both_stored_value_and_pointer_operand_by_store(
481 ; CHECK: vector.body:
482 ; CHECK-NEXT: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
483 ; CHECK-NEXT: [[VEC_IND:%.+]] = phi <4 x i64> [ <i64 0, i64 1, i64 2, i64 3>, %vector.ph ], [ %vec.ind.next, %vector.body ]
484 ; CHECK-NEXT: [[GEP:%.+]] = getelementptr inbounds ptr, ptr %ary, <4 x i64> [[VEC_IND]]
485 ; CHECK-NEXT: [[EXT:%.+]] = extractelement <4 x ptr> [[GEP]], i64 0
486 ; CHECK-NEXT: store <4 x ptr> [[GEP]], ptr [[EXT]], align 8
489 define void @pr61396_pointer_used_as_both_stored_value_and_pointer_operand_by_store(ptr %ary) {
494 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
495 %cur.ptr = getelementptr inbounds ptr, ptr %ary, i64 %iv
496 store ptr %cur.ptr, ptr %cur.ptr, align 8
497 %iv.next = add nuw nsw i64 %iv, 1
498 %done = icmp eq i64 %iv, 10240
499 br i1 %done, label %exit, label %loop