xref: /aosp_15_r20/external/llvm/test/Analysis/ValueTracking/deref-bitcast-of-gep.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: opt -S -licm < %s | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker
3*9880d681SAndroid Build Coastguard Worker; Note: the !invariant.load is there just solely to let us call @use()
4*9880d681SAndroid Build Coastguard Worker; to add a fake use, and still have the aliasing work out.  The call
5*9880d681SAndroid Build Coastguard Worker; to @use(0) is just to provide a may-unwind exit out of the loop, so
6*9880d681SAndroid Build Coastguard Worker; that LICM cannot hoist out the load simply because it is guaranteed
7*9880d681SAndroid Build Coastguard Worker; to execute.
8*9880d681SAndroid Build Coastguard Worker
9*9880d681SAndroid Build Coastguard Workerdeclare void @use(i32)
10*9880d681SAndroid Build Coastguard Worker
11*9880d681SAndroid Build Coastguard Workerdefine void @f_0(i8* align 4 dereferenceable(1024) %ptr) {
12*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_0(
13*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
14*9880d681SAndroid Build Coastguard Worker; CHECK:  %val = load i32, i32* %ptr.i32
15*9880d681SAndroid Build Coastguard Worker; CHECK:  br label %loop
16*9880d681SAndroid Build Coastguard Worker; CHECK: loop:
17*9880d681SAndroid Build Coastguard Worker; CHECK:  call void @use(i32 0)
18*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void @use(i32 %val)
19*9880d681SAndroid Build Coastguard Worker
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Workerentry:
22*9880d681SAndroid Build Coastguard Worker  %ptr.gep = getelementptr i8, i8* %ptr, i32 32
23*9880d681SAndroid Build Coastguard Worker  %ptr.i32 = bitcast i8* %ptr.gep to i32*
24*9880d681SAndroid Build Coastguard Worker  br label %loop
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Workerloop:
27*9880d681SAndroid Build Coastguard Worker  call void @use(i32 0)
28*9880d681SAndroid Build Coastguard Worker  %val = load i32, i32* %ptr.i32, !invariant.load !{}
29*9880d681SAndroid Build Coastguard Worker  call void @use(i32 %val)
30*9880d681SAndroid Build Coastguard Worker  br label %loop
31*9880d681SAndroid Build Coastguard Worker}
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Workerdefine void @f_1(i8* align 4 dereferenceable_or_null(1024) %ptr) {
34*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_1(
35*9880d681SAndroid Build Coastguard Workerentry:
36*9880d681SAndroid Build Coastguard Worker  %ptr.gep = getelementptr i8, i8* %ptr, i32 32
37*9880d681SAndroid Build Coastguard Worker  %ptr.i32 = bitcast i8* %ptr.gep to i32*
38*9880d681SAndroid Build Coastguard Worker  %ptr_is_null = icmp eq i8* %ptr, null
39*9880d681SAndroid Build Coastguard Worker  br i1 %ptr_is_null, label %leave, label %loop
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Worker; CHECK: loop.preheader:
42*9880d681SAndroid Build Coastguard Worker; CHECK:   %val = load i32, i32* %ptr.i32
43*9880d681SAndroid Build Coastguard Worker; CHECK:   br label %loop
44*9880d681SAndroid Build Coastguard Worker; CHECK: loop:
45*9880d681SAndroid Build Coastguard Worker; CHECK:  call void @use(i32 0)
46*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void @use(i32 %val)
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Workerloop:
49*9880d681SAndroid Build Coastguard Worker  call void @use(i32 0)
50*9880d681SAndroid Build Coastguard Worker  %val = load i32, i32* %ptr.i32, !invariant.load !{}
51*9880d681SAndroid Build Coastguard Worker  call void @use(i32 %val)
52*9880d681SAndroid Build Coastguard Worker  br label %loop
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Workerleave:
55*9880d681SAndroid Build Coastguard Worker  ret void
56*9880d681SAndroid Build Coastguard Worker}
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Workerdefine void @f_2(i8* align 4 dereferenceable_or_null(1024) %ptr) {
59*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @f_2(
60*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: load
61*9880d681SAndroid Build Coastguard Worker; CHECK:  call void @use(i32 0)
62*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  %val = load i32, i32* %ptr.i32, !invariant.load !0
63*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void @use(i32 %val)
64*9880d681SAndroid Build Coastguard Worker
65*9880d681SAndroid Build Coastguard Workerentry:
66*9880d681SAndroid Build Coastguard Worker  ;; Can't hoist, since the alignment does not work out -- (<4 byte
67*9880d681SAndroid Build Coastguard Worker  ;; aligned> + 30) is not necessarily 4 byte aligned.
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker  %ptr.gep = getelementptr i8, i8* %ptr, i32 30
70*9880d681SAndroid Build Coastguard Worker  %ptr.i32 = bitcast i8* %ptr.gep to i32*
71*9880d681SAndroid Build Coastguard Worker  %ptr_is_null = icmp eq i8* %ptr, null
72*9880d681SAndroid Build Coastguard Worker  br i1 %ptr_is_null, label %leave, label %loop
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Workerloop:
75*9880d681SAndroid Build Coastguard Worker  call void @use(i32 0)
76*9880d681SAndroid Build Coastguard Worker  %val = load i32, i32* %ptr.i32, !invariant.load !{}
77*9880d681SAndroid Build Coastguard Worker  call void @use(i32 %val)
78*9880d681SAndroid Build Coastguard Worker  br label %loop
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Workerleave:
81*9880d681SAndroid Build Coastguard Worker  ret void
82*9880d681SAndroid Build Coastguard Worker}
83