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:%.*]]
22 ; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_global()
23 ; CHECK-NEXT: ret i32 [[L]]
25 ; CHECK-NEXT: ret i32 0
27 %l = call i32 @f_load_global()
28 br i1 %z, label %true, label %false
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:%.*]]
40 ; CHECK-NEXT: ret i32 [[L]]
42 ; CHECK-NEXT: ret i32 0
44 %l = call i32 @f_load_global_throwable()
45 br i1 %z, label %true, label %false
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:%.*]]
57 ; CHECK-NEXT: ret i32 [[L]]
59 ; CHECK-NEXT: ret i32 0
61 %l = call i32 @f_load_global_may_not_return()
62 br i1 %z, label %true, label %false
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:%.*]]
74 ; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_arg(ptr @A)
75 ; CHECK-NEXT: ret i32 [[L]]
77 ; CHECK-NEXT: ret i32 0
79 %l = call i32 @f_load_arg(ptr @A)
81 br i1 %z, label %true, label %false
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:%.*]]
93 ; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_arg(ptr @A)
94 ; CHECK-NEXT: ret i32 [[L]]
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
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:%.*]]
112 ; CHECK-NEXT: [[L:%.*]] = call i32 @f_load_arg(ptr @A)
113 ; CHECK-NEXT: ret i32 [[L]]
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
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:%.*]]
133 ; CHECK-NEXT: ret i32 [[L]]
135 ; CHECK-NEXT: ret i32 0
137 %l = call i32 @f_load_global()
139 br i1 %z, label %true, label %false
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:%.*]]
152 ; CHECK-NEXT: ret i32 [[L]]
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
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:%.*]]
171 ; CHECK-NEXT: [[L:%.*]] = call i32 @f_readnone(i32 0)
172 ; CHECK-NEXT: ret i32 [[L]]
174 ; CHECK-NEXT: ret i32 0
176 %l = call i32 @f_readnone(i32 0)
178 br i1 %z, label %true, label %false