[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / LICM / store-hoisting.ll
blob0544af3cd0236942b1294b3ecc7009d408de8c74
1 ; RUN: opt -S -basic-aa -licm %s -enable-new-pm=0 | FileCheck %s
2 ; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
4 define void @test(i32* %loc) {
5 ; CHECK-LABEL: @test
6 ; CHECK-LABEL: entry:
7 ; CHECK: store i32 0, i32* %loc
8 ; CHECK-LABEL: loop:
9 entry:
10   br label %loop
12 loop:
13   %iv = phi i32 [0, %entry], [%iv.next, %loop]
14   store i32 0, i32* %loc
15   %iv.next = add i32 %iv, 1
16   %cmp = icmp slt i32 %iv, 200
17   br i1 %cmp, label %loop, label %exit
19 exit:
20   ret void
23 define void @test_multiexit(i32* %loc, i1 %earlycnd) {
24 ; CHECK-LABEL: @test_multiexit
25 ; CHECK-LABEL: entry:
26 ; CHECK: store i32 0, i32* %loc
27 ; CHECK-LABEL: loop:
28 entry:
29   br label %loop
31 loop:
32   %iv = phi i32 [0, %entry], [%iv.next, %backedge]
33   store i32 0, i32* %loc
34   %iv.next = add i32 %iv, 1
35   br i1 %earlycnd, label %exit1, label %backedge
36   
37 backedge:
38   %cmp = icmp slt i32 %iv, 200
39   br i1 %cmp, label %loop, label %exit2
41 exit1:
42   ret void
43 exit2:
44   ret void
47 define i32* @false_negative_2use(i32* %loc) {
48 ; CHECK-LABEL: @false_negative_2use
49 ; CHECK-LABEL: entry:
50 ; CHECK: store i32 0, i32* %loc
51 ; CHECK-LABEL: loop:
52 entry:
53   br label %loop
55 loop:
56   %iv = phi i32 [0, %entry], [%iv.next, %loop]
57   store i32 0, i32* %loc
58   %iv.next = add i32 %iv, 1
59   %cmp = icmp slt i32 %iv, 200
60   br i1 %cmp, label %loop, label %exit
62 exit:
63   ret i32* %loc
66 define void @neg_lv_value(i32* %loc) {
67 ; CHECK-LABEL: @neg_lv_value
68 ; CHECK-LABEL: exit:
69 ; CHECK: store i32 %iv.lcssa, i32* %loc
70 entry:
71   br label %loop
73 loop:
74   %iv = phi i32 [0, %entry], [%iv.next, %loop]
75   store i32 %iv, i32* %loc
76   %iv.next = add i32 %iv, 1
77   %cmp = icmp slt i32 %iv, 200
78   br i1 %cmp, label %loop, label %exit
80 exit:
81   ret void
84 define void @neg_lv_addr(i32* %loc) {
85 ; CHECK-LABEL: @neg_lv_addr
86 ; CHECK-LABEL: loop:
87 ; CHECK: store i32 0, i32* %p
88 ; CHECK-LABEL: exit:
89 entry:
90   br label %loop
92 loop:
93   %iv = phi i32 [0, %entry], [%iv.next, %loop]
94   %p = getelementptr i32, i32* %loc, i32 %iv
95   store i32 0, i32* %p
96   %iv.next = add i32 %iv, 1
97   %cmp = icmp slt i32 %iv, 200
98   br i1 %cmp, label %loop, label %exit
100 exit:
101   ret void
104 define void @neg_mod(i32* %loc) {
105 ; CHECK-LABEL: @neg_mod
106 ; CHECK-LABEL: exit:
107 ; CHECK: store i32 %iv.lcssa, i32* %loc
108 entry:
109   br label %loop
111 loop:
112   %iv = phi i32 [0, %entry], [%iv.next, %loop]
113   store i32 0, i32* %loc
114   store i32 %iv, i32* %loc
115   %iv.next = add i32 %iv, 1
116   %cmp = icmp slt i32 %iv, 200
117   br i1 %cmp, label %loop, label %exit
119 exit:
120   ret void
123 ; Hoisting the store is actually valid here, as it dominates the load.
124 define void @neg_ref(i32* %loc) {
125 ; CHECK-LABEL: @neg_ref
126 ; CHECK-LABEL: exit1:
127 ; CHECK: store i32 0, i32* %loc
128 ; CHECK-LABEL: exit2:
129 ; CHECK: store i32 0, i32* %loc
130 entry:
131   br label %loop
133 loop:
134   %iv = phi i32 [0, %entry], [%iv.next, %backedge]
135   store i32 0, i32* %loc
136   %v = load i32, i32* %loc
137   %earlycnd = icmp eq i32 %v, 198
138   br i1 %earlycnd, label %exit1, label %backedge
139   
140 backedge:
141   %iv.next = add i32 %iv, 1
142   %cmp = icmp slt i32 %iv, 200
143   br i1 %cmp, label %loop, label %exit2
145 exit1:
146   ret void
147 exit2:
148   ret void
151 ; Hoisting the store here leads to a miscompile.
152 define void @neg_ref2(i32* %loc) {
153 ; CHECK-LABEL: @neg_ref2
154 ; CHECK-LABEL: exit1:
155 ; CHECK: store i32 0, i32* %loc
156 ; CHECK-LABEL: exit2:
157 ; CHECK: store i32 0, i32* %loc
158 entry:
159   store i32 198, i32* %loc
160   br label %loop
162 loop:
163   %iv = phi i32 [0, %entry], [%iv.next, %backedge]
164   %v = load i32, i32* %loc
165   store i32 0, i32* %loc
166   %earlycnd = icmp eq i32 %v, 198
167   br i1 %earlycnd, label %exit1, label %backedge
168   
169 backedge:
170   %iv.next = add i32 %iv, 1
171   %cmp = icmp slt i32 %iv, 200
172   br i1 %cmp, label %loop, label %exit2
174 exit1:
175   ret void
176 exit2:
177   ret void
180 declare void @modref()
182 define void @neg_modref(i32* %loc) {
183 ; CHECK-LABEL: @neg_modref
184 ; CHECK-LABEL: loop:
185 ; CHECK: store i32 0, i32* %loc
186 ; CHECK-LABEL: exit:
187 entry:
188   br label %loop
190 loop:
191   %iv = phi i32 [0, %entry], [%iv.next, %loop]
192   store i32 0, i32* %loc
193   call void @modref()
194   %iv.next = add i32 %iv, 1
195   %cmp = icmp slt i32 %iv, 200
196   br i1 %cmp, label %loop, label %exit
198 exit:
199   ret void
202 define void @neg_fence(i32* %loc) {
203 ; CHECK-LABEL: @neg_fence
204 ; CHECK-LABEL: loop:
205 ; CHECK: store i32 0, i32* %loc
206 ; CHECK-LABEL: exit:
207 entry:
208   br label %loop
210 loop:
211   %iv = phi i32 [0, %entry], [%iv.next, %loop]
212   store i32 0, i32* %loc
213   fence seq_cst
214   %iv.next = add i32 %iv, 1
215   %cmp = icmp slt i32 %iv, 200
216   br i1 %cmp, label %loop, label %exit
218 exit:
219   ret void
222 define void @neg_volatile(i32* %loc) {
223 ; CHECK-LABEL: @neg_volatile
224 ; CHECK-LABEL: loop:
225 ; CHECK: store volatile i32 0, i32* %loc
226 ; CHECK-LABEL: exit:
227 entry:
228   br label %loop
230 loop:
231   %iv = phi i32 [0, %entry], [%iv.next, %loop]
232   store volatile i32 0, i32* %loc
233   %iv.next = add i32 %iv, 1
234   %cmp = icmp slt i32 %iv, 200
235   br i1 %cmp, label %loop, label %exit
237 exit:
238   ret void
241 define void @neg_release(i32* %loc) {
242 ; CHECK-LABEL: @neg_release
243 ; CHECK-LABEL: loop:
244 ; CHECK: store atomic i32 0, i32* %loc release, align 4
245 ; CHECK-LABEL: exit:
246 entry:
247   br label %loop
249 loop:
250   %iv = phi i32 [0, %entry], [%iv.next, %loop]
251   store atomic i32 0, i32* %loc release, align 4
252   %iv.next = add i32 %iv, 1
253   %cmp = icmp slt i32 %iv, 200
254   br i1 %cmp, label %loop, label %exit
256 exit:
257   ret void
260 define void @neg_seq_cst(i32* %loc) {
261 ; CHECK-LABEL: @neg_seq_cst
262 ; CHECK-LABEL: loop:
263 ; CHECK: store atomic i32 0, i32* %loc seq_cst, align 4
264 ; CHECK-LABEL: exit:
265 entry:
266   br label %loop
268 loop:
269   %iv = phi i32 [0, %entry], [%iv.next, %loop]
270   store atomic i32 0, i32* %loc seq_cst, align 4
271   %iv.next = add i32 %iv, 1
272   %cmp = icmp slt i32 %iv, 200
273   br i1 %cmp, label %loop, label %exit
275 exit:
276   ret void
279 declare void @maythrow() inaccessiblememonly
281 define void @neg_early_exit(i32* %loc) {
282 ; CHECK-LABEL: @neg_early_exit
283 ; CHECK-LABEL: body:
284 ; CHECK: store i32 0, i32* %loc
285 ; CHECK-LABEL: exit:
286 entry:
287   br label %loop
289 loop:
290   %iv = phi i32 [0, %entry], [%iv.next, %body]
291   %is_null = icmp eq i32* %loc, null
292   br i1 %is_null, label %exit, label %body
293 body:
294   call void @maythrow()
295   store i32 0, i32* %loc
296   %iv.next = add i32 %iv, 1
297   %cmp = icmp slt i32 %iv, 200
298   br i1 %cmp, label %loop, label %exit
300 exit:
301   ret void
304 define void @neg_early_throw(i32* %loc) {
305 ; CHECK-LABEL: @neg_early_throw
306 ; CHECK-LABEL: loop:
307 ; CHECK: store i32 0, i32* %loc
308 ; CHECK-LABEL: exit:
309 entry:
310   br label %loop
312 loop:
313   %iv = phi i32 [0, %entry], [%iv.next, %loop]
314   call void @maythrow()
315   store i32 0, i32* %loc
316   %iv.next = add i32 %iv, 1
317   %cmp = icmp slt i32 %iv, 200
318   br i1 %cmp, label %loop, label %exit
320 exit:
321   ret void
324 define void @test_late_throw(i32* %loc) {
325 ; CHECK-LABEL: @test_late_throw
326 ; CHECK-LABEL: entry:
327 ; CHECK: store i32 0, i32* %loc
328 ; CHECK-LABEL: loop:
329 entry:
330   br label %loop
332 loop:
333   %iv = phi i32 [0, %entry], [%iv.next, %loop]
334   store i32 0, i32* %loc
335   call void @maythrow()
336   %iv.next = add i32 %iv, 1
337   %cmp = icmp slt i32 %iv, 200
338   br i1 %cmp, label %loop, label %exit
340 exit:
341   ret void
344 ; TODO: could validly hoist the store here since we know what value
345 ; the load must observe.
346 define i32 @test_dominated_read(i32* %loc) {
347 ; CHECK-LABEL: @test_dominated_read
348 ; CHECK-LABEL: entry:
349 ; CHECK: store i32 0, i32* %loc
350 ; CHECK-LABEL: loop:
351 entry:
352   br label %loop
354 loop:
355   %iv = phi i32 [0, %entry], [%iv.next, %loop]
356   store i32 0, i32* %loc
357   %reload = load i32, i32* %loc
358   %iv.next = add i32 %iv, 1
359   %cmp = icmp slt i32 %iv, 200
360   br i1 %cmp, label %loop, label %exit
362 exit:
363   ret i32 %reload
366 ; TODO: could validly hoist the store since we already hoisted the load and
367 ; it's no longer in the loop.
368 define i32 @test_dominating_read(i32* %loc) {
369 ; CHECK-LABEL: @test_dominating_read
370 ; CHECK-LABEL: exit:
371 ; CHECK: store i32 0, i32* %loc
372 entry:
373   br label %loop
375 loop:
376   %iv = phi i32 [0, %entry], [%iv.next, %loop]
377   %reload = load i32, i32* %loc
378   store i32 0, i32* %loc
379   %iv.next = add i32 %iv, 1
380   %cmp = icmp slt i32 %iv, 200
381   br i1 %cmp, label %loop, label %exit
383 exit:
384   ret i32 %reload
387 declare void @readonly() readonly
389 ; TODO: can legally hoist since value read by call is known
390 define void @test_dominated_readonly(i32* %loc) {
391 ; CHECK-LABEL: @test_dominated_readonly
392 ; CHECK-LABEL: loop:
393 ; CHECK: store i32 0, i32* %loc
394 ; CHECK-LABEL: exit:
395 entry:
396   br label %loop
398 loop:
399   %iv = phi i32 [0, %entry], [%iv.next, %loop]
400   store i32 0, i32* %loc
401   call void @readonly()
402   %iv.next = add i32 %iv, 1
403   %cmp = icmp slt i32 %iv, 200
404   br i1 %cmp, label %loop, label %exit
406 exit:
407   ret void
410 ; While technically possible to hoist the store to %loc, this runs across
411 ; a funemental limitation of alias sets since both stores and the call are
412 ; within the same alias set and we can't distinguish them cheaply.
413 define void @test_aliasset_fn(i32* %loc, i32* %loc2) {
414 ; CHECK-LABEL: @test_aliasset_fn
415 ; CHECK-LABEL: loop:
416 ; CHECK: store i32 0, i32* %loc
417 ; CHECK-LABEL: exit:
418 entry:
419   br label %loop
421 loop:
422   %iv = phi i32 [0, %entry], [%iv.next, %loop]
423   store i32 0, i32* %loc
424   call void @readonly()
425   store i32 %iv, i32* %loc2
426   %iv.next = add i32 %iv, 1
427   %cmp = icmp slt i32 %iv, 200
428   br i1 %cmp, label %loop, label %exit
430 exit:
431   ret void
435 ; If we can't tell if the value is read before the write, we can't hoist the
436 ; write over the potential read (since we don't know the value read)
437 define void @neg_may_read(i32* %loc, i1 %maybe) {
438 ; CHECK-LABEL: @neg_may_read
439 ; CHECK-LABEL: loop:
440 ; CHECK: store i32 0, i32* %loc
441 ; CHECK-LABEL: exit:
442 entry:
443   br label %loop
445 loop:
446   %iv = phi i32 [0, %entry], [%iv.next, %merge]
447   ;; maybe is a placeholder for an unanalyzable condition
448   br i1 %maybe, label %taken, label %merge
449 taken:
450   call void @readonly()
451   br label %merge
452 merge:
453   store i32 0, i32* %loc
454   %iv.next = add i32 %iv, 1
455   %cmp = icmp slt i32 %iv, 200
456   br i1 %cmp, label %loop, label %exit
458 exit:
459   ret void