1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -gvn -S < %s | FileCheck %s
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4"
5 target triple = "x86_64-unknown-linux-gnu"
7 define void @f0(i1 %alwaysFalse, i64 %val, i64* %loc) {
10 ; CHECK-NEXT: store i64 [[VAL:%.*]], i64* [[LOC:%.*]]
11 ; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
13 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i64* [[LOC]] to i8 addrspace(4)**
14 ; CHECK-NEXT: [[PTR:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)** [[LOC_BC]]
15 ; CHECK-NEXT: store i8 5, i8 addrspace(4)* [[PTR]]
16 ; CHECK-NEXT: ret void
18 ; CHECK-NEXT: ret void
21 store i64 %val, i64* %loc
22 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
25 %loc.bc = bitcast i64* %loc to i8 addrspace(4)**
26 %ptr = load i8 addrspace(4)*, i8 addrspace(4)** %loc.bc
27 store i8 5, i8 addrspace(4)* %ptr
34 define i64 @f1(i1 %alwaysFalse, i8 addrspace(4)* %val, i8 addrspace(4)** %loc) {
37 ; CHECK-NEXT: store i8 addrspace(4)* [[VAL:%.*]], i8 addrspace(4)** [[LOC:%.*]]
38 ; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
40 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)** [[LOC]] to i64*
41 ; CHECK-NEXT: [[INT:%.*]] = load i64, i64* [[LOC_BC]]
42 ; CHECK-NEXT: ret i64 [[INT]]
44 ; CHECK-NEXT: ret i64 42
47 store i8 addrspace(4)* %val, i8 addrspace(4)** %loc
48 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
51 %loc.bc = bitcast i8 addrspace(4)** %loc to i64*
52 %int = load i64, i64* %loc.bc
59 ;; Note: For terseness, we stop using the %alwaysfalse trick for the
60 ;; tests below and just exercise the bits of forwarding logic directly.
62 declare void @llvm.memset.p4i8.i64(i8 addrspace(4)* nocapture, i8, i64, i1) nounwind
64 ; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)
65 define i8 addrspace(4)* @neg_forward_memset(i8 addrspace(4)* addrspace(4)* %loc) {
66 ; CHECK-LABEL: @neg_forward_memset(
68 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
69 ; CHECK-NEXT: call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8 7, i64 8, i1 false)
70 ; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]]
71 ; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
74 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
75 call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8 7, i64 8, i1 false)
76 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
77 ret i8 addrspace(4)* %ref
80 define <1 x i8 addrspace(4)*> @neg_forward_memset_vload(<1 x i8 addrspace(4)*> addrspace(4)* %loc) {
81 ; CHECK-LABEL: @neg_forward_memset_vload(
83 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast <1 x i8 addrspace(4)*> addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
84 ; CHECK-NEXT: call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8 7, i64 8, i1 false)
85 ; CHECK-NEXT: [[REF:%.*]] = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* [[LOC]]
86 ; CHECK-NEXT: ret <1 x i8 addrspace(4)*> [[REF]]
89 %loc.bc = bitcast <1 x i8 addrspace(4)*> addrspace(4)* %loc to i8 addrspace(4)*
90 call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8 7, i64 8, i1 false)
91 %ref = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* %loc
92 ret <1 x i8 addrspace(4)*> %ref
96 ; Can forward since we can do so w/o breaking types
97 define i8 addrspace(4)* @forward_memset_zero(i8 addrspace(4)* addrspace(4)* %loc) {
98 ; CHECK-LABEL: @forward_memset_zero(
100 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
101 ; CHECK-NEXT: call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8 0, i64 8, i1 false)
102 ; CHECK-NEXT: ret i8 addrspace(4)* null
105 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
106 call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8 0, i64 8, i1 false)
107 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
108 ret i8 addrspace(4)* %ref
111 ; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)
112 define i8 addrspace(4)* @neg_forward_store(i8 addrspace(4)* addrspace(4)* %loc) {
113 ; CHECK-LABEL: @neg_forward_store(
115 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i64 addrspace(4)*
116 ; CHECK-NEXT: store i64 5, i64 addrspace(4)* [[LOC_BC]]
117 ; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]]
118 ; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
121 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i64 addrspace(4)*
122 store i64 5, i64 addrspace(4)* %loc.bc
123 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
124 ret i8 addrspace(4)* %ref
127 define <1 x i8 addrspace(4)*> @neg_forward_store_vload(<1 x i8 addrspace(4)*> addrspace(4)* %loc) {
128 ; CHECK-LABEL: @neg_forward_store_vload(
130 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast <1 x i8 addrspace(4)*> addrspace(4)* [[LOC:%.*]] to i64 addrspace(4)*
131 ; CHECK-NEXT: store i64 5, i64 addrspace(4)* [[LOC_BC]]
132 ; CHECK-NEXT: [[REF:%.*]] = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* [[LOC]]
133 ; CHECK-NEXT: ret <1 x i8 addrspace(4)*> [[REF]]
136 %loc.bc = bitcast <1 x i8 addrspace(4)*> addrspace(4)* %loc to i64 addrspace(4)*
137 store i64 5, i64 addrspace(4)* %loc.bc
138 %ref = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* %loc
139 ret <1 x i8 addrspace(4)*> %ref
142 ; Nulls have known bit patterns, so we can forward
143 define i8 addrspace(4)* @forward_store_zero(i8 addrspace(4)* addrspace(4)* %loc) {
144 ; CHECK-LABEL: @forward_store_zero(
146 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i64 addrspace(4)*
147 ; CHECK-NEXT: store i64 0, i64 addrspace(4)* [[LOC_BC]]
148 ; CHECK-NEXT: ret i8 addrspace(4)* null
151 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i64 addrspace(4)*
152 store i64 0, i64 addrspace(4)* %loc.bc
153 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
154 ret i8 addrspace(4)* %ref
157 ; Nulls have known bit patterns, so we can forward
158 define i8 addrspace(4)* @forward_store_zero2(i8 addrspace(4)* addrspace(4)* %loc) {
159 ; CHECK-LABEL: @forward_store_zero2(
161 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i32> addrspace(4)*
162 ; CHECK-NEXT: store <2 x i32> zeroinitializer, <2 x i32> addrspace(4)* [[LOC_BC]]
163 ; CHECK-NEXT: ret i8 addrspace(4)* null
166 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i32> addrspace(4)*
167 store <2 x i32> zeroinitializer, <2 x i32> addrspace(4)* %loc.bc
168 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
169 ret i8 addrspace(4)* %ref
172 @NonZeroConstant = constant <4 x i64> <i64 3, i64 3, i64 3, i64 3>
173 @ZeroConstant = constant <4 x i64> zeroinitializer
176 ; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)
177 define i8 addrspace(4)* @neg_forward_memcopy(i8 addrspace(4)* addrspace(4)* %loc) {
178 ; CHECK-LABEL: @neg_forward_memcopy(
180 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
181 ; CHECK-NEXT: call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8* bitcast (<4 x i64>* @NonZeroConstant to i8*), i64 8, i1 false)
182 ; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]]
183 ; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
186 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
187 %src.bc = bitcast <4 x i64>* @NonZeroConstant to i8*
188 call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8* %src.bc, i64 8, i1 false)
189 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
190 ret i8 addrspace(4)* %ref
193 define <1 x i8 addrspace(4)*> @neg_forward_memcpy_vload(<1 x i8 addrspace(4)*> addrspace(4)* %loc) {
194 ; CHECK-LABEL: @neg_forward_memcpy_vload(
196 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast <1 x i8 addrspace(4)*> addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
197 ; CHECK-NEXT: call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8* bitcast (<4 x i64>* @NonZeroConstant to i8*), i64 8, i1 false)
198 ; CHECK-NEXT: [[REF:%.*]] = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* [[LOC]]
199 ; CHECK-NEXT: ret <1 x i8 addrspace(4)*> [[REF]]
202 %loc.bc = bitcast <1 x i8 addrspace(4)*> addrspace(4)* %loc to i8 addrspace(4)*
203 %src.bc = bitcast <4 x i64>* @NonZeroConstant to i8*
204 call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8* %src.bc, i64 8, i1 false)
205 %ref = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* %loc
206 ret <1 x i8 addrspace(4)*> %ref
210 ; Can forward since we can do so w/o breaking types
211 ; TODO: missed optimization
212 define i8 addrspace(4)* @forward_memcpy_zero(i8 addrspace(4)* addrspace(4)* %loc) {
213 ; CHECK-LABEL: @forward_memcpy_zero(
215 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
216 ; CHECK-NEXT: call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8* bitcast (<4 x i64>* @ZeroConstant to i8*), i64 8, i1 false)
217 ; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]]
218 ; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
221 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
222 %src.bc = bitcast <4 x i64>* @ZeroConstant to i8*
223 call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8* %src.bc, i64 8, i1 false)
224 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
225 ret i8 addrspace(4)* %ref
228 declare void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* nocapture, i8* nocapture, i64, i1) nounwind
231 ; Same as the neg_forward_store cases, but for non defs.
232 ; (Pretend we wrote out the alwaysfalse idiom above.)
233 define i8 addrspace(4)* @neg_store_clobber(i8 addrspace(4)* addrspace(4)* %loc) {
234 ; CHECK-LABEL: @neg_store_clobber(
236 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i64> addrspace(4)*
237 ; CHECK-NEXT: store <2 x i64> <i64 4, i64 4>, <2 x i64> addrspace(4)* [[LOC_BC]]
238 ; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], i64 1
239 ; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC_OFF]]
240 ; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
243 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i64> addrspace(4)*
244 store <2 x i64> <i64 4, i64 4>, <2 x i64> addrspace(4)* %loc.bc
245 %loc.off = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc, i64 1
246 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc.off
247 ret i8 addrspace(4)* %ref
250 declare void @use(<2 x i64>) inaccessiblememonly
252 ; Same as the neg_forward_store cases, but for non defs.
253 ; (Pretend we wrote out the alwaysfalse idiom above.)
254 define i8 addrspace(4)* @neg_load_clobber(i8 addrspace(4)* addrspace(4)* %loc) {
255 ; CHECK-LABEL: @neg_load_clobber(
257 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i64> addrspace(4)*
258 ; CHECK-NEXT: [[V:%.*]] = load <2 x i64>, <2 x i64> addrspace(4)* [[LOC_BC]]
259 ; CHECK-NEXT: call void @use(<2 x i64> [[V]])
260 ; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], i64 1
261 ; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC_OFF]]
262 ; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
265 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i64> addrspace(4)*
266 %v = load <2 x i64>, <2 x i64> addrspace(4)* %loc.bc
267 call void @use(<2 x i64> %v)
268 %loc.off = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc, i64 1
269 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc.off
270 ret i8 addrspace(4)* %ref
273 define i8 addrspace(4)* @store_clobber_zero(i8 addrspace(4)* addrspace(4)* %loc) {
274 ; CHECK-LABEL: @store_clobber_zero(
276 ; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i64> addrspace(4)*
277 ; CHECK-NEXT: store <2 x i64> zeroinitializer, <2 x i64> addrspace(4)* [[LOC_BC]]
278 ; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], i64 1
279 ; CHECK-NEXT: ret i8 addrspace(4)* null
282 %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i64> addrspace(4)*
283 store <2 x i64> zeroinitializer, <2 x i64> addrspace(4)* %loc.bc
284 %loc.off = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc, i64 1
285 %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc.off
286 ret i8 addrspace(4)* %ref