1; RUN: opt -inline < %s -S -o - -inline-threshold=8 | FileCheck %s
2; RUN: opt -passes='cgscc(inline)' < %s -S -o - -inline-threshold=8 | FileCheck %s
3
4target datalayout = "p:32:32"
5
6declare void @llvm.lifetime.start.p0i8(i64 %size, i8* nocapture %ptr)
7
8@glbl = external global i32
9
10define void @outer1() {
11; CHECK-LABEL: @outer1(
12; CHECK-NOT: call void @inner1
13  %ptr = alloca i32
14  call void @inner1(i32* %ptr)
15  ret void
16}
17
18define void @inner1(i32 *%ptr) {
19  %A = load i32, i32* %ptr
20  store i32 0, i32* %ptr
21  %C = getelementptr inbounds i32, i32* %ptr, i32 0
22  %D = getelementptr inbounds i32, i32* %ptr, i32 1
23  %E = bitcast i32* %ptr to i8*
24  %F = select i1 false, i32* %ptr, i32* @glbl
25  call void @llvm.lifetime.start.p0i8(i64 0, i8* %E)
26  call void @extern()
27  ret void
28}
29
30define void @outer2() {
31; CHECK-LABEL: @outer2(
32; CHECK: call void @inner2
33  %ptr = alloca i32
34  call void @inner2(i32* %ptr)
35  ret void
36}
37
38; %D poisons this call, scalar-repl can't handle that instruction.
39define void @inner2(i32 *%ptr) {
40  %A = load i32, i32* %ptr
41  store i32 0, i32* %ptr
42  %C = getelementptr inbounds i32, i32* %ptr, i32 0
43  %D = getelementptr inbounds i32, i32* %ptr, i32 %A
44  %E = bitcast i32* %ptr to i8*
45  %F = select i1 false, i32* %ptr, i32* @glbl
46  call void @llvm.lifetime.start.p0i8(i64 0, i8* %E)
47  call void @extern()
48  ret void
49}
50
51define void @outer3() {
52; CHECK-LABEL: @outer3(
53; CHECK-NOT: call void @inner3
54  %ptr = alloca i32
55  call void @inner3(i32* %ptr, i1 undef)
56  ret void
57}
58
59define void @inner3(i32 *%ptr, i1 %x) {
60  %A = icmp eq i32* %ptr, null
61  %B = and i1 %x, %A
62  call void @extern()
63  br i1 %A, label %bb.true, label %bb.false
64bb.true:
65  ; This block musn't be counted in the inline cost.
66  %t1 = load i32, i32* %ptr
67  %t2 = add i32 %t1, 1
68  %t3 = add i32 %t2, 1
69  %t4 = add i32 %t3, 1
70  %t5 = add i32 %t4, 1
71  %t6 = add i32 %t5, 1
72  %t7 = add i32 %t6, 1
73  %t8 = add i32 %t7, 1
74  %t9 = add i32 %t8, 1
75  %t10 = add i32 %t9, 1
76  %t11 = add i32 %t10, 1
77  %t12 = add i32 %t11, 1
78  %t13 = add i32 %t12, 1
79  %t14 = add i32 %t13, 1
80  %t15 = add i32 %t14, 1
81  %t16 = add i32 %t15, 1
82  %t17 = add i32 %t16, 1
83  %t18 = add i32 %t17, 1
84  %t19 = add i32 %t18, 1
85  %t20 = add i32 %t19, 1
86  ret void
87bb.false:
88  ret void
89}
90
91define void @outer4(i32 %A) {
92; CHECK-LABEL: @outer4(
93; CHECK-NOT: call void @inner4
94  %ptr = alloca i32
95  call void @inner4(i32* %ptr, i32 %A)
96  ret void
97}
98
99; %B poisons this call, scalar-repl can't handle that instruction. However, we
100; still want to detect that the icmp and branch *can* be handled.
101define void @inner4(i32 *%ptr, i32 %A) {
102  %B = getelementptr inbounds i32, i32* %ptr, i32 %A
103  %C = icmp eq i32* %ptr, null
104  call void @extern()
105  br i1 %C, label %bb.true, label %bb.false
106bb.true:
107  ; This block musn't be counted in the inline cost.
108  %t1 = load i32, i32* %ptr
109  %t2 = add i32 %t1, 1
110  %t3 = add i32 %t2, 1
111  %t4 = add i32 %t3, 1
112  %t5 = add i32 %t4, 1
113  %t6 = add i32 %t5, 1
114  %t7 = add i32 %t6, 1
115  %t8 = add i32 %t7, 1
116  %t9 = add i32 %t8, 1
117  %t10 = add i32 %t9, 1
118  %t11 = add i32 %t10, 1
119  %t12 = add i32 %t11, 1
120  %t13 = add i32 %t12, 1
121  %t14 = add i32 %t13, 1
122  %t15 = add i32 %t14, 1
123  %t16 = add i32 %t15, 1
124  %t17 = add i32 %t16, 1
125  %t18 = add i32 %t17, 1
126  %t19 = add i32 %t18, 1
127  %t20 = add i32 %t19, 1
128  ret void
129bb.false:
130  ret void
131}
132
133define void @outer5() {
134; CHECK-LABEL: @outer5(
135; CHECK-NOT: call void @inner5
136  %ptr = alloca i32
137  call void @inner5(i1 false, i32* %ptr)
138  ret void
139}
140
141; %D poisons this call, scalar-repl can't handle that instruction. However, if
142; the flag is set appropriately, the poisoning instruction is inside of dead
143; code, and so shouldn't be counted.
144define void @inner5(i1 %flag, i32 *%ptr) {
145  %A = load i32, i32* %ptr
146  store i32 0, i32* %ptr
147  call void @extern()
148  %C = getelementptr inbounds i32, i32* %ptr, i32 0
149  br i1 %flag, label %if.then, label %exit
150
151if.then:
152  %D = getelementptr inbounds i32, i32* %ptr, i32 %A
153  %E = bitcast i32* %ptr to i8*
154  %F = select i1 false, i32* %ptr, i32* @glbl
155  call void @llvm.lifetime.start.p0i8(i64 0, i8* %E)
156  ret void
157
158exit:
159  ret void
160}
161
162declare void @extern()
163