• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -basic-aa -sink -S | FileCheck %s
2
3declare i32 @f_load_global() nounwind readonly
4declare i32 @f_load_global_throwable() readonly
5declare i32 @f_load_arg(i32*) nounwind readonly argmemonly
6declare void @f_store_global(i32) nounwind
7declare void @f_store_arg(i32*) nounwind argmemonly
8declare void @f_readonly_arg(i32* readonly, i32*) nounwind argmemonly
9declare i32 @f_readnone(i32) nounwind readnone
10
11@A = external global i32
12@B = external global i32
13
14; Sink readonly call if no stores are in the way.
15;
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
20define i32 @test_sink_no_stores(i1 %z) {
21  %l = call i32 @f_load_global()
22  br i1 %z, label %true, label %false
23true:
24  ret i32 %l
25false:
26  ret i32 0
27}
28
29; CHECK-LABEL: @test_throwable_no_stores(
30; CHECK:         %l = call i32 @f_load_global
31; CHECK-NEXT:    br i1 %z
32define i32 @test_throwable_no_stores(i1 %z) {
33  %l = call i32 @f_load_global_throwable()
34  br i1 %z, label %true, label %false
35true:
36  ret i32 %l
37false:
38  ret i32 0
39}
40
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
45define 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
49true:
50  ret i32 %l
51false:
52  ret i32 0
53}
54
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
59define 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
63true:
64  ret i32 %l
65false:
66  ret i32 0
67}
68
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
73define 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
77true:
78  ret i32 %l
79false:
80  ret i32 0
81}
82
83; But don't sink if there is a store.
84;
85; CHECK-LABEL: @test_nosink_store(
86; CHECK: call i32 @f_load_global
87; CHECK-NEXT: store i32
88define 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
92true:
93  ret i32 %l
94false:
95  ret i32 0
96}
97
98; CHECK-LABEL: @test_nosink_call(
99; CHECK: call i32 @f_load_global
100; CHECK-NEXT: call void @f_store_global
101define 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
105true:
106  ret i32 %l
107false:
108  ret i32 0
109}
110
111; readnone calls are sunk across stores.
112;
113; CHECK-LABEL: @test_sink_readnone(
114; CHECK: true:
115; CHECK-NEXT: %l = call i32 @f_readnone(
116; CHECK-NEXT: ret i32 %l
117define 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
121true:
122  ret i32 %l
123false:
124  ret i32 0
125}
126