• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -basicaa -gvn -S -die | FileCheck %s
2
3; 32-bit little endian target.
4target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
5
6;; Trivial RLE test.
7define i32 @test0(i32 %V, i32* %P) {
8  store i32 %V, i32* %P
9
10  %A = load i32* %P
11  ret i32 %A
12; CHECK: @test0
13; CHECK: ret i32 %V
14}
15
16
17;;===----------------------------------------------------------------------===;;
18;; Tests for crashers
19;;===----------------------------------------------------------------------===;;
20
21;; PR5016
22define i8 @crash0({i32, i32} %A, {i32, i32}* %P) {
23  store {i32, i32} %A, {i32, i32}* %P
24  %X = bitcast {i32, i32}* %P to i8*
25  %Y = load i8* %X
26  ret i8 %Y
27}
28
29;; No PR filed, crashed in CaptureTracker.
30declare void @helper()
31define void @crash1() {
32  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* undef, i8* undef, i64 undef, i32 1, i1 false) nounwind
33  %tmp = load i8* bitcast (void ()* @helper to i8*)
34  %x = icmp eq i8 %tmp, 15
35  ret void
36}
37
38
39;;===----------------------------------------------------------------------===;;
40;; Store -> Load  and  Load -> Load forwarding where src and dst are different
41;; types, but where the base pointer is a must alias.
42;;===----------------------------------------------------------------------===;;
43
44;; i32 -> f32 forwarding.
45define float @coerce_mustalias1(i32 %V, i32* %P) {
46  store i32 %V, i32* %P
47
48  %P2 = bitcast i32* %P to float*
49
50  %A = load float* %P2
51  ret float %A
52; CHECK: @coerce_mustalias1
53; CHECK-NOT: load
54; CHECK: ret float
55}
56
57;; i32* -> float forwarding.
58define float @coerce_mustalias2(i32* %V, i32** %P) {
59  store i32* %V, i32** %P
60
61  %P2 = bitcast i32** %P to float*
62
63  %A = load float* %P2
64  ret float %A
65; CHECK: @coerce_mustalias2
66; CHECK-NOT: load
67; CHECK: ret float
68}
69
70;; float -> i32* forwarding.
71define i32* @coerce_mustalias3(float %V, float* %P) {
72  store float %V, float* %P
73
74  %P2 = bitcast float* %P to i32**
75
76  %A = load i32** %P2
77  ret i32* %A
78; CHECK: @coerce_mustalias3
79; CHECK-NOT: load
80; CHECK: ret i32*
81}
82
83;; i32 -> f32 load forwarding.
84define float @coerce_mustalias4(i32* %P, i1 %cond) {
85  %A = load i32* %P
86
87  %P2 = bitcast i32* %P to float*
88  %B = load float* %P2
89  br i1 %cond, label %T, label %F
90T:
91  ret float %B
92
93F:
94  %X = bitcast i32 %A to float
95  ret float %X
96
97; CHECK: @coerce_mustalias4
98; CHECK: %A = load i32* %P
99; CHECK-NOT: load
100; CHECK: ret float
101; CHECK: F:
102}
103
104;; i32 -> i8 forwarding
105define i8 @coerce_mustalias5(i32 %V, i32* %P) {
106  store i32 %V, i32* %P
107
108  %P2 = bitcast i32* %P to i8*
109
110  %A = load i8* %P2
111  ret i8 %A
112; CHECK: @coerce_mustalias5
113; CHECK-NOT: load
114; CHECK: ret i8
115}
116
117;; i64 -> float forwarding
118define float @coerce_mustalias6(i64 %V, i64* %P) {
119  store i64 %V, i64* %P
120
121  %P2 = bitcast i64* %P to float*
122
123  %A = load float* %P2
124  ret float %A
125; CHECK: @coerce_mustalias6
126; CHECK-NOT: load
127; CHECK: ret float
128}
129
130;; i64 -> i8* (32-bit) forwarding
131define i8* @coerce_mustalias7(i64 %V, i64* %P) {
132  store i64 %V, i64* %P
133
134  %P2 = bitcast i64* %P to i8**
135
136  %A = load i8** %P2
137  ret i8* %A
138; CHECK: @coerce_mustalias7
139; CHECK-NOT: load
140; CHECK: ret i8*
141}
142
143; memset -> i16 forwarding.
144define signext i16 @memset_to_i16_local(i16* %A) nounwind ssp {
145entry:
146  %conv = bitcast i16* %A to i8*
147  tail call void @llvm.memset.p0i8.i64(i8* %conv, i8 1, i64 200, i32 1, i1 false)
148  %arrayidx = getelementptr inbounds i16* %A, i64 42
149  %tmp2 = load i16* %arrayidx
150  ret i16 %tmp2
151; CHECK: @memset_to_i16_local
152; CHECK-NOT: load
153; CHECK: ret i16 257
154}
155
156; memset -> float forwarding.
157define float @memset_to_float_local(float* %A, i8 %Val) nounwind ssp {
158entry:
159  %conv = bitcast float* %A to i8*                ; <i8*> [#uses=1]
160  tail call void @llvm.memset.p0i8.i64(i8* %conv, i8 %Val, i64 400, i32 1, i1 false)
161  %arrayidx = getelementptr inbounds float* %A, i64 42 ; <float*> [#uses=1]
162  %tmp2 = load float* %arrayidx                   ; <float> [#uses=1]
163  ret float %tmp2
164; CHECK: @memset_to_float_local
165; CHECK-NOT: load
166; CHECK: zext
167; CHECK-NEXT: shl
168; CHECK-NEXT: or
169; CHECK-NEXT: shl
170; CHECK-NEXT: or
171; CHECK-NEXT: bitcast
172; CHECK-NEXT: ret float
173}
174
175;; non-local memset -> i16 load forwarding.
176define i16 @memset_to_i16_nonlocal0(i16* %P, i1 %cond) {
177  %P3 = bitcast i16* %P to i8*
178  br i1 %cond, label %T, label %F
179T:
180  tail call void @llvm.memset.p0i8.i64(i8* %P3, i8 1, i64 400, i32 1, i1 false)
181  br label %Cont
182
183F:
184  tail call void @llvm.memset.p0i8.i64(i8* %P3, i8 2, i64 400, i32 1, i1 false)
185  br label %Cont
186
187Cont:
188  %P2 = getelementptr i16* %P, i32 4
189  %A = load i16* %P2
190  ret i16 %A
191
192; CHECK: @memset_to_i16_nonlocal0
193; CHECK: Cont:
194; CHECK-NEXT:   %A = phi i16 [ 514, %F ], [ 257, %T ]
195; CHECK-NOT: load
196; CHECK: ret i16 %A
197}
198
199@GCst = constant {i32, float, i32 } { i32 42, float 14., i32 97 }
200
201; memset -> float forwarding.
202define float @memcpy_to_float_local(float* %A) nounwind ssp {
203entry:
204  %conv = bitcast float* %A to i8*                ; <i8*> [#uses=1]
205  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %conv, i8* bitcast ({i32, float, i32 }* @GCst to i8*), i64 12, i32 1, i1 false)
206  %arrayidx = getelementptr inbounds float* %A, i64 1 ; <float*> [#uses=1]
207  %tmp2 = load float* %arrayidx                   ; <float> [#uses=1]
208  ret float %tmp2
209; CHECK: @memcpy_to_float_local
210; CHECK-NOT: load
211; CHECK: ret float 1.400000e+01
212}
213
214
215
216;; non-local i32/float -> i8 load forwarding.
217define i8 @coerce_mustalias_nonlocal0(i32* %P, i1 %cond) {
218  %P2 = bitcast i32* %P to float*
219  %P3 = bitcast i32* %P to i8*
220  br i1 %cond, label %T, label %F
221T:
222  store i32 42, i32* %P
223  br label %Cont
224
225F:
226  store float 1.0, float* %P2
227  br label %Cont
228
229Cont:
230  %A = load i8* %P3
231  ret i8 %A
232
233; CHECK: @coerce_mustalias_nonlocal0
234; CHECK: Cont:
235; CHECK:   %A = phi i8 [
236; CHECK-NOT: load
237; CHECK: ret i8 %A
238}
239
240
241;; non-local i32/float -> i8 load forwarding.  This also tests that the "P3"
242;; bitcast equivalence can be properly phi translated.
243define i8 @coerce_mustalias_nonlocal1(i32* %P, i1 %cond) {
244  %P2 = bitcast i32* %P to float*
245  br i1 %cond, label %T, label %F
246T:
247  store i32 42, i32* %P
248  br label %Cont
249
250F:
251  store float 1.0, float* %P2
252  br label %Cont
253
254Cont:
255  %P3 = bitcast i32* %P to i8*
256  %A = load i8* %P3
257  ret i8 %A
258
259;; FIXME: This is disabled because this caused a miscompile in the llvm-gcc
260;; bootstrap, see r82411
261;
262; HECK: @coerce_mustalias_nonlocal1
263; HECK: Cont:
264; HECK:   %A = phi i8 [
265; HECK-NOT: load
266; HECK: ret i8 %A
267}
268
269
270;; non-local i32 -> i8 partial redundancy load forwarding.
271define i8 @coerce_mustalias_pre0(i32* %P, i1 %cond) {
272  %P3 = bitcast i32* %P to i8*
273  br i1 %cond, label %T, label %F
274T:
275  store i32 42, i32* %P
276  br label %Cont
277
278F:
279  br label %Cont
280
281Cont:
282  %A = load i8* %P3
283  ret i8 %A
284
285; CHECK: @coerce_mustalias_pre0
286; CHECK: F:
287; CHECK:   load i8* %P3
288; CHECK: Cont:
289; CHECK:   %A = phi i8 [
290; CHECK-NOT: load
291; CHECK: ret i8 %A
292}
293
294;;===----------------------------------------------------------------------===;;
295;; Store -> Load  and  Load -> Load forwarding where src and dst are different
296;; types, and the reload is an offset from the store pointer.
297;;===----------------------------------------------------------------------===;;
298
299;; i32 -> i8 forwarding.
300;; PR4216
301define i8 @coerce_offset0(i32 %V, i32* %P) {
302  store i32 %V, i32* %P
303
304  %P2 = bitcast i32* %P to i8*
305  %P3 = getelementptr i8* %P2, i32 2
306
307  %A = load i8* %P3
308  ret i8 %A
309; CHECK: @coerce_offset0
310; CHECK-NOT: load
311; CHECK: ret i8
312}
313
314;; non-local i32/float -> i8 load forwarding.
315define i8 @coerce_offset_nonlocal0(i32* %P, i1 %cond) {
316  %P2 = bitcast i32* %P to float*
317  %P3 = bitcast i32* %P to i8*
318  %P4 = getelementptr i8* %P3, i32 2
319  br i1 %cond, label %T, label %F
320T:
321  store i32 42, i32* %P
322  br label %Cont
323
324F:
325  store float 1.0, float* %P2
326  br label %Cont
327
328Cont:
329  %A = load i8* %P4
330  ret i8 %A
331
332; CHECK: @coerce_offset_nonlocal0
333; CHECK: Cont:
334; CHECK:   %A = phi i8 [
335; CHECK-NOT: load
336; CHECK: ret i8 %A
337}
338
339
340;; non-local i32 -> i8 partial redundancy load forwarding.
341define i8 @coerce_offset_pre0(i32* %P, i1 %cond) {
342  %P3 = bitcast i32* %P to i8*
343  %P4 = getelementptr i8* %P3, i32 2
344  br i1 %cond, label %T, label %F
345T:
346  store i32 42, i32* %P
347  br label %Cont
348
349F:
350  br label %Cont
351
352Cont:
353  %A = load i8* %P4
354  ret i8 %A
355
356; CHECK: @coerce_offset_pre0
357; CHECK: F:
358; CHECK:   load i8* %P4
359; CHECK: Cont:
360; CHECK:   %A = phi i8 [
361; CHECK-NOT: load
362; CHECK: ret i8 %A
363}
364
365define i32 @chained_load(i32** %p) {
366block1:
367  %A = alloca i32*
368
369  %z = load i32** %p
370  store i32* %z, i32** %A
371  br i1 true, label %block2, label %block3
372
373block2:
374 %a = load i32** %p
375 br label %block4
376
377block3:
378  %b = load i32** %p
379  br label %block4
380
381block4:
382  %c = load i32** %p
383  %d = load i32* %c
384  ret i32 %d
385
386; CHECK: @chained_load
387; CHECK: %z = load i32** %p
388; CHECK-NOT: load
389; CHECK: %d = load i32* %z
390; CHECK-NEXT: ret i32 %d
391}
392
393
394declare i1 @cond() readonly
395declare i1 @cond2() readonly
396
397define i32 @phi_trans2() {
398; CHECK: @phi_trans2
399entry:
400  %P = alloca i32, i32 400
401  br label %F1
402
403F1:
404  %A = phi i32 [1, %entry], [2, %F]
405  %cond2 = call i1 @cond()
406  br i1 %cond2, label %T1, label %TY
407
408T1:
409  %P2 = getelementptr i32* %P, i32 %A
410  %x = load i32* %P2
411  %cond = call i1 @cond2()
412  br i1 %cond, label %TX, label %F
413
414F:
415  %P3 = getelementptr i32* %P, i32 2
416  store i32 17, i32* %P3
417
418  store i32 42, i32* %P2  ; Provides "P[A]".
419  br label %F1
420
421TX:
422  ; This load should not be compiled to 'ret i32 42'.  An overly clever
423  ; implementation of GVN would see that we're returning 17 if the loop
424  ; executes once or 42 if it executes more than that, but we'd have to do
425  ; loop restructuring to expose this, and GVN shouldn't do this sort of CFG
426  ; transformation.
427
428; CHECK: TX:
429; CHECK: ret i32 %x
430  ret i32 %x
431TY:
432  ret i32 0
433}
434
435define i32 @phi_trans3(i32* %p) {
436; CHECK: @phi_trans3
437block1:
438  br i1 true, label %block2, label %block3
439
440block2:
441 store i32 87, i32* %p
442 br label %block4
443
444block3:
445  %p2 = getelementptr i32* %p, i32 43
446  store i32 97, i32* %p2
447  br label %block4
448
449block4:
450  %A = phi i32 [-1, %block2], [42, %block3]
451  br i1 true, label %block5, label %exit
452
453; CHECK: block4:
454; CHECK-NEXT: %D = phi i32 [ 87, %block2 ], [ 97, %block3 ]
455; CHECK-NOT: load
456
457block5:
458  %B = add i32 %A, 1
459  br i1 true, label %block6, label %exit
460
461block6:
462  %C = getelementptr i32* %p, i32 %B
463  br i1 true, label %block7, label %exit
464
465block7:
466  %D = load i32* %C
467  ret i32 %D
468
469; CHECK: block7:
470; CHECK-NEXT: ret i32 %D
471
472exit:
473  ret i32 -1
474}
475
476define i8 @phi_trans4(i8* %p) {
477; CHECK: @phi_trans4
478entry:
479  %X3 = getelementptr i8* %p, i32 192
480  store i8 192, i8* %X3
481
482  %X = getelementptr i8* %p, i32 4
483  %Y = load i8* %X
484  br label %loop
485
486loop:
487  %i = phi i32 [4, %entry], [192, %loop]
488  %X2 = getelementptr i8* %p, i32 %i
489  %Y2 = load i8* %X2
490
491; CHECK: loop:
492; CHECK-NEXT: %Y2 = phi i8 [ %Y, %entry ], [ 0, %loop ]
493; CHECK-NOT: load i8
494
495  %cond = call i1 @cond2()
496
497  %Z = bitcast i8 *%X3 to i32*
498  store i32 0, i32* %Z
499  br i1 %cond, label %loop, label %out
500
501out:
502  %R = add i8 %Y, %Y2
503  ret i8 %R
504}
505
506define i8 @phi_trans5(i8* %p) {
507; CHECK: @phi_trans5
508entry:
509
510  %X4 = getelementptr i8* %p, i32 2
511  store i8 19, i8* %X4
512
513  %X = getelementptr i8* %p, i32 4
514  %Y = load i8* %X
515  br label %loop
516
517loop:
518  %i = phi i32 [4, %entry], [3, %cont]
519  %X2 = getelementptr i8* %p, i32 %i
520  %Y2 = load i8* %X2  ; Ensure this load is not being incorrectly replaced.
521  %cond = call i1 @cond2()
522  br i1 %cond, label %cont, label %out
523
524cont:
525  %Z = getelementptr i8* %X2, i32 -1
526  %Z2 = bitcast i8 *%Z to i32*
527  store i32 50462976, i32* %Z2  ;; (1 << 8) | (2 << 16) | (3 << 24)
528
529
530; CHECK: store i32
531; CHECK-NEXT: getelementptr i8* %p, i32 3
532; CHECK-NEXT: load i8*
533  br label %loop
534
535out:
536  %R = add i8 %Y, %Y2
537  ret i8 %R
538}
539
540
541; PR6642
542define i32 @memset_to_load() nounwind readnone {
543entry:
544  %x = alloca [256 x i32], align 4                ; <[256 x i32]*> [#uses=2]
545  %tmp = bitcast [256 x i32]* %x to i8*           ; <i8*> [#uses=1]
546  call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 1024, i32 4, i1 false)
547  %arraydecay = getelementptr inbounds [256 x i32]* %x, i32 0, i32 0 ; <i32*>
548  %tmp1 = load i32* %arraydecay                   ; <i32> [#uses=1]
549  ret i32 %tmp1
550; CHECK: @memset_to_load
551; CHECK: ret i32 0
552}
553
554
555;;===----------------------------------------------------------------------===;;
556;; Load -> Load forwarding in partial alias case.
557;;===----------------------------------------------------------------------===;;
558
559define i32 @load_load_partial_alias(i8* %P) nounwind ssp {
560entry:
561  %0 = bitcast i8* %P to i32*
562  %tmp2 = load i32* %0
563  %add.ptr = getelementptr inbounds i8* %P, i64 1
564  %tmp5 = load i8* %add.ptr
565  %conv = zext i8 %tmp5 to i32
566  %add = add nsw i32 %tmp2, %conv
567  ret i32 %add
568
569; TEMPORARILYDISABLED: @load_load_partial_alias
570; TEMPORARILYDISABLED: load i32*
571; TEMPORARILYDISABLED-NOT: load
572; TEMPORARILYDISABLED: lshr i32 {{.*}}, 8
573; TEMPORARILYDISABLED-NOT: load
574; TEMPORARILYDISABLED: trunc i32 {{.*}} to i8
575; TEMPORARILYDISABLED-NOT: load
576; TEMPORARILYDISABLED: ret i32
577}
578
579
580; Cross block partial alias case.
581define i32 @load_load_partial_alias_cross_block(i8* %P) nounwind ssp {
582entry:
583  %xx = bitcast i8* %P to i32*
584  %x1 = load i32* %xx, align 4
585  %cmp = icmp eq i32 %x1, 127
586  br i1 %cmp, label %land.lhs.true, label %if.end
587
588land.lhs.true:                                    ; preds = %entry
589  %arrayidx4 = getelementptr inbounds i8* %P, i64 1
590  %tmp5 = load i8* %arrayidx4, align 1
591  %conv6 = zext i8 %tmp5 to i32
592  ret i32 %conv6
593
594if.end:
595  ret i32 52
596; TEMPORARILY_DISABLED: @load_load_partial_alias_cross_block
597; TEMPORARILY_DISABLED: land.lhs.true:
598; TEMPORARILY_DISABLED-NOT: load i8
599; TEMPORARILY_DISABLED: ret i32 %conv6
600}
601
602
603;;===----------------------------------------------------------------------===;;
604;; Load Widening
605;;===----------------------------------------------------------------------===;;
606
607%widening1 = type { i32, i8, i8, i8, i8 }
608
609@f = global %widening1 zeroinitializer, align 4
610
611define i32 @test_widening1(i8* %P) nounwind ssp noredzone {
612entry:
613  %tmp = load i8* getelementptr inbounds (%widening1* @f, i64 0, i32 1), align 4
614  %conv = zext i8 %tmp to i32
615  %tmp1 = load i8* getelementptr inbounds (%widening1* @f, i64 0, i32 2), align 1
616  %conv2 = zext i8 %tmp1 to i32
617  %add = add nsw i32 %conv, %conv2
618  ret i32 %add
619; CHECK: @test_widening1
620; CHECK-NOT: load
621; CHECK: load i16*
622; CHECK-NOT: load
623; CHECK-ret i32
624}
625
626define i32 @test_widening2() nounwind ssp noredzone {
627entry:
628  %tmp = load i8* getelementptr inbounds (%widening1* @f, i64 0, i32 1), align 4
629  %conv = zext i8 %tmp to i32
630  %tmp1 = load i8* getelementptr inbounds (%widening1* @f, i64 0, i32 2), align 1
631  %conv2 = zext i8 %tmp1 to i32
632  %add = add nsw i32 %conv, %conv2
633
634  %tmp2 = load i8* getelementptr inbounds (%widening1* @f, i64 0, i32 3), align 2
635  %conv3 = zext i8 %tmp2 to i32
636  %add2 = add nsw i32 %add, %conv3
637
638  %tmp3 = load i8* getelementptr inbounds (%widening1* @f, i64 0, i32 4), align 1
639  %conv4 = zext i8 %tmp3 to i32
640  %add3 = add nsw i32 %add2, %conv3
641
642  ret i32 %add3
643; CHECK: @test_widening2
644; CHECK-NOT: load
645; CHECK: load i32*
646; CHECK-NOT: load
647; CHECK-ret i32
648}
649
650declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
651
652declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
653
654;;===----------------------------------------------------------------------===;;
655;; Load -> Store dependency which isn't interfered with by a call that happens
656;; before the pointer was captured.
657;;===----------------------------------------------------------------------===;;
658
659%class.X = type { [8 x i8] }
660
661@_ZTV1X = weak_odr constant [5 x i8*] zeroinitializer
662@_ZTV1Y = weak_odr constant [5 x i8*] zeroinitializer
663
664declare void @use()
665declare void @use3(i8***, i8**)
666
667; PR8908
668define void @test_escape1() nounwind {
669  %x = alloca i8**, align 8
670  store i8** getelementptr inbounds ([5 x i8*]* @_ZTV1X, i64 0, i64 2), i8*** %x, align 8
671  call void @use() nounwind
672  %DEAD = load i8*** %x, align 8
673  call void @use3(i8*** %x, i8** %DEAD) nounwind
674  ret void
675; CHECK: test_escape1
676; CHECK-NOT: DEAD
677; CHECK: ret
678}
679