1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S < %s -passes=gvn,dce | FileCheck %s
4 ; Analyze Load from clobbering Load.
6 define <vscale x 4 x i32> @load_store_clobber_load(ptr %p) {
7 ; CHECK-LABEL: @load_store_clobber_load(
8 ; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 16
9 ; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr undef, align 16
10 ; CHECK-NEXT: [[ADD:%.*]] = add <vscale x 4 x i32> [[LOAD1]], [[LOAD1]]
11 ; CHECK-NEXT: ret <vscale x 4 x i32> [[ADD]]
13 %load1 = load <vscale x 4 x i32>, ptr %p
14 store <vscale x 4 x i32> zeroinitializer, ptr undef
15 %load2 = load <vscale x 4 x i32>, ptr %p ; <- load to be eliminated
16 %add = add <vscale x 4 x i32> %load1, %load2
17 ret <vscale x 4 x i32> %add
20 define <vscale x 4 x i32> @load_store_clobber_load_mayalias(ptr %p, ptr %p2) {
21 ; CHECK-LABEL: @load_store_clobber_load_mayalias(
22 ; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 16
23 ; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P2:%.*]], align 16
24 ; CHECK-NEXT: [[LOAD2:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16
25 ; CHECK-NEXT: [[SUB:%.*]] = sub <vscale x 4 x i32> [[LOAD1]], [[LOAD2]]
26 ; CHECK-NEXT: ret <vscale x 4 x i32> [[SUB]]
28 %load1 = load <vscale x 4 x i32>, ptr %p
29 store <vscale x 4 x i32> zeroinitializer, ptr %p2
30 %load2 = load <vscale x 4 x i32>, ptr %p
31 %sub = sub <vscale x 4 x i32> %load1, %load2
32 ret <vscale x 4 x i32> %sub
35 define <vscale x 4 x i32> @load_store_clobber_load_noalias(ptr noalias %p, ptr noalias %p2) {
36 ; CHECK-LABEL: @load_store_clobber_load_noalias(
37 ; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 16
38 ; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P2:%.*]], align 16
39 ; CHECK-NEXT: [[ADD:%.*]] = add <vscale x 4 x i32> [[LOAD1]], [[LOAD1]]
40 ; CHECK-NEXT: ret <vscale x 4 x i32> [[ADD]]
42 %load1 = load <vscale x 4 x i32>, ptr %p
43 store <vscale x 4 x i32> zeroinitializer, ptr %p2
44 %load2 = load <vscale x 4 x i32>, ptr %p ; <- load to be eliminated
45 %add = add <vscale x 4 x i32> %load1, %load2
46 ret <vscale x 4 x i32> %add
49 ; BasicAA return MayAlias for %gep1,%gep2, could improve as MustAlias.
50 define i32 @load_clobber_load_gep1(ptr %p) {
51 ; CHECK-LABEL: @load_clobber_load_gep1(
52 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 0, i64 1
53 ; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[GEP1]], align 4
54 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD1]], [[LOAD1]]
55 ; CHECK-NEXT: ret i32 [[ADD]]
57 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 1
58 %load1 = load i32, ptr %gep1
59 %gep2 = getelementptr i32, ptr %p, i64 1
60 %load2 = load i32, ptr %gep2 ; <- load could be eliminated
61 %add = add i32 %load1, %load2
65 define i32 @load_clobber_load_gep2(ptr %p) {
66 ; CHECK-LABEL: @load_clobber_load_gep2(
67 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 1, i64 0
68 ; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[GEP1]], align 4
69 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, ptr [[P]], i64 4
70 ; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[GEP2]], align 4
71 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD1]], [[LOAD2]]
72 ; CHECK-NEXT: ret i32 [[ADD]]
74 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 0
75 %load1 = load i32, ptr %gep1
76 %gep2 = getelementptr i32, ptr %p, i64 4
77 %load2 = load i32, ptr %gep2 ; <- can not determine at compile-time if %load1 and %load2 are same addr
78 %add = add i32 %load1, %load2
82 ; TODO: BasicAA return MayAlias for %gep1,%gep2, could improve as MustAlias.
83 define i32 @load_clobber_load_gep3(ptr %p) {
84 ; CHECK-LABEL: @load_clobber_load_gep3(
85 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 1, i64 0
86 ; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[GEP1]], align 4
87 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P]], i64 1, i64 0
88 ; CHECK-NEXT: [[LOAD2:%.*]] = load float, ptr [[GEP2]], align 4
89 ; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[LOAD2]] to i32
90 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD1]], [[CAST]]
91 ; CHECK-NEXT: ret i32 [[ADD]]
93 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 0
94 %load1 = load i32, ptr %gep1
95 %gep2 = getelementptr <vscale x 4 x float>, ptr %p, i64 1, i64 0
96 %load2 = load float, ptr %gep2 ; <- load could be eliminated
97 %cast = bitcast float %load2 to i32
98 %add = add i32 %load1, %cast
102 define <vscale x 4 x i32> @load_clobber_load_fence(ptr %p) {
103 ; CHECK-LABEL: @load_clobber_load_fence(
104 ; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 16
105 ; CHECK-NEXT: call void asm "", "~{memory}"()
106 ; CHECK-NEXT: [[LOAD2:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16
107 ; CHECK-NEXT: [[SUB:%.*]] = sub <vscale x 4 x i32> [[LOAD1]], [[LOAD2]]
108 ; CHECK-NEXT: ret <vscale x 4 x i32> [[SUB]]
110 %load1 = load <vscale x 4 x i32>, ptr %p
111 call void asm "", "~{memory}"()
112 %load2 = load <vscale x 4 x i32>, ptr %p
113 %sub = sub <vscale x 4 x i32> %load1, %load2
114 ret <vscale x 4 x i32> %sub
117 define <vscale x 4 x i32> @load_clobber_load_sideeffect(ptr %p) {
118 ; CHECK-LABEL: @load_clobber_load_sideeffect(
119 ; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 16
120 ; CHECK-NEXT: call void asm sideeffect "", ""()
121 ; CHECK-NEXT: [[LOAD2:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16
122 ; CHECK-NEXT: [[ADD:%.*]] = add <vscale x 4 x i32> [[LOAD1]], [[LOAD2]]
123 ; CHECK-NEXT: ret <vscale x 4 x i32> [[ADD]]
125 %load1 = load <vscale x 4 x i32>, ptr %p
126 call void asm sideeffect "", ""()
127 %load2 = load <vscale x 4 x i32>, ptr %p
128 %add = add <vscale x 4 x i32> %load1, %load2
129 ret <vscale x 4 x i32> %add
132 ; Analyze Load from clobbering Store.
134 define <vscale x 4 x i32> @store_forward_to_load(ptr %p) {
135 ; CHECK-LABEL: @store_forward_to_load(
136 ; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P:%.*]], align 16
137 ; CHECK-NEXT: ret <vscale x 4 x i32> zeroinitializer
139 store <vscale x 4 x i32> zeroinitializer, ptr %p
140 %load = load <vscale x 4 x i32>, ptr %p
141 ret <vscale x 4 x i32> %load
144 define <vscale x 4 x i32> @store_forward_to_load_sideeffect(ptr %p) {
145 ; CHECK-LABEL: @store_forward_to_load_sideeffect(
146 ; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P:%.*]], align 16
147 ; CHECK-NEXT: call void asm sideeffect "", ""()
148 ; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16
149 ; CHECK-NEXT: ret <vscale x 4 x i32> [[LOAD]]
151 store <vscale x 4 x i32> zeroinitializer, ptr %p
152 call void asm sideeffect "", ""()
153 %load = load <vscale x 4 x i32>, ptr %p
154 ret <vscale x 4 x i32> %load
157 define i32 @store_clobber_load() {
158 ; CHECK-LABEL: @store_clobber_load(
159 ; CHECK-NEXT: [[ALLOC:%.*]] = alloca <vscale x 4 x i32>, align 16
160 ; CHECK-NEXT: store <vscale x 4 x i32> undef, ptr [[ALLOC]], align 16
161 ; CHECK-NEXT: [[PTR:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[ALLOC]], i32 0, i32 1
162 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[PTR]], align 4
163 ; CHECK-NEXT: ret i32 [[LOAD]]
165 %alloc = alloca <vscale x 4 x i32>
166 store <vscale x 4 x i32> undef, ptr %alloc
167 %ptr = getelementptr <vscale x 4 x i32>, ptr %alloc, i32 0, i32 1
168 %load = load i32, ptr %ptr
172 ; Analyze Load from clobbering MemInst.
174 declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1)
176 define i32 @memset_clobber_load(ptr %p) {
177 ; CHECK-LABEL: @memset_clobber_load(
178 ; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 1, i64 200, i1 false)
179 ; CHECK-NEXT: ret i32 16843009
181 tail call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 200, i1 false)
182 %gep = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 5
183 %load = load i32, ptr %gep
187 define i32 @memset_clobber_load_vscaled_base(ptr %p) {
188 ; CHECK-LABEL: @memset_clobber_load_vscaled_base(
189 ; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 1, i64 200, i1 false)
190 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 1, i64 1
191 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4
192 ; CHECK-NEXT: ret i32 [[LOAD]]
194 tail call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 200, i1 false)
195 %gep = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 1
196 %load = load i32, ptr %gep
200 define i32 @memset_clobber_load_nonconst_index(ptr %p, i64 %idx1, i64 %idx2) {
201 ; CHECK-LABEL: @memset_clobber_load_nonconst_index(
202 ; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 1, i64 200, i1 false)
203 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 [[IDX1:%.*]], i64 [[IDX2:%.*]]
204 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4
205 ; CHECK-NEXT: ret i32 [[LOAD]]
207 tail call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 200, i1 false)
208 %gep = getelementptr <vscale x 4 x i32>, ptr %p, i64 %idx1, i64 %idx2
209 %load = load i32, ptr %gep
214 ; Load elimination across BBs
216 define ptr @load_from_alloc_replaced_with_undef() {
217 ; CHECK-LABEL: @load_from_alloc_replaced_with_undef(
219 ; CHECK-NEXT: [[A:%.*]] = alloca <vscale x 4 x i32>, align 16
220 ; CHECK-NEXT: br i1 undef, label [[IF_END:%.*]], label [[IF_THEN:%.*]]
222 ; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[A]], align 16
223 ; CHECK-NEXT: br label [[IF_END]]
225 ; CHECK-NEXT: ret ptr [[A]]
228 %a = alloca <vscale x 4 x i32>
229 %gep = getelementptr <vscale x 4 x i32>, ptr %a, i64 0, i64 1
230 %load = load i32, ptr %gep ; <- load to be eliminated
231 %tobool = icmp eq i32 %load, 0 ; <- icmp to be eliminated
232 br i1 %tobool, label %if.end, label %if.then
235 store <vscale x 4 x i32> zeroinitializer, ptr %a
242 define i32 @redundant_load_elimination_1(ptr %p) {
243 ; CHECK-LABEL: @redundant_load_elimination_1(
245 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 1, i64 1
246 ; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[GEP]], align 4
247 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[LOAD1]], 0
248 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
250 ; CHECK-NEXT: br label [[IF_END]]
252 ; CHECK-NEXT: ret i32 [[LOAD1]]
255 %gep = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 1
256 %load1 = load i32, ptr %gep
257 %cmp = icmp eq i32 %load1, 0
258 br i1 %cmp, label %if.then, label %if.end
261 %load2 = load i32, ptr %gep ; <- load to be eliminated
262 %add = add i32 %load1, %load2
266 %result = phi i32 [ %add, %if.then ], [ %load1, %entry ]
270 ; TODO: BasicAA return MayAlias for %gep1,%gep2, could improve as NoAlias.
271 define void @redundant_load_elimination_2(i1 %c, ptr %p, ptr %q) {
272 ; CHECK-LABEL: @redundant_load_elimination_2(
274 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 1, i64 1
275 ; CHECK-NEXT: store i32 0, ptr [[GEP1]], align 4
276 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 1, i64 0
277 ; CHECK-NEXT: store i32 1, ptr [[GEP2]], align 4
278 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
280 ; CHECK-NEXT: [[T:%.*]] = load i32, ptr [[GEP1]], align 4
281 ; CHECK-NEXT: store i32 [[T]], ptr [[Q:%.*]], align 4
282 ; CHECK-NEXT: ret void
284 ; CHECK-NEXT: ret void
287 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 1
288 store i32 0, ptr %gep1
289 %gep2 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 0
290 store i32 1, ptr %gep2
291 br i1 %c, label %if.else, label %if.then
294 %t = load i32, ptr %gep1 ; <- load could be eliminated
302 define void @redundant_load_elimination_zero_index(i1 %c, ptr %p, ptr %q) {
303 ; CHECK-LABEL: @redundant_load_elimination_zero_index(
305 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 0, i64 1
306 ; CHECK-NEXT: store i32 0, ptr [[GEP1]], align 4
307 ; CHECK-NEXT: store i32 1, ptr [[P]], align 4
308 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
310 ; CHECK-NEXT: store i32 0, ptr [[Q:%.*]], align 4
311 ; CHECK-NEXT: ret void
313 ; CHECK-NEXT: ret void
316 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 1
317 store i32 0, ptr %gep1
319 br i1 %c, label %if.else, label %if.then
322 %t = load i32, ptr %gep1 ; <- load could be eliminated
330 define void @redundant_load_elimination_zero_index_1(i1 %c, ptr %p, ptr %q, i64 %i) {
331 ; CHECK-LABEL: @redundant_load_elimination_zero_index_1(
333 ; CHECK-NEXT: [[J:%.*]] = add i64 [[I:%.*]], 1
334 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 0, i64 [[J]]
335 ; CHECK-NEXT: store i32 0, ptr [[GEP1]], align 4
336 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 0, i64 [[I]]
337 ; CHECK-NEXT: store i32 1, ptr [[GEP2]], align 4
338 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
340 ; CHECK-NEXT: store i32 0, ptr [[Q:%.*]], align 4
341 ; CHECK-NEXT: ret void
343 ; CHECK-NEXT: ret void
347 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 %j
348 store i32 0, ptr %gep1
349 %gep2 = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 %i
350 store i32 1, ptr %gep2
351 br i1 %c, label %if.else, label %if.then
354 %t = load i32, ptr %gep1 ; <- load could be eliminated
361 ; TODO: load in if.then could have been eliminated
362 define void @missing_load_elimination(i1 %c, ptr %p, ptr %q, <vscale x 4 x i32> %v) {
363 ; CHECK-LABEL: @missing_load_elimination(
365 ; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P:%.*]], align 16
366 ; CHECK-NEXT: [[P1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 1
367 ; CHECK-NEXT: store <vscale x 4 x i32> [[V:%.*]], ptr [[P1]], align 16
368 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
370 ; CHECK-NEXT: [[T:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16
371 ; CHECK-NEXT: store <vscale x 4 x i32> [[T]], ptr [[Q:%.*]], align 16
372 ; CHECK-NEXT: ret void
374 ; CHECK-NEXT: ret void
377 store <vscale x 4 x i32> zeroinitializer, ptr %p
378 %p1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1
379 store <vscale x 4 x i32> %v, ptr %p1
380 br i1 %c, label %if.else, label %if.then
383 %t = load <vscale x 4 x i32>, ptr %p ; load could be eliminated
384 store <vscale x 4 x i32> %t, ptr %q