Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / GVN / vscale.ll
blob71adaed8e5722bdba281f7c95c2e15a68f5ceca2
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
62   ret i32 %add
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
79   ret i32 %add
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
99   ret i32 %add
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
169   ret i32 %load
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
184   ret i32 %load
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
197   ret i32 %load
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
210   ret i32 %load
214 ; Load elimination across BBs
216 define ptr @load_from_alloc_replaced_with_undef() {
217 ; CHECK-LABEL: @load_from_alloc_replaced_with_undef(
218 ; CHECK-NEXT:  entry:
219 ; CHECK-NEXT:    [[A:%.*]] = alloca <vscale x 4 x i32>, align 16
220 ; CHECK-NEXT:    br i1 undef, label [[IF_END:%.*]], label [[IF_THEN:%.*]]
221 ; CHECK:       if.then:
222 ; CHECK-NEXT:    store <vscale x 4 x i32> zeroinitializer, ptr [[A]], align 16
223 ; CHECK-NEXT:    br label [[IF_END]]
224 ; CHECK:       if.end:
225 ; CHECK-NEXT:    ret ptr [[A]]
227 entry:
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
234 if.then:
235   store <vscale x 4 x i32> zeroinitializer, ptr %a
236   br label %if.end
238 if.end:
239   ret ptr %a
242 define i32 @redundant_load_elimination_1(ptr %p) {
243 ; CHECK-LABEL: @redundant_load_elimination_1(
244 ; CHECK-NEXT:  entry:
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:%.*]]
249 ; CHECK:       if.then:
250 ; CHECK-NEXT:    br label [[IF_END]]
251 ; CHECK:       if.end:
252 ; CHECK-NEXT:    ret i32 [[LOAD1]]
254 entry:
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
260 if.then:
261   %load2 = load i32, ptr %gep ; <- load to be eliminated
262   %add = add i32 %load1, %load2
263   br label %if.end
265 if.end:
266   %result = phi i32 [ %add, %if.then ], [ %load1, %entry ]
267   ret i32 %result
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(
273 ; CHECK-NEXT:  entry:
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:%.*]]
279 ; CHECK:       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
283 ; CHECK:       if.else:
284 ; CHECK-NEXT:    ret void
286 entry:
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
293 if.then:
294   %t = load i32, ptr %gep1 ; <- load could be eliminated
295   store i32 %t, ptr %q
296   ret void
298 if.else:
299   ret void
302 define void @redundant_load_elimination_zero_index(i1 %c, ptr %p, ptr %q) {
303 ; CHECK-LABEL: @redundant_load_elimination_zero_index(
304 ; CHECK-NEXT:  entry:
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:%.*]]
309 ; CHECK:       if.then:
310 ; CHECK-NEXT:    store i32 0, ptr [[Q:%.*]], align 4
311 ; CHECK-NEXT:    ret void
312 ; CHECK:       if.else:
313 ; CHECK-NEXT:    ret void
315 entry:
316   %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 1
317   store i32 0, ptr %gep1
318   store i32 1, ptr %p
319   br i1 %c, label %if.else, label %if.then
321 if.then:
322   %t = load i32, ptr %gep1 ; <- load could be eliminated
323   store i32 %t, ptr %q
324   ret void
326 if.else:
327   ret void
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(
332 ; CHECK-NEXT:  entry:
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:%.*]]
339 ; CHECK:       if.then:
340 ; CHECK-NEXT:    store i32 0, ptr [[Q:%.*]], align 4
341 ; CHECK-NEXT:    ret void
342 ; CHECK:       if.else:
343 ; CHECK-NEXT:    ret void
345 entry:
346   %j = add i64 %i, 1
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
353 if.then:
354   %t = load i32, ptr %gep1 ; <- load could be eliminated
355   store i32 %t, ptr %q
356   ret void
358 if.else:
359   ret void
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(
364 ; CHECK-NEXT:  entry:
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:%.*]]
369 ; CHECK:       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
373 ; CHECK:       if.else:
374 ; CHECK-NEXT:    ret void
376 entry:
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
382 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
385   ret void
387 if.else:
388   ret void