1; RUN: opt -inline < %s -S -o - -inline-threshold=3  | FileCheck %s
2
3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4target triple = "x86_64-unknown-linux-gnu"
5
6declare void @pad() readnone
7
8define void @outer1(i32* %a) {
9; CHECK-LABEL: @outer1(
10; CHECK-NOT: call void @inner1
11  %b = alloca i32
12  call void @inner1(i32* %a, i32* %b)
13  ret void
14}
15
16define void @inner1(i32* %a, i32* %b) {
17  %1 = load i32, i32* %a
18  store i32 %1, i32 * %b ; This store does not clobber the first load.
19  %2 = load i32, i32* %a
20  call void @pad()
21  %3 = load i32, i32* %a
22  ret void
23}
24
25
26define void @outer2(i32* %a, i32* %b) {
27; CHECK-LABEL: @outer2(
28; CHECK: call void @inner2
29  call void @inner2(i32* %a, i32* %b)
30  ret void
31}
32
33define void @inner2(i32* %a, i32* %b) {
34  %1 = load i32, i32* %a
35  store i32 %1, i32 * %b ; This store clobbers the first load.
36  %2 = load i32, i32* %a
37  call void @pad()
38  ret void
39}
40
41
42define void @outer3(i32* %a) {
43; CHECK-LABEL: @outer3(
44; CHECK: call void @inner3
45  call void @inner3(i32* %a)
46  ret void
47}
48
49declare void @ext()
50
51define void @inner3(i32* %a) {
52  %1 = load i32, i32* %a
53  call void @ext() ; This call clobbers the first load.
54  %2 = load i32, i32* %a
55  ret void
56}
57
58
59define void @outer4(i32* %a, i32* %b, i32* %c) {
60; CHECK-LABEL: @outer4(
61; CHECK-NOT: call void @inner4
62  call void @inner4(i32* %a, i32* %b, i1 false)
63  ret void
64}
65
66define void @inner4(i32* %a, i32* %b, i1 %pred) {
67  %1 = load i32, i32* %a
68  br i1 %pred, label %cond_true, label %cond_false
69
70cond_true:
71  store i32 %1, i32 * %b ; This store does not clobber the first load.
72  br label %cond_false
73
74cond_false:
75  %2 = load i32, i32* %a
76  call void @pad()
77  %3 = load i32, i32* %a
78  %4 = load i32, i32* %a
79  ret void
80}
81
82
83define void @outer5(i32* %a, double %b) {
84; CHECK-LABEL: @outer5(
85; CHECK-NOT: call void @inner5
86  call void @inner5(i32* %a, double %b)
87  ret void
88}
89
90declare double @llvm.fabs.f64(double) nounwind readnone
91
92define void @inner5(i32* %a, double %b) {
93  %1 = load i32, i32* %a
94  %2 = call double @llvm.fabs.f64(double %b) ; This intrinsic does not clobber the first load.
95  %3 = load i32, i32* %a
96  call void @pad()
97  ret void
98}
99
100define void @outer6(i32* %a, i8* %ptr) {
101; CHECK-LABEL: @outer6(
102; CHECK-NOT: call void @inner6
103  call void @inner6(i32* %a, i8* %ptr)
104  ret void
105}
106
107declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) argmemonly nounwind
108
109define void @inner6(i32* %a, i8* %ptr) {
110  %1 = load i32, i32* %a
111  call void @llvm.lifetime.start.p0i8(i64 32, i8* %ptr) ; This intrinsic does not clobber the first load.
112  %2 = load i32, i32* %a
113  call void @pad()
114  %3 = load i32, i32* %a
115  ret void
116}
117
118define void @outer7(i32* %a) {
119; CHECK-LABEL: @outer7(
120; CHECK-NOT: call void @inner7
121  call void @inner7(i32* %a)
122  ret void
123}
124
125declare void @ext2() readnone
126
127define void @inner7(i32* %a) {
128  %1 = load i32, i32* %a
129  call void @ext2() ; This call does not clobber the first load.
130  %2 = load i32, i32* %a
131  ret void
132}
133
134
135define void @outer8(i32* %a) {
136; CHECK-LABEL: @outer8(
137; CHECK-NOT: call void @inner8
138  call void @inner8(i32* %a, void ()* @ext2)
139  ret void
140}
141
142define void @inner8(i32* %a, void ()* %f) {
143  %1 = load i32, i32* %a
144  call void %f() ; This indirect call does not clobber the first load.
145  %2 = load i32, i32* %a
146  call void @pad()
147  call void @pad()
148  call void @pad()
149  call void @pad()
150  call void @pad()
151  call void @pad()
152  call void @pad()
153  call void @pad()
154  call void @pad()
155  call void @pad()
156  call void @pad()
157  call void @pad()
158  ret void
159}
160
161
162define void @outer9(i32* %a) {
163; CHECK-LABEL: @outer9(
164; CHECK: call void @inner9
165  call void @inner9(i32* %a, void ()* @ext)
166  ret void
167}
168
169define void @inner9(i32* %a, void ()* %f) {
170  %1 = load i32, i32* %a
171  call void %f() ; This indirect call clobbers the first load.
172  %2 = load i32, i32* %a
173  call void @pad()
174  call void @pad()
175  call void @pad()
176  call void @pad()
177  call void @pad()
178  call void @pad()
179  call void @pad()
180  call void @pad()
181  call void @pad()
182  call void @pad()
183  call void @pad()
184  call void @pad()
185  ret void
186}
187
188
189define void @outer10(i32* %a) {
190; CHECK-LABEL: @outer10(
191; CHECK: call void @inner10
192  %b = alloca i32
193  call void @inner10(i32* %a, i32* %b)
194  ret void
195}
196
197define void @inner10(i32* %a, i32* %b) {
198  %1 = load i32, i32* %a
199  store i32 %1, i32 * %b
200  %2 = load volatile i32, i32* %a ; volatile load should be kept.
201  call void @pad()
202  %3 = load volatile i32, i32* %a ; Same as the above.
203  ret void
204}
205