xref: /llvm-project/llvm/test/Analysis/BasicAA/gep-alias.ll (revision d69efa4015ca41746b1aa517976cc376bce48860)
1; RUN: opt < %s -aa-pipeline=basic-aa -passes=gvn,instcombine -S 2>&1 | FileCheck %s
2
3target datalayout = "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-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
4
5; Make sure that basicaa thinks R and r are must aliases.
6define i32 @test1(ptr %P) {
7entry:
8	%R = getelementptr {i32, i32}, ptr %P, i32 0, i32 1
9	%S = load i32, ptr %R
10
11	%r = getelementptr {i32, i32}, ptr %P, i32 0, i32 1
12	%s = load i32, ptr %r
13
14	%t = sub i32 %S, %s
15	ret i32 %t
16; CHECK-LABEL: @test1(
17; CHECK: ret i32 0
18}
19
20define i32 @test2(ptr %P) {
21entry:
22	%R = getelementptr {i32, i32, i32}, ptr %P, i32 0, i32 1
23	%S = load i32, ptr %R
24
25	%r = getelementptr {i32, i32, i32}, ptr %P, i32 0, i32 2
26  store i32 42, ptr %r
27
28	%s = load i32, ptr %R
29
30	%t = sub i32 %S, %s
31	ret i32 %t
32; CHECK-LABEL: @test2(
33; CHECK: ret i32 0
34}
35
36
37; This was a miscompilation.
38define i32 @test3(ptr %P) {
39entry:
40  %P2 = getelementptr {float, {i32, i32, i32}}, ptr %P, i32 0, i32 1
41	%R = getelementptr {i32, i32, i32}, ptr %P2, i32 0, i32 1
42	%S = load i32, ptr %R
43
44	%r = getelementptr {i32, i32, i32}, ptr %P2, i32 0, i32 2
45  store i32 42, ptr %r
46
47	%s = load i32, ptr %R
48
49	%t = sub i32 %S, %s
50	ret i32 %t
51; CHECK-LABEL: @test3(
52; CHECK: ret i32 0
53}
54
55
56;; This is reduced from the SmallPtrSet constructor.
57%SmallPtrSetImpl = type { ptr, i32, i32, i32, [1 x ptr] }
58%SmallPtrSet64 = type { %SmallPtrSetImpl, [64 x ptr] }
59
60define i32 @test4(ptr %P) {
61entry:
62  %tmp2 = getelementptr inbounds %SmallPtrSet64, ptr %P, i64 0, i32 0, i32 1
63  store i32 64, ptr %tmp2, align 8
64  %tmp3 = getelementptr inbounds %SmallPtrSet64, ptr %P, i64 0, i32 0, i32 4, i64 64
65  store ptr null, ptr %tmp3, align 8
66  %tmp4 = load i32, ptr %tmp2, align 8
67	ret i32 %tmp4
68; CHECK-LABEL: @test4(
69; CHECK: ret i32 64
70}
71
72; P[i] != p[i+1]
73define i32 @test5(ptr %p, i64 %i) {
74  %pi = getelementptr i32, ptr %p, i64 %i
75  %i.next = add i64 %i, 1
76  %pi.next = getelementptr i32, ptr %p, i64 %i.next
77  %x = load i32, ptr %pi
78  store i32 42, ptr %pi.next
79  %y = load i32, ptr %pi
80  %z = sub i32 %x, %y
81  ret i32 %z
82; CHECK-LABEL: @test5(
83; CHECK: ret i32 0
84}
85
86define i32 @test5_as1_smaller_size(ptr addrspace(1) %p, i8 %i) {
87  %pi = getelementptr i32, ptr addrspace(1) %p, i8 %i
88  %i.next = add i8 %i, 1
89  %pi.next = getelementptr i32, ptr addrspace(1) %p, i8 %i.next
90  %x = load i32, ptr addrspace(1) %pi
91  store i32 42, ptr addrspace(1) %pi.next
92  %y = load i32, ptr addrspace(1) %pi
93  %z = sub i32 %x, %y
94  ret i32 %z
95; CHECK-LABEL: @test5_as1_smaller_size(
96; CHECK: sext
97; CHECK: ret i32 0
98}
99
100define i32 @test5_as1_same_size(ptr addrspace(1) %p, i16 %i) {
101  %pi = getelementptr i32, ptr addrspace(1) %p, i16 %i
102  %i.next = add i16 %i, 1
103  %pi.next = getelementptr i32, ptr addrspace(1) %p, i16 %i.next
104  %x = load i32, ptr addrspace(1) %pi
105  store i32 42, ptr addrspace(1) %pi.next
106  %y = load i32, ptr addrspace(1) %pi
107  %z = sub i32 %x, %y
108  ret i32 %z
109; CHECK-LABEL: @test5_as1_same_size(
110; CHECK: ret i32 0
111}
112
113; P[i] != p[(i*4)|1]
114define i32 @test6(ptr %p, i64 %i1) {
115  %i = shl i64 %i1, 2
116  %pi = getelementptr i32, ptr %p, i64 %i
117  %i.next = or disjoint i64 %i, 1
118  %pi.next = getelementptr i32, ptr %p, i64 %i.next
119  %x = load i32, ptr %pi
120  store i32 42, ptr %pi.next
121  %y = load i32, ptr %pi
122  %z = sub i32 %x, %y
123  ret i32 %z
124; CHECK-LABEL: @test6(
125; CHECK: ret i32 0
126}
127
128; P[i] != p[(i*4)|2048] with disjoint or
129define i32 @test6_higheror(ptr %p, i64 %i1) {
130  %i = shl nuw nsw i64 %i1, 2
131  %pi = getelementptr i32, ptr %p, i64 %i
132  %i.next = or disjoint i64 %i, 2048
133  %pi.next = getelementptr i32, ptr %p, i64 %i.next
134  %x = load i32, ptr %pi
135  store i32 42, ptr %pi.next
136  %y = load i32, ptr %pi
137  %z = sub i32 %x, %y
138  ret i32 %z
139; CHECK-LABEL: @test6_higheror(
140; CHECK: ret i32 0
141}
142
143; P[1] != P[i*4]
144define i32 @test7(ptr %p, i64 %i) {
145  %pi = getelementptr i32, ptr %p, i64 1
146  %i.next = shl i64 %i, 2
147  %pi.next = getelementptr i32, ptr %p, i64 %i.next
148  %x = load i32, ptr %pi
149  store i32 42, ptr %pi.next
150  %y = load i32, ptr %pi
151  %z = sub i32 %x, %y
152  ret i32 %z
153; CHECK-LABEL: @test7(
154; CHECK: ret i32 0
155}
156
157; P[zext(i)] != p[zext(i+1)]
158; PR1143
159define i32 @test8(ptr %p, i16 %i) {
160  %i1 = zext i16 %i to i32
161  %pi = getelementptr i32, ptr %p, i32 %i1
162  %i.next = add i16 %i, 1
163  %i.next2 = zext i16 %i.next to i32
164  %pi.next = getelementptr i32, ptr %p, i32 %i.next2
165  %x = load i32, ptr %pi
166  store i32 42, ptr %pi.next
167  %y = load i32, ptr %pi
168  %z = sub i32 %x, %y
169  ret i32 %z
170; CHECK-LABEL: @test8(
171; CHECK: ret i32 0
172}
173
174define i8 @test9(ptr %P, i32 %i, i32 %j) {
175  %i2 = shl i32 %i, 2
176  %i3 = add i32 %i2, 1
177  ; P2 = P + 1 + 4*i
178  %P2 = getelementptr [4 x i8], ptr %P, i32 0, i32 %i3
179
180  %j2 = shl i32 %j, 2
181
182  ; P4 = P + 4*j
183  %P4 = getelementptr [4 x i8], ptr %P, i32 0, i32 %j2
184
185  %x = load i8, ptr %P2
186  store i8 42, ptr %P4
187  %y = load i8, ptr %P2
188  %z = sub i8 %x, %y
189  ret i8 %z
190; CHECK-LABEL: @test9(
191; CHECK: ret i8 0
192}
193
194define i8 @test10(ptr %P, i32 %i) {
195  %i2 = shl i32 %i, 2
196  %i3 = add i32 %i2, 4
197  ; P2 = P + 4 + 4*i
198  %P2 = getelementptr [4 x i8], ptr %P, i32 0, i32 %i3
199
200  ; P4 = P + 4*i
201  %P4 = getelementptr [4 x i8], ptr %P, i32 0, i32 %i2
202
203  %x = load i8, ptr %P2
204  store i8 42, ptr %P4
205  %y = load i8, ptr %P2
206  %z = sub i8 %x, %y
207  ret i8 %z
208; CHECK-LABEL: @test10(
209; CHECK: ret i8 0
210}
211
212; (This was a miscompilation.)
213define float @test11(i32 %indvar, ptr %q) nounwind ssp {
214  %tmp = mul i32 %indvar, -1
215  %dec = add i32 %tmp, 3
216  %scevgep = getelementptr [4 x [2 x float]], ptr %q, i32 0, i32 %dec
217  %y29 = getelementptr inbounds [2 x float], ptr %q, i32 0, i32 1
218  store float 1.0, ptr %y29, align 4
219  store i64 0, ptr %scevgep, align 4
220  %tmp30 = load float, ptr %y29, align 4
221  ret float %tmp30
222; CHECK-LABEL: @test11(
223; CHECK: ret float %tmp30
224}
225
226; (This was a miscompilation.)
227define i32 @test12(i32 %x, i32 %y, ptr %p) nounwind {
228  %b = getelementptr [13 x i8], ptr %p, i32 %x
229  %d = getelementptr [15 x i8], ptr %b, i32 %y, i32 8
230  store i32 1, ptr %p
231  store i32 0, ptr %d
232  %r = load i32, ptr %p
233  ret i32 %r
234; CHECK-LABEL: @test12(
235; CHECK: ret i32 %r
236}
237
238@P = internal global i32 715827882, align 4
239@Q = internal global i32 715827883, align 4
240@.str = private unnamed_addr constant [7 x i8] c"%u %u\0A\00", align 1
241
242; Make sure we recognize that u[0] and u[Global + Cst] may alias
243; when the addition has wrapping semantic.
244; PR24468.
245; CHECK-LABEL: @test13(
246; Make sure the stores appear before the related loads.
247; CHECK: store i8 42,
248; CHECK: store i8 99,
249; Find the loads and make sure they are used in the arguments to the printf.
250; CHECK: [[T0:%[a-zA-Z0-9_]+]] = load i8, ptr %t, align 1
251; CHECK: [[T0ARG:%[a-zA-Z0-9_]+]] = zext i8 [[T0]] to i32
252; CHECK: [[U0:%[a-zA-Z0-9_]+]] = load i8, ptr %u, align 1
253; CHECK: [[U0ARG:%[a-zA-Z0-9_]+]] = zext i8 [[U0]] to i32
254; CHECK: call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @.str, i32 [[T0ARG]], i32 [[U0ARG]])
255; CHECK: ret
256define void @test13() {
257entry:
258  %t = alloca [3 x i8], align 1
259  %u = alloca [3 x i8], align 1
260  %tmp = load i32, ptr @P, align 4
261  %tmp1 = mul i32 %tmp, 3
262  %mul = add i32 %tmp1, -2147483646
263  %idxprom = zext i32 %mul to i64
264  %arrayidx = getelementptr inbounds [3 x i8], ptr %t, i64 0, i64 %idxprom
265  store i8 42, ptr %arrayidx, align 1
266  %tmp2 = load i32, ptr @Q, align 4
267  %tmp3 = mul i32 %tmp2, 3
268  %mul2 = add i32 %tmp3, 2147483647
269  %idxprom3 = zext i32 %mul2 to i64
270  %arrayidx4 = getelementptr inbounds [3 x i8], ptr %u, i64 0, i64 %idxprom3
271  store i8 99, ptr %arrayidx4, align 1
272  %tmp4 = load i8, ptr %t, align 1
273  %conv = zext i8 %tmp4 to i32
274  %tmp5 = load i8, ptr %u, align 1
275  %conv7 = zext i8 %tmp5 to i32
276  %call = call i32 (ptr, ...) @printf(ptr @.str, i32 %conv, i32 %conv7)
277  ret void
278}
279
280declare i32 @printf(ptr, ...)
281