Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / GVN / PRE / rle.ll
blobfd4a9a081eab3e9c55c9143147903935ae7123fc
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -data-layout="e-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-n8:16:32" -passes=gvn,dce -enable-split-backedge-in-load-pre -S | FileCheck %s --check-prefixes=CHECK,LE
3 ; RUN: opt < %s -data-layout="E-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-n32" -passes=gvn,dce -enable-split-backedge-in-load-pre -S | FileCheck %s --check-prefixes=CHECK,BE
5 ;; Trivial RLE test.
6 define i32 @test0(i32 %V, ptr %P) {
7 ; CHECK-LABEL: @test0(
8 ; CHECK-NEXT:    store i32 [[V:%.*]], ptr [[P:%.*]], align 4
9 ; CHECK-NEXT:    ret i32 [[V]]
11   store i32 %V, ptr %P
13   %A = load i32, ptr %P
14   ret i32 %A
18 ;;===----------------------------------------------------------------------===;;
19 ;; Tests for crashers
20 ;;===----------------------------------------------------------------------===;;
22 ;; PR5016
23 define i8 @crash0({i32, i32} %A, ptr %P) {
24 ; CHECK-LABEL: @crash0(
25 ; CHECK-NEXT:    store { i32, i32 } [[A:%.*]], ptr [[P:%.*]], align 4
26 ; CHECK-NEXT:    [[Y:%.*]] = load i8, ptr [[P]], align 1
27 ; CHECK-NEXT:    ret i8 [[Y]]
29   store {i32, i32} %A, ptr %P
30   %Y = load i8, ptr %P
31   ret i8 %Y
34 ;; No PR filed, crashed in CaptureTracker.
35 declare void @helper()
36 define void @crash1() {
37 ; CHECK-LABEL: @crash1(
38 ; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr undef, ptr undef, i64 undef, i1 false) #[[ATTR3:[0-9]+]]
39 ; CHECK-NEXT:    ret void
41   tail call void @llvm.memcpy.p0.p0.i64(ptr undef, ptr undef, i64 undef, i1 false) nounwind
42   %ttmp = load i8, ptr @helper
43   %x = icmp eq i8 %ttmp, 15
44   ret void
48 ;;===----------------------------------------------------------------------===;;
49 ;; Store -> Load  and  Load -> Load forwarding where src and dst are different
50 ;; types, but where the base pointer is a must alias.
51 ;;===----------------------------------------------------------------------===;;
53 ;; i32 -> f32 forwarding.
54 define float @coerce_mustalias1(i32 %V, ptr %P) {
55 ; CHECK-LABEL: @coerce_mustalias1(
56 ; CHECK-NEXT:    store i32 [[V:%.*]], ptr [[P:%.*]], align 4
57 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i32 [[V]] to float
58 ; CHECK-NEXT:    ret float [[TMP1]]
60   store i32 %V, ptr %P
63   %A = load float, ptr %P
64   ret float %A
67 ;; ptr -> float forwarding.
68 define float @coerce_mustalias2(ptr %V, ptr %P) {
69 ; CHECK-LABEL: @coerce_mustalias2(
70 ; CHECK-NEXT:    store ptr [[V:%.*]], ptr [[P:%.*]], align 4
71 ; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[V]] to i32
72 ; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i32 [[TMP1]] to float
73 ; CHECK-NEXT:    ret float [[TMP2]]
75   store ptr %V, ptr %P
78   %A = load float, ptr %P
79   ret float %A
82 ;; float -> ptr forwarding.
83 define ptr @coerce_mustalias3(float %V, ptr %P) {
84 ; CHECK-LABEL: @coerce_mustalias3(
85 ; CHECK-NEXT:    store float [[V:%.*]], ptr [[P:%.*]], align 4
86 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[V]] to i32
87 ; CHECK-NEXT:    [[TMP2:%.*]] = inttoptr i32 [[TMP1]] to ptr
88 ; CHECK-NEXT:    ret ptr [[TMP2]]
90   store float %V, ptr %P
93   %A = load ptr, ptr %P
94   ret ptr %A
97 ;; i32 -> f32 load forwarding.
98 define float @coerce_mustalias4(ptr %P, i1 %cond) {
99 ; CHECK-LABEL: @coerce_mustalias4(
100 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P:%.*]], align 4
101 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i32 [[A]] to float
102 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
103 ; CHECK:       T:
104 ; CHECK-NEXT:    ret float [[TMP1]]
105 ; CHECK:       F:
106 ; CHECK-NEXT:    ret float [[TMP1]]
108   %A = load i32, ptr %P
110   %B = load float, ptr %P
111   br i1 %cond, label %T, label %F
113   ret float %B
116   %X = bitcast i32 %A to float
117   ret float %X
121 ;; i32 -> i8 forwarding
122 define i8 @coerce_mustalias5(i32 %V, ptr %P) {
123 ; LE-LABEL: @coerce_mustalias5(
124 ; LE-NEXT:    store i32 [[V:%.*]], ptr [[P:%.*]], align 4
125 ; LE-NEXT:    [[TMP1:%.*]] = trunc i32 [[V]] to i8
126 ; LE-NEXT:    ret i8 [[TMP1]]
128 ; BE-LABEL: @coerce_mustalias5(
129 ; BE-NEXT:    store i32 [[V:%.*]], ptr [[P:%.*]], align 4
130 ; BE-NEXT:    [[TMP1:%.*]] = lshr i32 [[V]], 24
131 ; BE-NEXT:    [[TMP2:%.*]] = trunc i32 [[TMP1]] to i8
132 ; BE-NEXT:    ret i8 [[TMP2]]
134   store i32 %V, ptr %P
137   %A = load i8, ptr %P
138   ret i8 %A
141 ;; i64 -> float forwarding
142 define float @coerce_mustalias6(i64 %V, ptr %P) {
143 ; LE-LABEL: @coerce_mustalias6(
144 ; LE-NEXT:    store i64 [[V:%.*]], ptr [[P:%.*]], align 4
145 ; LE-NEXT:    [[TMP1:%.*]] = trunc i64 [[V]] to i32
146 ; LE-NEXT:    [[TMP2:%.*]] = bitcast i32 [[TMP1]] to float
147 ; LE-NEXT:    ret float [[TMP2]]
149 ; BE-LABEL: @coerce_mustalias6(
150 ; BE-NEXT:    store i64 [[V:%.*]], ptr [[P:%.*]], align 4
151 ; BE-NEXT:    [[TMP1:%.*]] = lshr i64 [[V]], 32
152 ; BE-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
153 ; BE-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
154 ; BE-NEXT:    ret float [[TMP3]]
156   store i64 %V, ptr %P
159   %A = load float, ptr %P
160   ret float %A
163 ;; i64 -> ptr (32-bit) forwarding
164 define ptr @coerce_mustalias7(i64 %V, ptr %P) {
165 ; LE-LABEL: @coerce_mustalias7(
166 ; LE-NEXT:    store i64 [[V:%.*]], ptr [[P:%.*]], align 4
167 ; LE-NEXT:    [[TMP1:%.*]] = trunc i64 [[V]] to i32
168 ; LE-NEXT:    [[TMP2:%.*]] = inttoptr i32 [[TMP1]] to ptr
169 ; LE-NEXT:    ret ptr [[TMP2]]
171 ; BE-LABEL: @coerce_mustalias7(
172 ; BE-NEXT:    store i64 [[V:%.*]], ptr [[P:%.*]], align 4
173 ; BE-NEXT:    [[TMP1:%.*]] = lshr i64 [[V]], 32
174 ; BE-NEXT:    [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
175 ; BE-NEXT:    [[TMP3:%.*]] = inttoptr i32 [[TMP2]] to ptr
176 ; BE-NEXT:    ret ptr [[TMP3]]
178   store i64 %V, ptr %P
181   %A = load ptr, ptr %P
182   ret ptr %A
185 ; memset -> i16 forwarding.
186 define signext i16 @memset_to_i16_local(ptr %A) nounwind ssp {
187 ; CHECK-LABEL: @memset_to_i16_local(
188 ; CHECK-NEXT:  entry:
189 ; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr [[A:%.*]], i8 1, i64 200, i1 false)
190 ; CHECK-NEXT:    ret i16 257
192 entry:
193   tail call void @llvm.memset.p0.i64(ptr %A, i8 1, i64 200, i1 false)
194   %arrayidx = getelementptr inbounds i16, ptr %A, i64 42
195   %ttmp2 = load i16, ptr %arrayidx
196   ret i16 %ttmp2
199 ; memset -> float forwarding.
200 define float @memset_to_float_local(ptr %A, i8 %Val) nounwind ssp {
201 ; CHECK-LABEL: @memset_to_float_local(
202 ; CHECK-NEXT:  entry:
203 ; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr [[A:%.*]], i8 [[VAL:%.*]], i64 400, i1 false)
204 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[VAL]] to i32
205 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[TMP0]], 8
206 ; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[TMP0]], [[TMP1]]
207 ; CHECK-NEXT:    [[TMP3:%.*]] = shl i32 [[TMP2]], 16
208 ; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]]
209 ; CHECK-NEXT:    [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float
210 ; CHECK-NEXT:    ret float [[TMP5]]
212 entry:
213   tail call void @llvm.memset.p0.i64(ptr %A, i8 %Val, i64 400, i1 false)
214   %arrayidx = getelementptr inbounds float, ptr %A, i64 42 ; <ptr> [#uses=1]
215   %ttmp2 = load float, ptr %arrayidx                   ; <float> [#uses=1]
216   ret float %ttmp2
219 ;; non-local memset -> i16 load forwarding.
220 define i16 @memset_to_i16_nonlocal0(ptr %P, i1 %cond) {
221 ; CHECK-LABEL: @memset_to_i16_nonlocal0(
222 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
223 ; CHECK:       T:
224 ; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 1, i64 400, i1 false)
225 ; CHECK-NEXT:    br label [[CONT:%.*]]
226 ; CHECK:       F:
227 ; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr [[P]], i8 2, i64 400, i1 false)
228 ; CHECK-NEXT:    br label [[CONT]]
229 ; CHECK:       Cont:
230 ; CHECK-NEXT:    [[A:%.*]] = phi i16 [ 514, [[F]] ], [ 257, [[T]] ]
231 ; CHECK-NEXT:    ret i16 [[A]]
233   br i1 %cond, label %T, label %F
235   tail call void @llvm.memset.p0.i64(ptr %P, i8 1, i64 400, i1 false)
236   br label %Cont
239   tail call void @llvm.memset.p0.i64(ptr %P, i8 2, i64 400, i1 false)
240   br label %Cont
242 Cont:
243   %P2 = getelementptr i16, ptr %P, i32 4
244   %A = load i16, ptr %P2
245   ret i16 %A
249 @GCst = constant {i32, float, i32 } { i32 42, float 14., i32 97 }
250 @GCst_as1 = addrspace(1) constant {i32, float, i32 } { i32 42, float 14., i32 97 }
252 ; memset -> float forwarding.
253 define float @memcpy_to_float_local(ptr %A) nounwind ssp {
254 ; CHECK-LABEL: @memcpy_to_float_local(
255 ; CHECK-NEXT:  entry:
256 ; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr [[A:%.*]], ptr @GCst, i64 12, i1 false)
257 ; CHECK-NEXT:    ret float 1.400000e+01
259 entry:
260   tail call void @llvm.memcpy.p0.p0.i64(ptr %A, ptr @GCst, i64 12, i1 false)
261   %arrayidx = getelementptr inbounds float, ptr %A, i64 1 ; <ptr> [#uses=1]
262   %ttmp2 = load float, ptr %arrayidx                   ; <float> [#uses=1]
263   ret float %ttmp2
266 ; memcpy from address space 1
267 define float @memcpy_to_float_local_as1(ptr %A) nounwind ssp {
268 ; CHECK-LABEL: @memcpy_to_float_local_as1(
269 ; CHECK-NEXT:  entry:
270 ; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p1.i64(ptr [[A:%.*]], ptr addrspace(1) @GCst_as1, i64 12, i1 false)
271 ; CHECK-NEXT:    ret float 1.400000e+01
273 entry:
274   tail call void @llvm.memcpy.p0.p1.i64(ptr %A, ptr addrspace(1) @GCst_as1, i64 12, i1 false)
275   %arrayidx = getelementptr inbounds float, ptr %A, i64 1 ; <ptr> [#uses=1]
276   %ttmp2 = load float, ptr %arrayidx                   ; <float> [#uses=1]
277   ret float %ttmp2
280 ;; non-local i32/float -> i8 load forwarding.
281 define i8 @coerce_mustalias_nonlocal0(ptr %P, i1 %cond) {
282 ; LE-LABEL: @coerce_mustalias_nonlocal0(
283 ; LE-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
284 ; LE:       T:
285 ; LE-NEXT:    store i32 42, ptr [[P:%.*]], align 4
286 ; LE-NEXT:    br label [[CONT:%.*]]
287 ; LE:       F:
288 ; LE-NEXT:    store float 1.000000e+00, ptr [[P]], align 4
289 ; LE-NEXT:    br label [[CONT]]
290 ; LE:       Cont:
291 ; LE-NEXT:    [[A:%.*]] = phi i8 [ 0, [[F]] ], [ 42, [[T]] ]
292 ; LE-NEXT:    ret i8 [[A]]
294 ; BE-LABEL: @coerce_mustalias_nonlocal0(
295 ; BE-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
296 ; BE:       T:
297 ; BE-NEXT:    store i32 42, ptr [[P:%.*]], align 4
298 ; BE-NEXT:    br label [[CONT:%.*]]
299 ; BE:       F:
300 ; BE-NEXT:    store float 1.000000e+00, ptr [[P]], align 4
301 ; BE-NEXT:    br label [[CONT]]
302 ; BE:       Cont:
303 ; BE-NEXT:    [[A:%.*]] = phi i8 [ 63, [[F]] ], [ 0, [[T]] ]
304 ; BE-NEXT:    ret i8 [[A]]
306   br i1 %cond, label %T, label %F
308   store i32 42, ptr %P
309   br label %Cont
312   store float 1.0, ptr %P
313   br label %Cont
315 Cont:
316   %A = load i8, ptr %P
317   ret i8 %A
322 ;; non-local i32/float -> i8 load forwarding.  This also tests that the "P3"
323 ;; bitcast equivalence can be properly phi translated.
324 define i8 @coerce_mustalias_nonlocal1(ptr %P, i1 %cond) {
325 ; LE-LABEL: @coerce_mustalias_nonlocal1(
326 ; LE-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
327 ; LE:       T:
328 ; LE-NEXT:    store i32 42, ptr [[P:%.*]], align 4
329 ; LE-NEXT:    br label [[CONT:%.*]]
330 ; LE:       F:
331 ; LE-NEXT:    store float 1.000000e+00, ptr [[P]], align 4
332 ; LE-NEXT:    br label [[CONT]]
333 ; LE:       Cont:
334 ; LE-NEXT:    [[A:%.*]] = phi i8 [ 0, [[F]] ], [ 42, [[T]] ]
335 ; LE-NEXT:    ret i8 [[A]]
337 ; BE-LABEL: @coerce_mustalias_nonlocal1(
338 ; BE-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
339 ; BE:       T:
340 ; BE-NEXT:    store i32 42, ptr [[P:%.*]], align 4
341 ; BE-NEXT:    br label [[CONT:%.*]]
342 ; BE:       F:
343 ; BE-NEXT:    store float 1.000000e+00, ptr [[P]], align 4
344 ; BE-NEXT:    br label [[CONT]]
345 ; BE:       Cont:
346 ; BE-NEXT:    [[A:%.*]] = phi i8 [ 63, [[F]] ], [ 0, [[T]] ]
347 ; BE-NEXT:    ret i8 [[A]]
349   br i1 %cond, label %T, label %F
351   store i32 42, ptr %P
352   br label %Cont
355   store float 1.0, ptr %P
356   br label %Cont
358 Cont:
359   %A = load i8, ptr %P
360   ret i8 %A
365 ;; non-local i32 -> i8 partial redundancy load forwarding.
366 define i8 @coerce_mustalias_pre0(ptr %P, i1 %cond) {
367 ; LE-LABEL: @coerce_mustalias_pre0(
368 ; LE-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
369 ; LE:       T:
370 ; LE-NEXT:    store i32 42, ptr [[P:%.*]], align 4
371 ; LE-NEXT:    br label [[CONT:%.*]]
372 ; LE:       F:
373 ; LE-NEXT:    [[A_PRE:%.*]] = load i8, ptr [[P]], align 1
374 ; LE-NEXT:    br label [[CONT]]
375 ; LE:       Cont:
376 ; LE-NEXT:    [[A:%.*]] = phi i8 [ [[A_PRE]], [[F]] ], [ 42, [[T]] ]
377 ; LE-NEXT:    ret i8 [[A]]
379 ; BE-LABEL: @coerce_mustalias_pre0(
380 ; BE-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
381 ; BE:       T:
382 ; BE-NEXT:    store i32 42, ptr [[P:%.*]], align 4
383 ; BE-NEXT:    br label [[CONT:%.*]]
384 ; BE:       F:
385 ; BE-NEXT:    [[A_PRE:%.*]] = load i8, ptr [[P]], align 1
386 ; BE-NEXT:    br label [[CONT]]
387 ; BE:       Cont:
388 ; BE-NEXT:    [[A:%.*]] = phi i8 [ [[A_PRE]], [[F]] ], [ 0, [[T]] ]
389 ; BE-NEXT:    ret i8 [[A]]
391   br i1 %cond, label %T, label %F
393   store i32 42, ptr %P
394   br label %Cont
397   br label %Cont
399 Cont:
400   %A = load i8, ptr %P
401   ret i8 %A
405 ;;===----------------------------------------------------------------------===;;
406 ;; Store -> Load  and  Load -> Load forwarding where src and dst are different
407 ;; types, and the reload is an offset from the store pointer.
408 ;;===----------------------------------------------------------------------===;;
410 ;; i32 -> i8 forwarding.
411 ;; PR4216
412 define i8 @coerce_offset0(i32 %V, ptr %P) {
413 ; LE-LABEL: @coerce_offset0(
414 ; LE-NEXT:    store i32 [[V:%.*]], ptr [[P:%.*]], align 4
415 ; LE-NEXT:    [[TMP1:%.*]] = lshr i32 [[V]], 16
416 ; LE-NEXT:    [[TMP2:%.*]] = trunc i32 [[TMP1]] to i8
417 ; LE-NEXT:    ret i8 [[TMP2]]
419 ; BE-LABEL: @coerce_offset0(
420 ; BE-NEXT:    store i32 [[V:%.*]], ptr [[P:%.*]], align 4
421 ; BE-NEXT:    [[TMP1:%.*]] = lshr i32 [[V]], 8
422 ; BE-NEXT:    [[TMP2:%.*]] = trunc i32 [[TMP1]] to i8
423 ; BE-NEXT:    ret i8 [[TMP2]]
425   store i32 %V, ptr %P
427   %P3 = getelementptr i8, ptr %P, i32 2
429   %A = load i8, ptr %P3
430   ret i8 %A
433 ;; non-local i32/float -> i8 load forwarding.
434 define i8 @coerce_offset_nonlocal0(ptr %P, i1 %cond) {
435 ; LE-LABEL: @coerce_offset_nonlocal0(
436 ; LE-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
437 ; LE:       T:
438 ; LE-NEXT:    store i32 57005, ptr [[P:%.*]], align 4
439 ; LE-NEXT:    br label [[CONT:%.*]]
440 ; LE:       F:
441 ; LE-NEXT:    store float 1.000000e+00, ptr [[P]], align 4
442 ; LE-NEXT:    br label [[CONT]]
443 ; LE:       Cont:
444 ; LE-NEXT:    [[A:%.*]] = phi i8 [ -128, [[F]] ], [ 0, [[T]] ]
445 ; LE-NEXT:    ret i8 [[A]]
447 ; BE-LABEL: @coerce_offset_nonlocal0(
448 ; BE-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
449 ; BE:       T:
450 ; BE-NEXT:    store i32 57005, ptr [[P:%.*]], align 4
451 ; BE-NEXT:    br label [[CONT:%.*]]
452 ; BE:       F:
453 ; BE-NEXT:    store float 1.000000e+00, ptr [[P]], align 4
454 ; BE-NEXT:    br label [[CONT]]
455 ; BE:       Cont:
456 ; BE-NEXT:    [[A:%.*]] = phi i8 [ 0, [[F]] ], [ -34, [[T]] ]
457 ; BE-NEXT:    ret i8 [[A]]
459   %P4 = getelementptr i8, ptr %P, i32 2
460   br i1 %cond, label %T, label %F
462   store i32 57005, ptr %P
463   br label %Cont
466   store float 1.0, ptr %P
467   br label %Cont
469 Cont:
470   %A = load i8, ptr %P4
471   ret i8 %A
476 ;; non-local i32 -> i8 partial redundancy load forwarding.
477 define i8 @coerce_offset_pre0(ptr %P, i1 %cond) {
478 ; CHECK-LABEL: @coerce_offset_pre0(
479 ; CHECK-NEXT:    [[P4:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 2
480 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
481 ; CHECK:       T:
482 ; CHECK-NEXT:    store i32 42, ptr [[P]], align 4
483 ; CHECK-NEXT:    br label [[CONT:%.*]]
484 ; CHECK:       F:
485 ; CHECK-NEXT:    [[A_PRE:%.*]] = load i8, ptr [[P4]], align 1
486 ; CHECK-NEXT:    br label [[CONT]]
487 ; CHECK:       Cont:
488 ; CHECK-NEXT:    [[A:%.*]] = phi i8 [ [[A_PRE]], [[F]] ], [ 0, [[T]] ]
489 ; CHECK-NEXT:    ret i8 [[A]]
491   %P4 = getelementptr i8, ptr %P, i32 2
492   br i1 %cond, label %T, label %F
494   store i32 42, ptr %P
495   br label %Cont
498   br label %Cont
500 Cont:
501   %A = load i8, ptr %P4
502   ret i8 %A
506 define i32 @chained_load(ptr %p, i32 %x, i32 %y) {
507 ; CHECK-LABEL: @chained_load(
508 ; CHECK-NEXT:  block1:
509 ; CHECK-NEXT:    [[A:%.*]] = alloca ptr, align 4
510 ; CHECK-NEXT:    [[Z:%.*]] = load ptr, ptr [[P:%.*]], align 4
511 ; CHECK-NEXT:    store ptr [[Z]], ptr [[A]], align 4
512 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
513 ; CHECK-NEXT:    br i1 [[CMP]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]
514 ; CHECK:       block2:
515 ; CHECK-NEXT:    br label [[BLOCK4:%.*]]
516 ; CHECK:       block3:
517 ; CHECK-NEXT:    br label [[BLOCK4]]
518 ; CHECK:       block4:
519 ; CHECK-NEXT:    [[D:%.*]] = load i32, ptr [[Z]], align 4
520 ; CHECK-NEXT:    ret i32 [[D]]
522 block1:
523   %A = alloca ptr
525   %z = load ptr, ptr %p
526   store ptr %z, ptr %A
527   %cmp = icmp eq i32 %x, %y
528   br i1 %cmp, label %block2, label %block3
530 block2:
531   %a = load ptr, ptr %p
532   br label %block4
534 block3:
535   %b = load ptr, ptr %p
536   br label %block4
538 block4:
539   %c = load ptr, ptr %p
540   %d = load i32, ptr %c
541   ret i32 %d
546 declare i1 @cond() readonly
547 declare i1 @cond2() readonly
549 define i32 @phi_trans2() {
550 ; CHECK-LABEL: @phi_trans2(
551 ; CHECK-NEXT:  entry:
552 ; CHECK-NEXT:    [[P:%.*]] = alloca i32, i32 400, align 4
553 ; CHECK-NEXT:    br label [[F1:%.*]]
554 ; CHECK:       F1:
555 ; CHECK-NEXT:    [[A:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 2, [[F:%.*]] ]
556 ; CHECK-NEXT:    [[COND2:%.*]] = call i1 @cond()
557 ; CHECK-NEXT:    br i1 [[COND2]], label [[T1:%.*]], label [[TY:%.*]]
558 ; CHECK:       T1:
559 ; CHECK-NEXT:    [[P2:%.*]] = getelementptr i32, ptr [[P]], i32 [[A]]
560 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P2]], align 4
561 ; CHECK-NEXT:    [[COND:%.*]] = call i1 @cond2()
562 ; CHECK-NEXT:    br i1 [[COND]], label [[TX:%.*]], label [[F]]
563 ; CHECK:       F:
564 ; CHECK-NEXT:    [[P3:%.*]] = getelementptr i32, ptr [[P]], i32 2
565 ; CHECK-NEXT:    store i32 17, ptr [[P3]], align 4
566 ; CHECK-NEXT:    store i32 42, ptr [[P2]], align 4
567 ; CHECK-NEXT:    br label [[F1]]
568 ; CHECK:       TX:
569 ; CHECK-NEXT:    ret i32 [[X]]
570 ; CHECK:       TY:
571 ; CHECK-NEXT:    ret i32 0
573 entry:
574   %P = alloca i32, i32 400
575   br label %F1
578   %A = phi i32 [1, %entry], [2, %F]
579   %cond2 = call i1 @cond()
580   br i1 %cond2, label %T1, label %TY
583   %P2 = getelementptr i32, ptr %P, i32 %A
584   %x = load i32, ptr %P2
585   %cond = call i1 @cond2()
586   br i1 %cond, label %TX, label %F
589   %P3 = getelementptr i32, ptr %P, i32 2
590   store i32 17, ptr %P3
592   store i32 42, ptr %P2  ; Provides "P[A]".
593   br label %F1
596   ; This load should not be compiled to 'ret i32 42'.  An overly clever
597   ; implementation of GVN would see that we're returning 17 if the loop
598   ; executes once or 42 if it executes more than that, but we'd have to do
599   ; loop restructuring to expose this, and GVN shouldn't do this sort of CFG
600   ; transformation.
602   ret i32 %x
604   ret i32 0
607 define i32 @phi_trans3(ptr %p, i32 %x, i32 %y, i32 %z) {
608 ; CHECK-LABEL: @phi_trans3(
609 ; CHECK-NEXT:  block1:
610 ; CHECK-NEXT:    [[CMPXY:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
611 ; CHECK-NEXT:    br i1 [[CMPXY]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]
612 ; CHECK:       block2:
613 ; CHECK-NEXT:    store i32 87, ptr [[P:%.*]], align 4
614 ; CHECK-NEXT:    br label [[BLOCK4:%.*]]
615 ; CHECK:       block3:
616 ; CHECK-NEXT:    [[P2:%.*]] = getelementptr i32, ptr [[P]], i32 43
617 ; CHECK-NEXT:    store i32 97, ptr [[P2]], align 4
618 ; CHECK-NEXT:    br label [[BLOCK4]]
619 ; CHECK:       block4:
620 ; CHECK-NEXT:    [[D:%.*]] = phi i32 [ 87, [[BLOCK2]] ], [ 97, [[BLOCK3]] ]
621 ; CHECK-NEXT:    br i1 [[CMPXY]], label [[BLOCK5:%.*]], label [[EXIT:%.*]]
622 ; CHECK:       block5:
623 ; CHECK-NEXT:    br i1 true, label [[BLOCK6:%.*]], label [[BLOCK5_EXIT_CRIT_EDGE:%.*]]
624 ; CHECK:       block5.exit_crit_edge:
625 ; CHECK-NEXT:    br label [[EXIT]]
626 ; CHECK:       block6:
627 ; CHECK-NEXT:    br i1 true, label [[BLOCK7:%.*]], label [[BLOCK6_EXIT_CRIT_EDGE:%.*]]
628 ; CHECK:       block6.exit_crit_edge:
629 ; CHECK-NEXT:    br label [[EXIT]]
630 ; CHECK:       block7:
631 ; CHECK-NEXT:    ret i32 [[D]]
632 ; CHECK:       exit:
633 ; CHECK-NEXT:    ret i32 -1
635 block1:
636   %cmpxy = icmp eq i32 %x, %y
637   br i1 %cmpxy, label %block2, label %block3
639 block2:
640   store i32 87, ptr %p
641   br label %block4
643 block3:
644   %p2 = getelementptr i32, ptr %p, i32 43
645   store i32 97, ptr %p2
646   br label %block4
648 block4:
649   %A = phi i32 [-1, %block2], [42, %block3]
650   br i1 %cmpxy, label %block5, label %exit
653 block5:
654   %B = add i32 %A, 1
655   br i1 %cmpxy, label %block6, label %exit
657 block6:
658   %C = getelementptr i32, ptr %p, i32 %B
659   br i1 %cmpxy, label %block7, label %exit
661 block7:
662   %D = load i32, ptr %C
663   ret i32 %D
666 exit:
667   ret i32 -1
670 define i8 @phi_trans4(ptr %p) {
671 ; CHECK-LABEL: @phi_trans4(
672 ; CHECK-NEXT:  entry:
673 ; CHECK-NEXT:    [[X3:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 192
674 ; CHECK-NEXT:    store i8 -64, ptr [[X3]], align 1
675 ; CHECK-NEXT:    [[X:%.*]] = getelementptr i8, ptr [[P]], i32 4
676 ; CHECK-NEXT:    [[Y:%.*]] = load i8, ptr [[X]], align 1
677 ; CHECK-NEXT:    br label [[LOOP:%.*]]
678 ; CHECK:       loop:
679 ; CHECK-NEXT:    [[Y2:%.*]] = phi i8 [ [[Y]], [[ENTRY:%.*]] ], [ 0, [[LOOP]] ]
680 ; CHECK-NEXT:    [[COND:%.*]] = call i1 @cond2()
681 ; CHECK-NEXT:    store i32 0, ptr [[X3]], align 4
682 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[OUT:%.*]]
683 ; CHECK:       out:
684 ; CHECK-NEXT:    [[R:%.*]] = add i8 [[Y]], [[Y2]]
685 ; CHECK-NEXT:    ret i8 [[R]]
687 entry:
688   %X3 = getelementptr i8, ptr %p, i32 192
689   store i8 192, ptr %X3
691   %X = getelementptr i8, ptr %p, i32 4
692   %Y = load i8, ptr %X
693   br label %loop
695 loop:
696   %i = phi i32 [4, %entry], [192, %loop]
697   %X2 = getelementptr i8, ptr %p, i32 %i
698   %Y2 = load i8, ptr %X2
701   %cond = call i1 @cond2()
703   store i32 0, ptr %X3
704   br i1 %cond, label %loop, label %out
706 out:
707   %R = add i8 %Y, %Y2
708   ret i8 %R
711 define i8 @phi_trans5(ptr %p) {
712 ; CHECK-LABEL: @phi_trans5(
713 ; CHECK-NEXT:  entry:
714 ; CHECK-NEXT:    [[X4:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 2
715 ; CHECK-NEXT:    store i8 19, ptr [[X4]], align 1
716 ; CHECK-NEXT:    [[X:%.*]] = getelementptr i8, ptr [[P]], i32 4
717 ; CHECK-NEXT:    [[Y:%.*]] = load i8, ptr [[X]], align 1
718 ; CHECK-NEXT:    br label [[LOOP:%.*]]
719 ; CHECK:       loop:
720 ; CHECK-NEXT:    [[Y2:%.*]] = phi i8 [ [[Y]], [[ENTRY:%.*]] ], [ [[Y2_PRE:%.*]], [[CONT:%.*]] ]
721 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 4, [[ENTRY]] ], [ 3, [[CONT]] ]
722 ; CHECK-NEXT:    [[X2:%.*]] = getelementptr i8, ptr [[P]], i32 [[I]]
723 ; CHECK-NEXT:    [[COND:%.*]] = call i1 @cond2()
724 ; CHECK-NEXT:    br i1 [[COND]], label [[CONT]], label [[OUT:%.*]]
725 ; CHECK:       cont:
726 ; CHECK-NEXT:    [[Z:%.*]] = getelementptr i8, ptr [[X2]], i32 -1
727 ; CHECK-NEXT:    store i32 50462976, ptr [[Z]], align 4
728 ; CHECK-NEXT:    [[X2_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr [[P]], i32 3
729 ; CHECK-NEXT:    [[Y2_PRE]] = load i8, ptr [[X2_PHI_TRANS_INSERT]], align 1
730 ; CHECK-NEXT:    br label [[LOOP]]
731 ; CHECK:       out:
732 ; CHECK-NEXT:    [[R:%.*]] = add i8 [[Y]], [[Y2]]
733 ; CHECK-NEXT:    ret i8 [[R]]
735 entry:
737   %X4 = getelementptr i8, ptr %p, i32 2
738   store i8 19, ptr %X4
740   %X = getelementptr i8, ptr %p, i32 4
741   %Y = load i8, ptr %X
742   br label %loop
744 loop:
745   %i = phi i32 [4, %entry], [3, %cont]
746   %X2 = getelementptr i8, ptr %p, i32 %i
747   %Y2 = load i8, ptr %X2  ; Ensure this load is not being incorrectly replaced.
748   %cond = call i1 @cond2()
749   br i1 %cond, label %cont, label %out
751 cont:
752   %Z = getelementptr i8, ptr %X2, i32 -1
753   store i32 50462976, ptr %Z  ;; (1 << 8) | (2 << 16) | (3 << 24)
756   br label %loop
758 out:
759   %R = add i8 %Y, %Y2
760   ret i8 %R
763 declare void @use_i32(i32) readonly
765 ; indirectbr currently prevents MergeBlockIntoPredecessor from merging latch
766 ; into header. Make sure we translate the address for %l1 correctly where
767 ; parts of the address computations are in different basic blocks.
768 define i32 @phi_trans6(ptr noalias nocapture readonly %x, i1 %cond) {
769 ; CHECK-LABEL: @phi_trans6(
770 ; CHECK-NEXT:  entry:
771 ; CHECK-NEXT:    [[L0:%.*]] = load i32, ptr [[X:%.*]], align 4
772 ; CHECK-NEXT:    call void @use_i32(i32 [[L0]])
773 ; CHECK-NEXT:    br label [[HEADER:%.*]]
774 ; CHECK:       header:
775 ; CHECK-NEXT:    [[L1:%.*]] = phi i32 [ [[L0]], [[ENTRY:%.*]] ], [ [[L1_PRE:%.*]], [[LATCH_HEADER_CRIT_EDGE:%.*]] ]
776 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT:%.*]], [[LATCH_HEADER_CRIT_EDGE]] ]
777 ; CHECK-NEXT:    indirectbr ptr blockaddress(@phi_trans6, [[LATCH:%.*]]), [label %latch]
778 ; CHECK:       latch:
779 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
780 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[LATCH_HEADER_CRIT_EDGE]]
781 ; CHECK:       latch.header_crit_edge:
782 ; CHECK-NEXT:    [[GEP_1_PHI_TRANS_INSERT_PHI_TRANS_INSERT:%.*]] = getelementptr i32, ptr [[X]], i32 [[IV_NEXT]]
783 ; CHECK-NEXT:    [[L1_PRE]] = load i32, ptr [[GEP_1_PHI_TRANS_INSERT_PHI_TRANS_INSERT]], align 4
784 ; CHECK-NEXT:    br label [[HEADER]]
785 ; CHECK:       exit:
786 ; CHECK-NEXT:    ret i32 [[L1]]
788 entry:
789   %l0 = load i32, ptr %x
790   call void @use_i32(i32 %l0)
791   br label %header
793 header:
794   %iv = phi i32 [0, %entry], [ %iv.next, %latch]
795   indirectbr ptr blockaddress(@phi_trans6, %latch), [label %latch]
797 latch:
798   %gep.1 = getelementptr i32, ptr %x, i32 %iv
799   %l1 = load i32, ptr %gep.1
800   %iv.next = add i32 %iv, 1
801   br i1 %cond, label %exit, label %header
803 exit:
804   ret i32 %l1
807 ; FIXME: Currently we fail to translate the PHI in this case.
808 define i32 @phi_trans7(ptr noalias nocapture readonly %x, i1 %cond) {
809 ; CHECK-LABEL: @phi_trans7(
810 ; CHECK-NEXT:  entry:
811 ; CHECK-NEXT:    [[L0:%.*]] = load i32, ptr [[X:%.*]], align 4
812 ; CHECK-NEXT:    call void @use_i32(i32 [[L0]])
813 ; CHECK-NEXT:    br label [[HEADER:%.*]]
814 ; CHECK:       header:
815 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH_HEADER_CRIT_EDGE:%.*]] ]
816 ; CHECK-NEXT:    [[OFFSET:%.*]] = add i32 [[IV]], -2
817 ; CHECK-NEXT:    indirectbr ptr blockaddress(@phi_trans7, [[LATCH:%.*]]), [label %latch]
818 ; CHECK:       latch:
819 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i32, ptr [[X]], i32 [[OFFSET]]
820 ; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[GEP_1]], align 4
821 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
822 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[LATCH_HEADER_CRIT_EDGE]]
823 ; CHECK:       latch.header_crit_edge:
824 ; CHECK-NEXT:    br label [[HEADER]]
825 ; CHECK:       exit:
826 ; CHECK-NEXT:    ret i32 [[L1]]
828 entry:
829   %l0 = load i32, ptr %x
830   call void @use_i32(i32 %l0)
831   br label %header
833 header:
834   %iv = phi i32 [2, %entry], [ %iv.next, %latch]
835   %offset = add i32 %iv, -2
836   indirectbr ptr blockaddress(@phi_trans7, %latch), [label %latch]
838 latch:
839   %gep.1 = getelementptr i32, ptr %x, i32 %offset
840   %l1 = load i32, ptr %gep.1
841   %iv.next = add i32 %iv, 1
842   br i1 %cond, label %exit, label %header
844 exit:
845   ret i32 %l1
848 ; FIXME: Currently we fail to translate the PHI in this case.
849 define i32 @phi_trans8(ptr noalias nocapture readonly %x, i1 %cond) {
850 ; CHECK-LABEL: @phi_trans8(
851 ; CHECK-NEXT:  entry:
852 ; CHECK-NEXT:    [[L0:%.*]] = load i32, ptr [[X:%.*]], align 4
853 ; CHECK-NEXT:    call void @use_i32(i32 [[L0]])
854 ; CHECK-NEXT:    br label [[HEADER:%.*]]
855 ; CHECK:       header:
856 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH_HEADER_CRIT_EDGE:%.*]] ]
857 ; CHECK-NEXT:    indirectbr ptr blockaddress(@phi_trans8, [[LATCH:%.*]]), [label %latch]
858 ; CHECK:       latch:
859 ; CHECK-NEXT:    [[OFFSET:%.*]] = add i32 [[IV]], -2
860 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i32, ptr [[X]], i32 [[OFFSET]]
861 ; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[GEP_1]], align 4
862 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
863 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[LATCH_HEADER_CRIT_EDGE]]
864 ; CHECK:       latch.header_crit_edge:
865 ; CHECK-NEXT:    br label [[HEADER]]
866 ; CHECK:       exit:
867 ; CHECK-NEXT:    ret i32 [[L1]]
869 entry:
870   %l0 = load i32, ptr %x
871   call void @use_i32(i32 %l0)
872   br label %header
874 header:
875   %iv = phi i32 [2, %entry], [ %iv.next, %latch]
876   indirectbr ptr blockaddress(@phi_trans8, %latch), [label %latch]
878 latch:
879   %offset = add i32 %iv, -2
880   %gep.1 = getelementptr i32, ptr %x, i32 %offset
881   %l1 = load i32, ptr %gep.1
882   %iv.next = add i32 %iv, 1
883   br i1 %cond, label %exit, label %header
885 exit:
886   ret i32 %l1
891 ; PR6642
892 define i32 @memset_to_load() nounwind readnone {
893 ; CHECK-LABEL: @memset_to_load(
894 ; CHECK-NEXT:  entry:
895 ; CHECK-NEXT:    [[X:%.*]] = alloca [256 x i32], align 4
896 ; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[X]], i8 0, i64 1024, i1 false)
897 ; CHECK-NEXT:    ret i32 0
899 entry:
900   %x = alloca [256 x i32], align 4                ; <ptr> [#uses=2]
901   call void @llvm.memset.p0.i64(ptr align 4 %x, i8 0, i64 1024, i1 false)
902   %arraydecay = getelementptr inbounds [256 x i32], ptr %x, i32 0, i32 0 ; <ptr>
903   %ttmp1 = load i32, ptr %arraydecay                   ; <i32> [#uses=1]
904   ret i32 %ttmp1
908 ;;===----------------------------------------------------------------------===;;
909 ;; Load -> Load forwarding in partial alias case.
910 ;;===----------------------------------------------------------------------===;;
912 define i32 @load_load_partial_alias(ptr %P) nounwind ssp {
913 ; LE-LABEL: @load_load_partial_alias(
914 ; LE-NEXT:  entry:
915 ; LE-NEXT:    [[TTMP2:%.*]] = load i32, ptr [[P:%.*]], align 4
916 ; LE-NEXT:    [[TMP0:%.*]] = lshr i32 [[TTMP2]], 8
917 ; LE-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
918 ; LE-NEXT:    [[CONV:%.*]] = zext i8 [[TMP1]] to i32
919 ; LE-NEXT:    [[ADD:%.*]] = add nsw i32 [[TTMP2]], [[CONV]]
920 ; LE-NEXT:    ret i32 [[ADD]]
922 ; BE-LABEL: @load_load_partial_alias(
923 ; BE-NEXT:  entry:
924 ; BE-NEXT:    [[TTMP2:%.*]] = load i32, ptr [[P:%.*]], align 4
925 ; BE-NEXT:    [[TMP0:%.*]] = lshr i32 [[TTMP2]], 16
926 ; BE-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
927 ; BE-NEXT:    [[CONV:%.*]] = zext i8 [[TMP1]] to i32
928 ; BE-NEXT:    [[ADD:%.*]] = add nsw i32 [[TTMP2]], [[CONV]]
929 ; BE-NEXT:    ret i32 [[ADD]]
931 entry:
932   %ttmp2 = load i32, ptr %P
933   %add.ptr = getelementptr inbounds i8, ptr %P, i64 1
934   %ttmp5 = load i8, ptr %add.ptr
935   %conv = zext i8 %ttmp5 to i32
936   %add = add nsw i32 %ttmp2, %conv
937   ret i32 %add
941 ; Cross block partial alias case.
942 define i32 @load_load_partial_alias_cross_block(ptr %P) nounwind ssp {
943 ; LE-LABEL: @load_load_partial_alias_cross_block(
944 ; LE-NEXT:  entry:
945 ; LE-NEXT:    [[X1:%.*]] = load i32, ptr [[P:%.*]], align 4
946 ; LE-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X1]], 127
947 ; LE-NEXT:    [[TMP0:%.*]] = lshr i32 [[X1]], 8
948 ; LE-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
949 ; LE-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END:%.*]]
950 ; LE:       land.lhs.true:
951 ; LE-NEXT:    [[CONV6:%.*]] = zext i8 [[TMP1]] to i32
952 ; LE-NEXT:    ret i32 [[CONV6]]
953 ; LE:       if.end:
954 ; LE-NEXT:    ret i32 52
956 ; BE-LABEL: @load_load_partial_alias_cross_block(
957 ; BE-NEXT:  entry:
958 ; BE-NEXT:    [[X1:%.*]] = load i32, ptr [[P:%.*]], align 4
959 ; BE-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X1]], 127
960 ; BE-NEXT:    [[TMP0:%.*]] = lshr i32 [[X1]], 16
961 ; BE-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
962 ; BE-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END:%.*]]
963 ; BE:       land.lhs.true:
964 ; BE-NEXT:    [[CONV6:%.*]] = zext i8 [[TMP1]] to i32
965 ; BE-NEXT:    ret i32 [[CONV6]]
966 ; BE:       if.end:
967 ; BE-NEXT:    ret i32 52
969 entry:
970   %x1 = load i32, ptr %P, align 4
971   %cmp = icmp eq i32 %x1, 127
972   br i1 %cmp, label %land.lhs.true, label %if.end
974 land.lhs.true:                                    ; preds = %entry
975   %arrayidx4 = getelementptr inbounds i8, ptr %P, i64 1
976   %ttmp5 = load i8, ptr %arrayidx4, align 1
977   %conv6 = zext i8 %ttmp5 to i32
978   ret i32 %conv6
980 if.end:
981   ret i32 52
984 define i32 @load_load_partial_alias_cross_block_phi_trans(ptr %P) nounwind {
985 ; LE-LABEL: @load_load_partial_alias_cross_block_phi_trans(
986 ; LE-NEXT:  entry:
987 ; LE-NEXT:    [[X1:%.*]] = load i32, ptr [[P:%.*]], align 4
988 ; LE-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X1]], 127
989 ; LE-NEXT:    [[TMP0:%.*]] = lshr i32 [[X1]], 16
990 ; LE-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
991 ; LE-NEXT:    [[TMP2:%.*]] = lshr i32 [[X1]], 8
992 ; LE-NEXT:    [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
993 ; LE-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[ELSE:%.*]]
994 ; LE:       if:
995 ; LE-NEXT:    br label [[JOIN:%.*]]
996 ; LE:       else:
997 ; LE-NEXT:    br label [[JOIN]]
998 ; LE:       join:
999 ; LE-NEXT:    [[TTMP5:%.*]] = phi i8 [ [[TMP3]], [[IF]] ], [ [[TMP1]], [[ELSE]] ]
1000 ; LE-NEXT:    [[CONV6:%.*]] = zext i8 [[TTMP5]] to i32
1001 ; LE-NEXT:    ret i32 [[CONV6]]
1002 ; LE:       if.end:
1003 ; LE-NEXT:    ret i32 52
1005 ; BE-LABEL: @load_load_partial_alias_cross_block_phi_trans(
1006 ; BE-NEXT:  entry:
1007 ; BE-NEXT:    [[X1:%.*]] = load i32, ptr [[P:%.*]], align 4
1008 ; BE-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X1]], 127
1009 ; BE-NEXT:    [[TMP0:%.*]] = lshr i32 [[X1]], 8
1010 ; BE-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
1011 ; BE-NEXT:    [[TMP2:%.*]] = lshr i32 [[X1]], 16
1012 ; BE-NEXT:    [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
1013 ; BE-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[ELSE:%.*]]
1014 ; BE:       if:
1015 ; BE-NEXT:    br label [[JOIN:%.*]]
1016 ; BE:       else:
1017 ; BE-NEXT:    br label [[JOIN]]
1018 ; BE:       join:
1019 ; BE-NEXT:    [[TTMP5:%.*]] = phi i8 [ [[TMP3]], [[IF]] ], [ [[TMP1]], [[ELSE]] ]
1020 ; BE-NEXT:    [[CONV6:%.*]] = zext i8 [[TTMP5]] to i32
1021 ; BE-NEXT:    ret i32 [[CONV6]]
1022 ; BE:       if.end:
1023 ; BE-NEXT:    ret i32 52
1025 entry:
1026   %x1 = load i32, ptr %P, align 4
1027   %cmp = icmp eq i32 %x1, 127
1028   br i1 %cmp, label %if, label %else
1031   %arrayidx.if = getelementptr inbounds i8, ptr %P, i64 1
1032   br label %join
1034 else:
1035   %arrayidx.else = getelementptr inbounds i8, ptr %P, i64 2
1036   br label %join
1038 join:
1039   %idx = phi i64 [ 1, %if ], [ 2, %else ]
1040   %arrayidx4 = getelementptr inbounds i8, ptr %P, i64 %idx
1041   %ttmp5 = load i8, ptr %arrayidx4, align 1
1042   %conv6 = zext i8 %ttmp5 to i32
1043   ret i32 %conv6
1045 if.end:
1046   ret i32 52
1049 define void @load_load_partial_alias_loop(ptr %P) {
1050 ; LE-LABEL: @load_load_partial_alias_loop(
1051 ; LE-NEXT:  entry:
1052 ; LE-NEXT:    [[P_1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1
1053 ; LE-NEXT:    [[V_1:%.*]] = load i8, ptr [[P_1]], align 1
1054 ; LE-NEXT:    call void @use.i8(i8 [[V_1]])
1055 ; LE-NEXT:    [[V_1_32:%.*]] = load i32, ptr [[P_1]], align 4
1056 ; LE-NEXT:    call void @use.i32(i32 [[V_1_32]])
1057 ; LE-NEXT:    [[TMP0:%.*]] = trunc i32 [[V_1_32]] to i8
1058 ; LE-NEXT:    br label [[LOOP:%.*]]
1059 ; LE:       loop:
1060 ; LE-NEXT:    [[V_I:%.*]] = phi i8 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[V_I_PRE:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ]
1061 ; LE-NEXT:    [[I:%.*]] = phi i64 [ 1, [[ENTRY]] ], [ [[I_INC:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
1062 ; LE-NEXT:    [[P_I:%.*]] = getelementptr i8, ptr [[P]], i64 [[I]]
1063 ; LE-NEXT:    call void @use.i8(i8 [[V_I]])
1064 ; LE-NEXT:    [[V_I_32:%.*]] = load i32, ptr [[P_I]], align 4
1065 ; LE-NEXT:    call void @use.i32(i32 [[V_I_32]])
1066 ; LE-NEXT:    [[I_INC]] = add i64 [[I]], 1
1067 ; LE-NEXT:    [[CMP:%.*]] = icmp ne i64 [[I_INC]], 64
1068 ; LE-NEXT:    br i1 [[CMP]], label [[LOOP_LOOP_CRIT_EDGE]], label [[EXIT:%.*]]
1069 ; LE:       loop.loop_crit_edge:
1070 ; LE-NEXT:    [[P_I_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr [[P]], i64 [[I_INC]]
1071 ; LE-NEXT:    [[V_I_PRE]] = load i8, ptr [[P_I_PHI_TRANS_INSERT]], align 1
1072 ; LE-NEXT:    br label [[LOOP]]
1073 ; LE:       exit:
1074 ; LE-NEXT:    ret void
1076 ; BE-LABEL: @load_load_partial_alias_loop(
1077 ; BE-NEXT:  entry:
1078 ; BE-NEXT:    [[P_1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1
1079 ; BE-NEXT:    [[V_1:%.*]] = load i8, ptr [[P_1]], align 1
1080 ; BE-NEXT:    call void @use.i8(i8 [[V_1]])
1081 ; BE-NEXT:    [[V_1_32:%.*]] = load i32, ptr [[P_1]], align 4
1082 ; BE-NEXT:    call void @use.i32(i32 [[V_1_32]])
1083 ; BE-NEXT:    [[TMP0:%.*]] = lshr i32 [[V_1_32]], 24
1084 ; BE-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
1085 ; BE-NEXT:    br label [[LOOP:%.*]]
1086 ; BE:       loop:
1087 ; BE-NEXT:    [[V_I:%.*]] = phi i8 [ [[TMP1]], [[ENTRY:%.*]] ], [ [[V_I_PRE:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ]
1088 ; BE-NEXT:    [[I:%.*]] = phi i64 [ 1, [[ENTRY]] ], [ [[I_INC:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
1089 ; BE-NEXT:    [[P_I:%.*]] = getelementptr i8, ptr [[P]], i64 [[I]]
1090 ; BE-NEXT:    call void @use.i8(i8 [[V_I]])
1091 ; BE-NEXT:    [[V_I_32:%.*]] = load i32, ptr [[P_I]], align 4
1092 ; BE-NEXT:    call void @use.i32(i32 [[V_I_32]])
1093 ; BE-NEXT:    [[I_INC]] = add i64 [[I]], 1
1094 ; BE-NEXT:    [[CMP:%.*]] = icmp ne i64 [[I_INC]], 64
1095 ; BE-NEXT:    br i1 [[CMP]], label [[LOOP_LOOP_CRIT_EDGE]], label [[EXIT:%.*]]
1096 ; BE:       loop.loop_crit_edge:
1097 ; BE-NEXT:    [[P_I_PHI_TRANS_INSERT:%.*]] = getelementptr i8, ptr [[P]], i64 [[I_INC]]
1098 ; BE-NEXT:    [[V_I_PRE]] = load i8, ptr [[P_I_PHI_TRANS_INSERT]], align 1
1099 ; BE-NEXT:    br label [[LOOP]]
1100 ; BE:       exit:
1101 ; BE-NEXT:    ret void
1103 entry:
1104   %P.1 = getelementptr i8, ptr %P, i64 1
1105   %v.1 = load i8, ptr %P.1
1106   call void @use.i8(i8 %v.1)
1107   %v.1.32 = load i32, ptr %P.1
1108   call void @use.i32(i32 %v.1.32)
1109   br label %loop
1111 loop:
1112   %i = phi i64 [ 1, %entry ], [ %i.inc, %loop ]
1113   %P.i = getelementptr i8, ptr %P, i64 %i
1114   %v.i = load i8, ptr %P.i
1115   call void @use.i8(i8 %v.i)
1116   %v.i.32 = load i32, ptr %P.i
1117   call void @use.i32(i32 %v.i.32)
1118   %i.inc = add i64 %i, 1
1119   %cmp = icmp ne i64 %i.inc, 64
1120   br i1 %cmp, label %loop, label %exit
1122 exit:
1123   ret void
1126 declare void @use.i8(i8) readnone
1127 declare void @use.i32(i32) readnone
1129 @global = external local_unnamed_addr global i8, align 4
1131 define void @load_load_partial_alias_atomic(ptr %arg) {
1132 ; LE-LABEL: @load_load_partial_alias_atomic(
1133 ; LE-NEXT:  bb:
1134 ; LE-NEXT:    [[TMP2_1:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1
1135 ; LE-NEXT:    [[TMP2_3:%.*]] = load i64, ptr [[TMP2_1]], align 4
1136 ; LE-NEXT:    [[TMP3_1:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2
1137 ; LE-NEXT:    [[TMP0:%.*]] = lshr i64 [[TMP2_3]], 8
1138 ; LE-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i8
1139 ; LE-NEXT:    br label [[BB5:%.*]]
1140 ; LE:       bb5:
1141 ; LE-NEXT:    [[TMP4_1:%.*]] = phi i8 [ [[TMP4_1_PRE:%.*]], [[BB5]] ], [ [[TMP1]], [[BB:%.*]] ]
1142 ; LE-NEXT:    [[TMP6_1:%.*]] = load atomic i8, ptr @global acquire, align 4
1143 ; LE-NEXT:    [[TMP7_1:%.*]] = add i8 [[TMP6_1]], [[TMP4_1]]
1144 ; LE-NEXT:    store i8 [[TMP7_1]], ptr [[ARG]], align 1
1145 ; LE-NEXT:    [[TMP4_1_PRE]] = load i8, ptr [[TMP3_1]], align 4
1146 ; LE-NEXT:    br label [[BB5]]
1148 ; BE-LABEL: @load_load_partial_alias_atomic(
1149 ; BE-NEXT:  bb:
1150 ; BE-NEXT:    [[TMP2_1:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1
1151 ; BE-NEXT:    [[TMP2_3:%.*]] = load i64, ptr [[TMP2_1]], align 4
1152 ; BE-NEXT:    [[TMP3_1:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2
1153 ; BE-NEXT:    [[TMP0:%.*]] = lshr i64 [[TMP2_3]], 48
1154 ; BE-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i8
1155 ; BE-NEXT:    br label [[BB5:%.*]]
1156 ; BE:       bb5:
1157 ; BE-NEXT:    [[TMP4_1:%.*]] = phi i8 [ [[TMP4_1_PRE:%.*]], [[BB5]] ], [ [[TMP1]], [[BB:%.*]] ]
1158 ; BE-NEXT:    [[TMP6_1:%.*]] = load atomic i8, ptr @global acquire, align 4
1159 ; BE-NEXT:    [[TMP7_1:%.*]] = add i8 [[TMP6_1]], [[TMP4_1]]
1160 ; BE-NEXT:    store i8 [[TMP7_1]], ptr [[ARG]], align 1
1161 ; BE-NEXT:    [[TMP4_1_PRE]] = load i8, ptr [[TMP3_1]], align 4
1162 ; BE-NEXT:    br label [[BB5]]
1165   %tmp2.1 = getelementptr inbounds i8, ptr %arg, i64 1
1166   %tmp2.3 = load i64, ptr %tmp2.1, align 4
1167   %tmp2.4 = icmp ugt i64 %tmp2.3, 1
1169   %tmp3.1 = getelementptr inbounds i8, ptr %arg, i64 2
1170   br label %bb5
1172 bb5:                                              ; preds = %bb14, %bb
1173   %tmp4.1 = load i8, ptr %tmp3.1, align 4
1174   %tmp6.1 = load atomic i8, ptr @global acquire, align 4
1175   %tmp7.1 = add i8 %tmp6.1, %tmp4.1
1176   store i8 %tmp7.1, ptr %arg
1177   br label %bb5
1181 ;;===----------------------------------------------------------------------===;;
1182 ;; Load Widening
1183 ;; We explicitly choose NOT to widen. And are testing to make sure we don't.
1184 ;;===----------------------------------------------------------------------===;;
1186 %widening1 = type { i32, i8, i8, i8, i8 }
1188 @f = global %widening1 zeroinitializer, align 4
1190 define i32 @test_widening1(ptr %P) nounwind ssp noredzone {
1191 ; CHECK-LABEL: @test_widening1(
1192 ; CHECK-NEXT:  entry:
1193 ; CHECK-NEXT:    [[TTMP:%.*]] = load i8, ptr getelementptr inbounds ([[WIDENING1:%.*]], ptr @f, i64 0, i32 1), align 4
1194 ; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[TTMP]] to i32
1195 ; CHECK-NEXT:    [[TTMP1:%.*]] = load i8, ptr getelementptr inbounds ([[WIDENING1]], ptr @f, i64 0, i32 2), align 1
1196 ; CHECK-NEXT:    [[CONV2:%.*]] = zext i8 [[TTMP1]] to i32
1197 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], [[CONV2]]
1198 ; CHECK-NEXT:    ret i32 [[ADD]]
1200 entry:
1201   %ttmp = load i8, ptr getelementptr inbounds (%widening1, ptr @f, i64 0, i32 1), align 4
1202   %conv = zext i8 %ttmp to i32
1203   %ttmp1 = load i8, ptr getelementptr inbounds (%widening1, ptr @f, i64 0, i32 2), align 1
1204   %conv2 = zext i8 %ttmp1 to i32
1205   %add = add nsw i32 %conv, %conv2
1206   ret i32 %add
1209 define i32 @test_widening2() nounwind ssp noredzone {
1210 ; CHECK-LABEL: @test_widening2(
1211 ; CHECK-NEXT:  entry:
1212 ; CHECK-NEXT:    [[TTMP:%.*]] = load i8, ptr getelementptr inbounds ([[WIDENING1:%.*]], ptr @f, i64 0, i32 1), align 4
1213 ; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[TTMP]] to i32
1214 ; CHECK-NEXT:    [[TTMP1:%.*]] = load i8, ptr getelementptr inbounds ([[WIDENING1]], ptr @f, i64 0, i32 2), align 1
1215 ; CHECK-NEXT:    [[CONV2:%.*]] = zext i8 [[TTMP1]] to i32
1216 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], [[CONV2]]
1217 ; CHECK-NEXT:    [[TTMP2:%.*]] = load i8, ptr getelementptr inbounds ([[WIDENING1]], ptr @f, i64 0, i32 3), align 2
1218 ; CHECK-NEXT:    [[CONV3:%.*]] = zext i8 [[TTMP2]] to i32
1219 ; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i32 [[ADD]], [[CONV3]]
1220 ; CHECK-NEXT:    [[TTMP3:%.*]] = load i8, ptr getelementptr inbounds ([[WIDENING1]], ptr @f, i64 0, i32 4), align 1
1221 ; CHECK-NEXT:    [[CONV4:%.*]] = zext i8 [[TTMP3]] to i32
1222 ; CHECK-NEXT:    [[ADD3:%.*]] = add nsw i32 [[ADD2]], [[CONV4]]
1223 ; CHECK-NEXT:    ret i32 [[ADD3]]
1225 entry:
1226   %ttmp = load i8, ptr getelementptr inbounds (%widening1, ptr @f, i64 0, i32 1), align 4
1227   %conv = zext i8 %ttmp to i32
1228   %ttmp1 = load i8, ptr getelementptr inbounds (%widening1, ptr @f, i64 0, i32 2), align 1
1229   %conv2 = zext i8 %ttmp1 to i32
1230   %add = add nsw i32 %conv, %conv2
1232   %ttmp2 = load i8, ptr getelementptr inbounds (%widening1, ptr @f, i64 0, i32 3), align 2
1233   %conv3 = zext i8 %ttmp2 to i32
1234   %add2 = add nsw i32 %add, %conv3
1236   %ttmp3 = load i8, ptr getelementptr inbounds (%widening1, ptr @f, i64 0, i32 4), align 1
1237   %conv4 = zext i8 %ttmp3 to i32
1238   %add3 = add nsw i32 %add2, %conv4
1240   ret i32 %add3
1244 declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
1246 declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
1247 declare void @llvm.memcpy.p0.p1.i64(ptr nocapture, ptr addrspace(1) nocapture, i64, i1) nounwind
1250 ;;===----------------------------------------------------------------------===;;
1251 ;; Load -> Store dependency which isn't interfered with by a call that happens
1252 ;; before the pointer was captured.
1253 ;;===----------------------------------------------------------------------===;;
1255 %class.X = type { [8 x i8] }
1257 @_ZTV1X = weak_odr constant [5 x ptr] zeroinitializer
1258 @_ZTV1Y = weak_odr constant [5 x ptr] zeroinitializer
1260 declare void @use()
1261 declare void @use3(ptr, ptr)
1263 ; PR8908
1264 define void @test_escape1() nounwind {
1265 ; CHECK-LABEL: @test_escape1(
1266 ; CHECK-NEXT:    [[X:%.*]] = alloca ptr, align 8
1267 ; CHECK-NEXT:    store ptr getelementptr inbounds ([5 x ptr], ptr @_ZTV1X, i64 0, i64 2), ptr [[X]], align 8
1268 ; CHECK-NEXT:    call void @use() #[[ATTR3]]
1269 ; CHECK-NEXT:    call void @use3(ptr [[X]], ptr getelementptr inbounds ([5 x ptr], ptr @_ZTV1X, i64 0, i64 2)) #[[ATTR3]]
1270 ; CHECK-NEXT:    ret void
1272   %x = alloca ptr, align 8
1273   store ptr getelementptr inbounds ([5 x ptr], ptr @_ZTV1X, i64 0, i64 2), ptr %x, align 8
1274   call void @use() nounwind
1275   %DEAD = load ptr, ptr %x, align 8
1276   call void @use3(ptr %x, ptr %DEAD) nounwind
1277   ret void