[IRBuilder] Add Align argument for CreateMaskedExpandLoad and CreateMaskedCompressSto...
[llvm-project.git] / llvm / test / Transforms / LoopVectorize / consecutive-ptr-uniforms.ll
blobc7c5f05ac2381df37db7da8e94baadbdc537f5bb
1 ; REQUIRES: asserts
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
15 ; CHECK:     vector.body
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) {
23 entry:
24   br label %for.body
26 for.body:
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
36 for.end:
37   %tmp4 = phi i32 [ %tmp3, %for.body ]
38   ret i32 %tmp4
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
47 ; CHECK:     vector.body
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) {
57 entry:
58   br label %for.body
60 for.body:
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
70 for.end:
71   %tmp4 = phi i32 [ %tmp3, %for.body ]
72   ret i32 %tmp4
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
85 ; CHECK:     vector.body
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
102 ; INTER:     vector.body
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) {
110 entry:
111   br label %for.body
113 for.body:
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
126 for.end:
127   %tmp14 = phi i32 [ %tmp6, %for.body ]
128   ret i32 %tmp14
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
142 ; CHECK:     vector.body
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
160 ; INTER:     vector.body
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) {
170 entry:
171   br label %for.body
173 for.body:
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
186 for.end:
187   %tmp14 = phi i32 [ %tmp6, %for.body ]
188   ret i32 %tmp14
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
198 ; non-uniform.
200 ; INTER-NOT: LV: Found uniform instruction: %tmp0 = getelementptr inbounds %pair, ptr %p, i64 %i, i32 0
201 ; INTER:     vector.body
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) {
214 entry:
215   br label %for.body
217 for.body:
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
224 if.then:
225   store i32 %tmp1, ptr %tmp0, align 8
226   br label %if.merge
228 if.merge:
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
233 for.end:
234   ret void
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
244 ; CHECK:     vector.body
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) {
256 entry:
257   br label %for.body
259 for.body:
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
268 for.end:
269   ret void
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 ]
278 ; CHECK:     vector.body
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) {
287 entry:
288   br label %for.body
290 for.body:
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
299 for.end:
300   ret void
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 ]
311 ; INTER:     vector.body
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) {
324 entry:
325   br label %for.body
327 for.body:
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
347 for.end:
348   ret void
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]
358 ; CHECK:     vector.body
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) {
371 entry:
372   br label %for.body
374 for.body:
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
384 for.end:
385   ret void
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 ]
397 ; CHECK:     vector.body
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) {
408 entry:
409   br label %for.body
411 for.body:
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
425 for.end:
426   %tmp5 = phi i32 [ %tmp2, %for.body ]
427   ret i32 %tmp5
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) {
457 entry:
458   br label %for.body
460 for.body:
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
473 for.end:
474   ret void
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) {
490 entry:
491   br label %loop
493 loop:
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
501 exit:
502   ret void