xref: /llvm-project/llvm/test/Transforms/GVN/non-integral-pointers.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=gvn -S < %s | FileCheck %s
3
4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4:5"
5target triple = "x86_64-unknown-linux-gnu"
6
7define void @f0(i1 %alwaysFalse, i64 %val, ptr %loc) {
8; CHECK-LABEL: @f0(
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    store i64 [[VAL:%.*]], ptr [[LOC:%.*]], align 8
11; CHECK-NEXT:    br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
12; CHECK:       neverTaken:
13; CHECK-NEXT:    [[PTR:%.*]] = load ptr addrspace(4), ptr [[LOC]], align 8
14; CHECK-NEXT:    store i8 5, ptr addrspace(4) [[PTR]], align 1
15; CHECK-NEXT:    ret void
16; CHECK:       alwaysTaken:
17; CHECK-NEXT:    ret void
18;
19  entry:
20  store i64 %val, ptr %loc
21  br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
22
23  neverTaken:
24  %ptr = load ptr addrspace(4), ptr %loc
25  store i8 5, ptr addrspace(4) %ptr
26  ret void
27
28  alwaysTaken:
29  ret void
30}
31
32define i64 @f1(i1 %alwaysFalse, ptr addrspace(4) %val, ptr %loc) {
33; CHECK-LABEL: @f1(
34; CHECK-NEXT:  entry:
35; CHECK-NEXT:    store ptr addrspace(4) [[VAL:%.*]], ptr [[LOC:%.*]], align 8
36; CHECK-NEXT:    br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
37; CHECK:       neverTaken:
38; CHECK-NEXT:    [[INT:%.*]] = load i64, ptr [[LOC]], align 8
39; CHECK-NEXT:    ret i64 [[INT]]
40; CHECK:       alwaysTaken:
41; CHECK-NEXT:    ret i64 42
42;
43  entry:
44  store ptr addrspace(4) %val, ptr %loc
45  br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
46
47  neverTaken:
48  %int = load i64, ptr %loc
49  ret i64 %int
50
51  alwaysTaken:
52  ret i64 42
53}
54
55;; Note: For terseness, we stop using the %alwaysfalse trick for the
56;; tests below and just exercise the bits of forwarding logic directly.
57
58declare void @llvm.memset.p4.i64(ptr addrspace(4) nocapture, i8, i64, i1) nounwind
59
60; Can't forward as the load might be dead.  (Pretend we wrote out the alwaysfalse idiom above.)
61define ptr addrspace(4) @neg_forward_memset(ptr addrspace(4) %loc) {
62; CHECK-LABEL: @neg_forward_memset(
63; CHECK-NEXT:  entry:
64; CHECK-NEXT:    call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 [[LOC:%.*]], i8 7, i64 8, i1 false)
65; CHECK-NEXT:    [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8
66; CHECK-NEXT:    ret ptr addrspace(4) [[REF]]
67;
68  entry:
69  call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 %loc, i8 7, i64 8, i1 false)
70  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
71  ret ptr addrspace(4) %ref
72}
73
74define <1 x ptr addrspace(4)> @neg_forward_memset_vload(ptr addrspace(4) %loc) {
75; CHECK-LABEL: @neg_forward_memset_vload(
76; CHECK-NEXT:  entry:
77; CHECK-NEXT:    call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 [[LOC:%.*]], i8 7, i64 8, i1 false)
78; CHECK-NEXT:    [[REF:%.*]] = load <1 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 8
79; CHECK-NEXT:    ret <1 x ptr addrspace(4)> [[REF]]
80;
81  entry:
82  call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 %loc, i8 7, i64 8, i1 false)
83  %ref = load <1 x ptr addrspace(4)>, ptr addrspace(4) %loc
84  ret <1 x ptr addrspace(4)> %ref
85}
86
87
88; Can forward since we can do so w/o breaking types
89define ptr addrspace(4) @forward_memset_zero(ptr addrspace(4) %loc) {
90; CHECK-LABEL: @forward_memset_zero(
91; CHECK-NEXT:  entry:
92; CHECK-NEXT:    call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 [[LOC:%.*]], i8 0, i64 8, i1 false)
93; CHECK-NEXT:    ret ptr addrspace(4) null
94;
95  entry:
96  call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 %loc, i8 0, i64 8, i1 false)
97  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
98  ret ptr addrspace(4) %ref
99}
100
101; Can't forward as the load might be dead.  (Pretend we wrote out the alwaysfalse idiom above.)
102define ptr addrspace(4) @neg_forward_store(ptr addrspace(4) %loc) {
103; CHECK-LABEL: @neg_forward_store(
104; CHECK-NEXT:  entry:
105; CHECK-NEXT:    store i64 5, ptr addrspace(4) [[LOC:%.*]], align 8
106; CHECK-NEXT:    [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8
107; CHECK-NEXT:    ret ptr addrspace(4) [[REF]]
108;
109  entry:
110  store i64 5, ptr addrspace(4) %loc
111  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
112  ret ptr addrspace(4) %ref
113}
114
115define <1 x ptr addrspace(4)> @neg_forward_store_vload(ptr addrspace(4) %loc) {
116; CHECK-LABEL: @neg_forward_store_vload(
117; CHECK-NEXT:  entry:
118; CHECK-NEXT:    store i64 5, ptr addrspace(4) [[LOC:%.*]], align 8
119; CHECK-NEXT:    [[REF:%.*]] = load <1 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 8
120; CHECK-NEXT:    ret <1 x ptr addrspace(4)> [[REF]]
121;
122  entry:
123  store i64 5, ptr addrspace(4) %loc
124  %ref = load <1 x ptr addrspace(4)>, ptr addrspace(4) %loc
125  ret <1 x ptr addrspace(4)> %ref
126}
127
128; Nulls have known bit patterns, so we can forward
129define ptr addrspace(4) @forward_store_zero(ptr addrspace(4) %loc) {
130; CHECK-LABEL: @forward_store_zero(
131; CHECK-NEXT:  entry:
132; CHECK-NEXT:    store i64 0, ptr addrspace(4) [[LOC:%.*]], align 8
133; CHECK-NEXT:    ret ptr addrspace(4) null
134;
135  entry:
136  store i64 0, ptr addrspace(4) %loc
137  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
138  ret ptr addrspace(4) %ref
139}
140
141; Nulls have known bit patterns, so we can forward
142define ptr addrspace(4) @forward_store_zero2(ptr addrspace(4) %loc) {
143; CHECK-LABEL: @forward_store_zero2(
144; CHECK-NEXT:  entry:
145; CHECK-NEXT:    store <2 x i32> zeroinitializer, ptr addrspace(4) [[LOC:%.*]], align 8
146; CHECK-NEXT:    ret ptr addrspace(4) null
147;
148  entry:
149  store <2 x i32> zeroinitializer, ptr addrspace(4) %loc
150  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
151  ret ptr addrspace(4) %ref
152}
153
154
155
156@NonZeroConstant = constant <4 x i64> <i64 3, i64 3, i64 3, i64 3>
157@NonZeroConstant2 = constant <4 x ptr addrspace(4)> <
158  ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3),
159  ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3),
160  ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3),
161  ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)>
162@ZeroConstant = constant <4 x i64> zeroinitializer
163
164
165; Can't forward as the load might be dead.  (Pretend we wrote out the alwaysfalse idiom above.)
166define ptr addrspace(4) @neg_forward_memcopy(ptr addrspace(4) %loc) {
167; CHECK-LABEL: @neg_forward_memcopy(
168; CHECK-NEXT:  entry:
169; CHECK-NEXT:    call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 8, i1 false)
170; CHECK-NEXT:    [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8
171; CHECK-NEXT:    ret ptr addrspace(4) [[REF]]
172;
173entry:
174  call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 8, i1 false)
175  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
176  ret ptr addrspace(4) %ref
177}
178
179define ptr addrspace(4) @neg_forward_memcopy2(ptr addrspace(4) %loc) {
180; CHECK-LABEL: @neg_forward_memcopy2(
181; CHECK-NEXT:  entry:
182; CHECK-NEXT:    call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 8, i1 false)
183; CHECK-NEXT:    [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8
184; CHECK-NEXT:    ret ptr addrspace(4) [[REF]]
185;
186entry:
187  call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 8, i1 false)
188  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
189  ret ptr addrspace(4) %ref
190}
191
192define ptr addrspace(4) @forward_memcopy(ptr addrspace(4) %loc) {
193; CHECK-LABEL: @forward_memcopy(
194; CHECK-NEXT:  entry:
195; CHECK-NEXT:    call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 8, i1 false)
196; CHECK-NEXT:    ret ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)
197;
198entry:
199  call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 8, i1 false)
200  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
201  ret ptr addrspace(4) %ref
202}
203
204define ptr addrspace(4) @forward_memcopy2(ptr addrspace(4) %loc) {
205; CHECK-LABEL: @forward_memcopy2(
206; CHECK-NEXT:  entry:
207; CHECK-NEXT:    call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 8, i1 false)
208; CHECK-NEXT:    ret ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)
209;
210entry:
211  call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 8, i1 false)
212  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
213  ret ptr addrspace(4) %ref
214}
215
216define <1 x ptr addrspace(4)> @neg_forward_memcpy_vload(ptr addrspace(4) %loc) {
217; CHECK-LABEL: @neg_forward_memcpy_vload(
218; CHECK-NEXT:  entry:
219; CHECK-NEXT:    call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 8, i1 false)
220; CHECK-NEXT:    [[REF:%.*]] = load <1 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 8
221; CHECK-NEXT:    ret <1 x ptr addrspace(4)> [[REF]]
222;
223entry:
224  call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 8, i1 false)
225  %ref = load <1 x ptr addrspace(4)>, ptr addrspace(4) %loc
226  ret <1 x ptr addrspace(4)> %ref
227}
228
229define <4 x ptr addrspace(4)> @neg_forward_memcpy_vload2(ptr addrspace(4) %loc) {
230; CHECK-LABEL: @neg_forward_memcpy_vload2(
231; CHECK-NEXT:  entry:
232; CHECK-NEXT:    call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 32, i1 false)
233; CHECK-NEXT:    [[REF:%.*]] = load <4 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 32
234; CHECK-NEXT:    ret <4 x ptr addrspace(4)> [[REF]]
235;
236entry:
237  call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 32, i1 false)
238  %ref = load <4 x ptr addrspace(4)>, ptr addrspace(4) %loc
239  ret <4 x ptr addrspace(4)> %ref
240}
241
242define <4 x i64> @neg_forward_memcpy_vload3(ptr addrspace(4) %loc) {
243; CHECK-LABEL: @neg_forward_memcpy_vload3(
244; CHECK-NEXT:  entry:
245; CHECK-NEXT:    call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 32, i1 false)
246; CHECK-NEXT:    [[REF:%.*]] = load <4 x i64>, ptr addrspace(4) [[LOC]], align 32
247; CHECK-NEXT:    ret <4 x i64> [[REF]]
248;
249entry:
250  call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 32, i1 false)
251  %ref = load <4 x i64>, ptr addrspace(4) %loc
252  ret <4 x i64> %ref
253}
254
255define <1 x ptr addrspace(4)> @forward_memcpy_vload3(ptr addrspace(4) %loc) {
256; CHECK-LABEL: @forward_memcpy_vload3(
257; CHECK-NEXT:  entry:
258; CHECK-NEXT:    call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 32, i1 false)
259; CHECK-NEXT:    ret <1 x ptr addrspace(4)> <ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)>
260;
261entry:
262  call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 32, i1 false)
263  %ref = load <4 x ptr addrspace(4)>, ptr addrspace(4) %loc
264  %val = extractelement <4 x ptr addrspace(4)> %ref, i32 0
265  %ret = insertelement <1 x ptr addrspace(4)> undef, ptr addrspace(4) %val, i32 0
266  ret <1 x ptr addrspace(4)> %ret
267}
268
269; Can forward since we can do so w/o breaking types
270define ptr addrspace(4) @forward_memcpy_zero(ptr addrspace(4) %loc) {
271; CHECK-LABEL: @forward_memcpy_zero(
272; CHECK-NEXT:  entry:
273; CHECK-NEXT:    call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @ZeroConstant, i64 8, i1 false)
274; CHECK-NEXT:    ret ptr addrspace(4) null
275;
276entry:
277  call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @ZeroConstant, i64 8, i1 false)
278  %ref = load ptr addrspace(4), ptr addrspace(4) %loc
279  ret ptr addrspace(4) %ref
280}
281
282declare void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) nocapture, ptr nocapture, i64, i1) nounwind
283
284
285; Same as the neg_forward_store cases, but for non defs.
286; (Pretend we wrote out the alwaysfalse idiom above.)
287define ptr addrspace(4) @neg_store_clobber(ptr addrspace(4) %loc) {
288; CHECK-LABEL: @neg_store_clobber(
289; CHECK-NEXT:  entry:
290; CHECK-NEXT:    store <2 x i64> splat (i64 4), ptr addrspace(4) [[LOC:%.*]], align 16
291; CHECK-NEXT:    [[LOC_OFF:%.*]] = getelementptr ptr addrspace(4), ptr addrspace(4) [[LOC]], i64 1
292; CHECK-NEXT:    [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC_OFF]], align 8
293; CHECK-NEXT:    ret ptr addrspace(4) [[REF]]
294;
295entry:
296  store <2 x i64> <i64 4, i64 4>, ptr addrspace(4) %loc
297  %loc.off = getelementptr ptr addrspace(4), ptr addrspace(4) %loc, i64 1
298  %ref = load ptr addrspace(4), ptr addrspace(4) %loc.off
299  ret ptr addrspace(4) %ref
300}
301
302declare void @use(<2 x i64>) inaccessiblememonly
303
304; Same as the neg_forward_store cases, but for non defs.
305; (Pretend we wrote out the alwaysfalse idiom above.)
306define ptr addrspace(4) @neg_load_clobber(ptr addrspace(4) %loc) {
307; CHECK-LABEL: @neg_load_clobber(
308; CHECK-NEXT:  entry:
309; CHECK-NEXT:    [[V:%.*]] = load <2 x i64>, ptr addrspace(4) [[LOC:%.*]], align 16
310; CHECK-NEXT:    call void @use(<2 x i64> [[V]])
311; CHECK-NEXT:    [[LOC_OFF:%.*]] = getelementptr ptr addrspace(4), ptr addrspace(4) [[LOC]], i64 1
312; CHECK-NEXT:    [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC_OFF]], align 8
313; CHECK-NEXT:    ret ptr addrspace(4) [[REF]]
314;
315entry:
316  %v = load <2 x i64>, ptr addrspace(4) %loc
317  call void @use(<2 x i64> %v)
318  %loc.off = getelementptr ptr addrspace(4), ptr addrspace(4) %loc, i64 1
319  %ref = load ptr addrspace(4), ptr addrspace(4) %loc.off
320  ret ptr addrspace(4) %ref
321}
322
323define ptr addrspace(4) @store_clobber_zero(ptr addrspace(4) %loc) {
324; CHECK-LABEL: @store_clobber_zero(
325; CHECK-NEXT:  entry:
326; CHECK-NEXT:    store <2 x i64> zeroinitializer, ptr addrspace(4) [[LOC:%.*]], align 16
327; CHECK-NEXT:    [[LOC_OFF:%.*]] = getelementptr ptr addrspace(4), ptr addrspace(4) [[LOC]], i64 1
328; CHECK-NEXT:    ret ptr addrspace(4) null
329;
330entry:
331  store <2 x i64> zeroinitializer, ptr addrspace(4) %loc
332  %loc.off = getelementptr ptr addrspace(4), ptr addrspace(4) %loc, i64 1
333  %ref = load ptr addrspace(4), ptr addrspace(4) %loc.off
334  ret ptr addrspace(4) %ref
335}
336
337
338define void @smaller_vector(ptr %p) {
339; CHECK-LABEL: @smaller_vector(
340; CHECK-NEXT:  entry:
341; CHECK-NEXT:    [[V4:%.*]] = load <4 x ptr addrspace(4)>, ptr [[P:%.*]], align 32
342; CHECK-NEXT:    [[V2:%.*]] = load <2 x ptr addrspace(4)>, ptr [[P]], align 32
343; CHECK-NEXT:    call void @use.v2(<2 x ptr addrspace(4)> [[V2]])
344; CHECK-NEXT:    call void @use.v4(<4 x ptr addrspace(4)> [[V4]])
345; CHECK-NEXT:    ret void
346;
347entry:
348  %v4 = load <4 x ptr addrspace(4)>, ptr %p, align 32
349  %v2 = load <2 x ptr addrspace(4)>, ptr %p, align 32
350  call void @use.v2(<2 x ptr addrspace(4)> %v2)
351  call void @use.v4(<4 x ptr addrspace(4)> %v4)
352  ret void
353}
354
355define ptr addrspace(4) @vector_extract(ptr %p) {
356; CHECK-LABEL: @vector_extract(
357; CHECK-NEXT:  entry:
358; CHECK-NEXT:    [[V4:%.*]] = load <4 x ptr addrspace(4)>, ptr [[P:%.*]], align 32
359; CHECK-NEXT:    [[RES:%.*]] = load ptr addrspace(4), ptr [[P]], align 32
360; CHECK-NEXT:    call void @use.v4(<4 x ptr addrspace(4)> [[V4]])
361; CHECK-NEXT:    ret ptr addrspace(4) [[RES]]
362;
363entry:
364  %v4 = load <4 x ptr addrspace(4)>, ptr %p, align 32
365  %res = load ptr addrspace(4), ptr %p, align 32
366  call void @use.v4(<4 x ptr addrspace(4)> %v4)
367  ret ptr addrspace(4) %res
368}
369
370declare void @use.v2(<2 x ptr addrspace(4)>)
371declare void @use.v4(<4 x ptr addrspace(4)>)
372define ptr addrspace(5) @multini(i1 %alwaysFalse, ptr addrspace(4) %val, ptr %loc) {
373; CHECK-LABEL: @multini(
374; CHECK-NEXT:  entry:
375; CHECK-NEXT:    store ptr addrspace(4) [[VAL:%.*]], ptr [[LOC:%.*]], align 8
376; CHECK-NEXT:    br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
377; CHECK:       neverTaken:
378; CHECK-NEXT:    [[DIFFERENTAS:%.*]] = load ptr addrspace(5), ptr [[LOC]], align 8
379; CHECK-NEXT:    ret ptr addrspace(5) [[DIFFERENTAS]]
380; CHECK:       alwaysTaken:
381; CHECK-NEXT:    ret ptr addrspace(5) null
382;
383entry:
384  store ptr addrspace(4) %val, ptr %loc
385  br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
386
387neverTaken:
388  %differentas = load ptr addrspace(5), ptr %loc
389  ret ptr addrspace(5) %differentas
390
391alwaysTaken:
392  ret ptr addrspace(5) null
393}
394