Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / Sink / call.ll
blobffa892cc71e2bf6b132eb88de89e68b5f0882f8f
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=sink -S | FileCheck %s
4 declare i32 @f_load_global() nounwind willreturn readonly
5 declare i32 @f_load_global_throwable() willreturn readonly
6 declare i32 @f_load_global_may_not_return() nounwind readonly
7 declare i32 @f_load_arg(ptr) nounwind willreturn readonly argmemonly
8 declare void @f_store_global(i32) nounwind willreturn
9 declare void @f_store_arg(ptr) nounwind willreturn argmemonly
10 declare void @f_readonly_arg(ptr readonly, ptr) nounwind willreturn argmemonly
11 declare i32 @f_readnone(i32) nounwind willreturn readnone
13 @A = external global i32
14 @B = external global i32
16 ; Sink readonly call if no stores are in the way.
18 define i32 @test_sink_no_stores(i1 %z) {
19 ; CHECK-LABEL: @test_sink_no_stores(
20 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
21 ; CHECK:       true:
22 ; CHECK-NEXT:    [[L:%.*]] = call i32 @f_load_global()
23 ; CHECK-NEXT:    ret i32 [[L]]
24 ; CHECK:       false:
25 ; CHECK-NEXT:    ret i32 0
27   %l = call i32 @f_load_global()
28   br i1 %z, label %true, label %false
29 true:
30   ret i32 %l
31 false:
32   ret i32 0
35 define i32 @test_throwable_no_stores(i1 %z) {
36 ; CHECK-LABEL: @test_throwable_no_stores(
37 ; CHECK-NEXT:    [[L:%.*]] = call i32 @f_load_global_throwable()
38 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
39 ; CHECK:       true:
40 ; CHECK-NEXT:    ret i32 [[L]]
41 ; CHECK:       false:
42 ; CHECK-NEXT:    ret i32 0
44   %l = call i32 @f_load_global_throwable()
45   br i1 %z, label %true, label %false
46 true:
47   ret i32 %l
48 false:
49   ret i32 0
52 define i32 @test_may_not_return_no_stores(i1 %z) {
53 ; CHECK-LABEL: @test_may_not_return_no_stores(
54 ; CHECK-NEXT:    [[L:%.*]] = call i32 @f_load_global_may_not_return()
55 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
56 ; CHECK:       true:
57 ; CHECK-NEXT:    ret i32 [[L]]
58 ; CHECK:       false:
59 ; CHECK-NEXT:    ret i32 0
61   %l = call i32 @f_load_global_may_not_return()
62   br i1 %z, label %true, label %false
63 true:
64   ret i32 %l
65 false:
66   ret i32 0
69 define i32 @test_sink_argmem_store(i1 %z) {
70 ; CHECK-LABEL: @test_sink_argmem_store(
71 ; CHECK-NEXT:    store i32 0, ptr @B, align 4
72 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
73 ; CHECK:       true:
74 ; CHECK-NEXT:    [[L:%.*]] = call i32 @f_load_arg(ptr @A)
75 ; CHECK-NEXT:    ret i32 [[L]]
76 ; CHECK:       false:
77 ; CHECK-NEXT:    ret i32 0
79   %l = call i32 @f_load_arg(ptr @A)
80   store i32 0, ptr @B
81   br i1 %z, label %true, label %false
82 true:
83   ret i32 %l
84 false:
85   ret i32 0
88 define i32 @test_sink_argmem_call(i1 %z) {
89 ; CHECK-LABEL: @test_sink_argmem_call(
90 ; CHECK-NEXT:    call void @f_store_arg(ptr @B)
91 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
92 ; CHECK:       true:
93 ; CHECK-NEXT:    [[L:%.*]] = call i32 @f_load_arg(ptr @A)
94 ; CHECK-NEXT:    ret i32 [[L]]
95 ; CHECK:       false:
96 ; CHECK-NEXT:    ret i32 0
98   %l = call i32 @f_load_arg(ptr @A)
99   call void @f_store_arg(ptr @B)
100   br i1 %z, label %true, label %false
101 true:
102   ret i32 %l
103 false:
104   ret i32 0
107 define i32 @test_sink_argmem_multiple(i1 %z) {
108 ; CHECK-LABEL: @test_sink_argmem_multiple(
109 ; CHECK-NEXT:    call void @f_readonly_arg(ptr @A, ptr @B)
110 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
111 ; CHECK:       true:
112 ; CHECK-NEXT:    [[L:%.*]] = call i32 @f_load_arg(ptr @A)
113 ; CHECK-NEXT:    ret i32 [[L]]
114 ; CHECK:       false:
115 ; CHECK-NEXT:    ret i32 0
117   %l = call i32 @f_load_arg(ptr @A)
118   call void @f_readonly_arg(ptr @A, ptr @B)
119   br i1 %z, label %true, label %false
120 true:
121   ret i32 %l
122 false:
123   ret i32 0
126 ; But don't sink if there is a store.
127 define i32 @test_nosink_store(i1 %z) {
128 ; CHECK-LABEL: @test_nosink_store(
129 ; CHECK-NEXT:    [[L:%.*]] = call i32 @f_load_global()
130 ; CHECK-NEXT:    store i32 0, ptr @A, align 4
131 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
132 ; CHECK:       true:
133 ; CHECK-NEXT:    ret i32 [[L]]
134 ; CHECK:       false:
135 ; CHECK-NEXT:    ret i32 0
137   %l = call i32 @f_load_global()
138   store i32 0, ptr @A
139   br i1 %z, label %true, label %false
140 true:
141   ret i32 %l
142 false:
143   ret i32 0
146 define i32 @test_nosink_call(i1 %z) {
147 ; CHECK-LABEL: @test_nosink_call(
148 ; CHECK-NEXT:    [[L:%.*]] = call i32 @f_load_global()
149 ; CHECK-NEXT:    call void @f_store_global(i32 0)
150 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
151 ; CHECK:       true:
152 ; CHECK-NEXT:    ret i32 [[L]]
153 ; CHECK:       false:
154 ; CHECK-NEXT:    ret i32 0
156   %l = call i32 @f_load_global()
157   call void @f_store_global(i32 0)
158   br i1 %z, label %true, label %false
159 true:
160   ret i32 %l
161 false:
162   ret i32 0
165 ; readnone calls are sunk across stores.
166 define i32 @test_sink_readnone(i1 %z) {
167 ; CHECK-LABEL: @test_sink_readnone(
168 ; CHECK-NEXT:    store i32 0, ptr @A, align 4
169 ; CHECK-NEXT:    br i1 [[Z:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
170 ; CHECK:       true:
171 ; CHECK-NEXT:    [[L:%.*]] = call i32 @f_readnone(i32 0)
172 ; CHECK-NEXT:    ret i32 [[L]]
173 ; CHECK:       false:
174 ; CHECK-NEXT:    ret i32 0
176   %l = call i32 @f_readnone(i32 0)
177   store i32 0, ptr @A
178   br i1 %z, label %true, label %false
179 true:
180   ret i32 %l
181 false:
182   ret i32 0