1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=gvn -S < %s | FileCheck %s
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4:5"
5 target triple = "x86_64-unknown-linux-gnu"
7 define void @f0(i1 %alwaysFalse, i64 %val, ptr %loc) {
10 ; CHECK-NEXT: store i64 [[VAL:%.*]], ptr [[LOC:%.*]], align 8
11 ; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
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
17 ; CHECK-NEXT: ret void
20 store i64 %val, ptr %loc
21 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
24 %ptr = load ptr addrspace(4), ptr %loc
25 store i8 5, ptr addrspace(4) %ptr
32 define i64 @f1(i1 %alwaysFalse, ptr addrspace(4) %val, ptr %loc) {
35 ; CHECK-NEXT: store ptr addrspace(4) [[VAL:%.*]], ptr [[LOC:%.*]], align 8
36 ; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
38 ; CHECK-NEXT: [[INT:%.*]] = load i64, ptr [[LOC]], align 8
39 ; CHECK-NEXT: ret i64 [[INT]]
41 ; CHECK-NEXT: ret i64 42
44 store ptr addrspace(4) %val, ptr %loc
45 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
48 %int = load i64, ptr %loc
55 ;; Note: For terseness, we stop using the %alwaysfalse trick for the
56 ;; tests below and just exercise the bits of forwarding logic directly.
58 declare void @llvm.memset.p4.i64(ptr addrspace(4) nocapture, i8, i64, i1) nounwind
60 ; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)
61 define ptr addrspace(4) @neg_forward_memset(ptr addrspace(4) %loc) {
62 ; CHECK-LABEL: @neg_forward_memset(
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]]
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
74 define <1 x ptr addrspace(4)> @neg_forward_memset_vload(ptr addrspace(4) %loc) {
75 ; CHECK-LABEL: @neg_forward_memset_vload(
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]]
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
88 ; Can forward since we can do so w/o breaking types
89 define ptr addrspace(4) @forward_memset_zero(ptr addrspace(4) %loc) {
90 ; CHECK-LABEL: @forward_memset_zero(
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
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
101 ; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)
102 define ptr addrspace(4) @neg_forward_store(ptr addrspace(4) %loc) {
103 ; CHECK-LABEL: @neg_forward_store(
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]]
110 store i64 5, ptr addrspace(4) %loc
111 %ref = load ptr addrspace(4), ptr addrspace(4) %loc
112 ret ptr addrspace(4) %ref
115 define <1 x ptr addrspace(4)> @neg_forward_store_vload(ptr addrspace(4) %loc) {
116 ; CHECK-LABEL: @neg_forward_store_vload(
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]]
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
128 ; Nulls have known bit patterns, so we can forward
129 define ptr addrspace(4) @forward_store_zero(ptr addrspace(4) %loc) {
130 ; CHECK-LABEL: @forward_store_zero(
132 ; CHECK-NEXT: store i64 0, ptr addrspace(4) [[LOC:%.*]], align 8
133 ; CHECK-NEXT: ret ptr addrspace(4) null
136 store i64 0, ptr addrspace(4) %loc
137 %ref = load ptr addrspace(4), ptr addrspace(4) %loc
138 ret ptr addrspace(4) %ref
141 ; Nulls have known bit patterns, so we can forward
142 define ptr addrspace(4) @forward_store_zero2(ptr addrspace(4) %loc) {
143 ; CHECK-LABEL: @forward_store_zero2(
145 ; CHECK-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(4) [[LOC:%.*]], align 8
146 ; CHECK-NEXT: ret ptr addrspace(4) null
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
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
165 ; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)
166 define ptr addrspace(4) @neg_forward_memcopy(ptr addrspace(4) %loc) {
167 ; CHECK-LABEL: @neg_forward_memcopy(
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]]
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
179 define ptr addrspace(4) @neg_forward_memcopy2(ptr addrspace(4) %loc) {
180 ; CHECK-LABEL: @neg_forward_memcopy2(
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]]
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
192 define ptr addrspace(4) @forward_memcopy(ptr addrspace(4) %loc) {
193 ; CHECK-LABEL: @forward_memcopy(
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)
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
204 define ptr addrspace(4) @forward_memcopy2(ptr addrspace(4) %loc) {
205 ; CHECK-LABEL: @forward_memcopy2(
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)
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
216 define <1 x ptr addrspace(4)> @neg_forward_memcpy_vload(ptr addrspace(4) %loc) {
217 ; CHECK-LABEL: @neg_forward_memcpy_vload(
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]]
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
229 define <4 x ptr addrspace(4)> @neg_forward_memcpy_vload2(ptr addrspace(4) %loc) {
230 ; CHECK-LABEL: @neg_forward_memcpy_vload2(
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]]
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
242 define <4 x i64> @neg_forward_memcpy_vload3(ptr addrspace(4) %loc) {
243 ; CHECK-LABEL: @neg_forward_memcpy_vload3(
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]]
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
255 define <1 x ptr addrspace(4)> @forward_memcpy_vload3(ptr addrspace(4) %loc) {
256 ; CHECK-LABEL: @forward_memcpy_vload3(
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)>
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)> poison, ptr addrspace(4) %val, i32 0
266 ret <1 x ptr addrspace(4)> %ret
269 ; Can forward since we can do so w/o breaking types
270 define ptr addrspace(4) @forward_memcpy_zero(ptr addrspace(4) %loc) {
271 ; CHECK-LABEL: @forward_memcpy_zero(
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
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
282 declare void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) nocapture, ptr nocapture, i64, i1) nounwind
285 ; Same as the neg_forward_store cases, but for non defs.
286 ; (Pretend we wrote out the alwaysfalse idiom above.)
287 define ptr addrspace(4) @neg_store_clobber(ptr addrspace(4) %loc) {
288 ; CHECK-LABEL: @neg_store_clobber(
290 ; CHECK-NEXT: store <2 x i64> <i64 4, 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]]
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
302 declare void @use(<2 x i64>) inaccessiblememonly
304 ; Same as the neg_forward_store cases, but for non defs.
305 ; (Pretend we wrote out the alwaysfalse idiom above.)
306 define ptr addrspace(4) @neg_load_clobber(ptr addrspace(4) %loc) {
307 ; CHECK-LABEL: @neg_load_clobber(
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]]
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
323 define ptr addrspace(4) @store_clobber_zero(ptr addrspace(4) %loc) {
324 ; CHECK-LABEL: @store_clobber_zero(
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
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
338 define void @smaller_vector(ptr %p) {
339 ; CHECK-LABEL: @smaller_vector(
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
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)
355 define ptr addrspace(4) @vector_extract(ptr %p) {
356 ; CHECK-LABEL: @vector_extract(
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]]
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
370 declare void @use.v2(<2 x ptr addrspace(4)>)
371 declare void @use.v4(<4 x ptr addrspace(4)>)
372 define ptr addrspace(5) @multini(i1 %alwaysFalse, ptr addrspace(4) %val, ptr %loc) {
373 ; CHECK-LABEL: @multini(
375 ; CHECK-NEXT: store ptr addrspace(4) [[VAL:%.*]], ptr [[LOC:%.*]], align 8
376 ; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
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
384 store ptr addrspace(4) %val, ptr %loc
385 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
388 %differentas = load ptr addrspace(5), ptr %loc
389 ret ptr addrspace(5) %differentas
392 ret ptr addrspace(5) null