[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / Sink / call.ll
blob1e80aeee21da7e7e29c3bc54ec384990bad365f0
1 ; RUN: opt < %s -basic-aa -sink -S | FileCheck %s
3 declare i32 @f_load_global() nounwind readonly
4 declare i32 @f_load_global_throwable() readonly
5 declare i32 @f_load_arg(i32*) nounwind readonly argmemonly
6 declare void @f_store_global(i32) nounwind
7 declare void @f_store_arg(i32*) nounwind argmemonly
8 declare void @f_readonly_arg(i32* readonly, i32*) nounwind argmemonly
9 declare i32 @f_readnone(i32) nounwind readnone
11 @A = external global i32
12 @B = external global i32
14 ; Sink readonly call if no stores are in the way.
16 ; CHECK-LABEL: @test_sink_no_stores(
17 ; CHECK: true:
18 ; CHECK-NEXT: %l = call i32 @f_load_global
19 ; CHECK-NEXT: ret i32 %l
20 define i32 @test_sink_no_stores(i1 %z) {
21   %l = call i32 @f_load_global()
22   br i1 %z, label %true, label %false
23 true:
24   ret i32 %l
25 false:
26   ret i32 0
29 ; CHECK-LABEL: @test_throwable_no_stores(
30 ; CHECK:         %l = call i32 @f_load_global
31 ; CHECK-NEXT:    br i1 %z
32 define i32 @test_throwable_no_stores(i1 %z) {
33   %l = call i32 @f_load_global_throwable()
34   br i1 %z, label %true, label %false
35 true:
36   ret i32 %l
37 false:
38   ret i32 0
41 ; CHECK-LABEL: @test_sink_argmem_store(
42 ; CHECK: true:
43 ; CHECK-NEXT: %l = call i32 @f_load_arg
44 ; CHECK-NEXT: ret i32 %l
45 define i32 @test_sink_argmem_store(i1 %z) {
46   %l = call i32 @f_load_arg(i32* @A)
47   store i32 0, i32* @B
48   br i1 %z, label %true, label %false
49 true:
50   ret i32 %l
51 false:
52   ret i32 0
55 ; CHECK-LABEL: @test_sink_argmem_call(
56 ; CHECK: true:
57 ; CHECK-NEXT: %l = call i32 @f_load_arg
58 ; CHECK-NEXT: ret i32 %l
59 define i32 @test_sink_argmem_call(i1 %z) {
60   %l = call i32 @f_load_arg(i32* @A)
61   call void @f_store_arg(i32* @B)
62   br i1 %z, label %true, label %false
63 true:
64   ret i32 %l
65 false:
66   ret i32 0
69 ; CHECK-LABEL: @test_sink_argmem_multiple(
70 ; CHECK: true:
71 ; CHECK-NEXT: %l = call i32 @f_load_arg
72 ; CHECK-NEXT: ret i32 %l
73 define i32 @test_sink_argmem_multiple(i1 %z) {
74   %l = call i32 @f_load_arg(i32* @A)
75   call void @f_readonly_arg(i32* @A, i32* @B)
76   br i1 %z, label %true, label %false
77 true:
78   ret i32 %l
79 false:
80   ret i32 0
83 ; But don't sink if there is a store.
85 ; CHECK-LABEL: @test_nosink_store(
86 ; CHECK: call i32 @f_load_global
87 ; CHECK-NEXT: store i32
88 define i32 @test_nosink_store(i1 %z) {
89   %l = call i32 @f_load_global()
90   store i32 0, i32* @A
91   br i1 %z, label %true, label %false
92 true:
93   ret i32 %l
94 false:
95   ret i32 0
98 ; CHECK-LABEL: @test_nosink_call(
99 ; CHECK: call i32 @f_load_global
100 ; CHECK-NEXT: call void @f_store_global
101 define i32 @test_nosink_call(i1 %z) {
102   %l = call i32 @f_load_global()
103   call void @f_store_global(i32 0)
104   br i1 %z, label %true, label %false
105 true:
106   ret i32 %l
107 false:
108   ret i32 0
111 ; readnone calls are sunk across stores.
113 ; CHECK-LABEL: @test_sink_readnone(
114 ; CHECK: true:
115 ; CHECK-NEXT: %l = call i32 @f_readnone(
116 ; CHECK-NEXT: ret i32 %l
117 define i32 @test_sink_readnone(i1 %z) {
118   %l = call i32 @f_readnone(i32 0)
119   store i32 0, i32* @A
120   br i1 %z, label %true, label %false
121 true:
122   ret i32 %l
123 false:
124   ret i32 0