1*67e74705SXin Li // RUN: %clang_cc1 -triple armv7-unknown-linux-gnueabihf %s -o - -emit-llvm -O1 | FileCheck %s
2*67e74705SXin Li
3*67e74705SXin Li // Stack should be reused when possible, no need to allocate two separate slots
4*67e74705SXin Li // if they have disjoint lifetime.
5*67e74705SXin Li
6*67e74705SXin Li // Sizes of objects are related to previously existed threshold of 32. In case
7*67e74705SXin Li // of S_large stack size is rounded to 40 bytes.
8*67e74705SXin Li
9*67e74705SXin Li // 32B
10*67e74705SXin Li struct S_small {
11*67e74705SXin Li int a[8];
12*67e74705SXin Li };
13*67e74705SXin Li
14*67e74705SXin Li // 36B
15*67e74705SXin Li struct S_large {
16*67e74705SXin Li int a[9];
17*67e74705SXin Li };
18*67e74705SXin Li
19*67e74705SXin Li // Helper class for lifetime scope absence testing
20*67e74705SXin Li struct Combiner {
21*67e74705SXin Li S_large a, b;
22*67e74705SXin Li
23*67e74705SXin Li Combiner(S_large);
24*67e74705SXin Li Combiner f();
25*67e74705SXin Li };
26*67e74705SXin Li
27*67e74705SXin Li extern S_small foo_small();
28*67e74705SXin Li extern S_large foo_large();
29*67e74705SXin Li extern void bar_small(S_small*);
30*67e74705SXin Li extern void bar_large(S_large*);
31*67e74705SXin Li
32*67e74705SXin Li // Prevent mangling of function names.
33*67e74705SXin Li extern "C" {
34*67e74705SXin Li
small_rvoed_unnamed_temporary_object()35*67e74705SXin Li void small_rvoed_unnamed_temporary_object() {
36*67e74705SXin Li // CHECK-LABEL: define void @small_rvoed_unnamed_temporary_object
37*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
38*67e74705SXin Li // CHECK: call void @_Z9foo_smallv
39*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
40*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
41*67e74705SXin Li // CHECK: call void @_Z9foo_smallv
42*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
43*67e74705SXin Li
44*67e74705SXin Li foo_small();
45*67e74705SXin Li foo_small();
46*67e74705SXin Li }
47*67e74705SXin Li
large_rvoed_unnamed_temporary_object()48*67e74705SXin Li void large_rvoed_unnamed_temporary_object() {
49*67e74705SXin Li // CHECK-LABEL: define void @large_rvoed_unnamed_temporary_object
50*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
51*67e74705SXin Li // CHECK: call void @_Z9foo_largev
52*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
53*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
54*67e74705SXin Li // CHECK: call void @_Z9foo_largev
55*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
56*67e74705SXin Li
57*67e74705SXin Li foo_large();
58*67e74705SXin Li foo_large();
59*67e74705SXin Li }
60*67e74705SXin Li
small_rvoed_named_temporary_object()61*67e74705SXin Li void small_rvoed_named_temporary_object() {
62*67e74705SXin Li // CHECK-LABEL: define void @small_rvoed_named_temporary_object
63*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
64*67e74705SXin Li // CHECK: call void @_Z9foo_smallv
65*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
66*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
67*67e74705SXin Li // CHECK: call void @_Z9foo_smallv
68*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
69*67e74705SXin Li
70*67e74705SXin Li {
71*67e74705SXin Li S_small s = foo_small();
72*67e74705SXin Li }
73*67e74705SXin Li {
74*67e74705SXin Li S_small s = foo_small();
75*67e74705SXin Li }
76*67e74705SXin Li }
77*67e74705SXin Li
large_rvoed_named_temporary_object()78*67e74705SXin Li void large_rvoed_named_temporary_object() {
79*67e74705SXin Li // CHECK-LABEL: define void @large_rvoed_named_temporary_object
80*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
81*67e74705SXin Li // CHECK: call void @_Z9foo_largev
82*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
83*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
84*67e74705SXin Li // CHECK: call void @_Z9foo_largev
85*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
86*67e74705SXin Li
87*67e74705SXin Li {
88*67e74705SXin Li S_large s = foo_large();
89*67e74705SXin Li }
90*67e74705SXin Li {
91*67e74705SXin Li S_large s = foo_large();
92*67e74705SXin Li }
93*67e74705SXin Li }
94*67e74705SXin Li
small_auto_object()95*67e74705SXin Li void small_auto_object() {
96*67e74705SXin Li // CHECK-LABEL: define void @small_auto_object
97*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
98*67e74705SXin Li // CHECK: call void @_Z9bar_smallP7S_small
99*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
100*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
101*67e74705SXin Li // CHECK: call void @_Z9bar_smallP7S_small
102*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
103*67e74705SXin Li
104*67e74705SXin Li {
105*67e74705SXin Li S_small s;
106*67e74705SXin Li bar_small(&s);
107*67e74705SXin Li }
108*67e74705SXin Li {
109*67e74705SXin Li S_small s;
110*67e74705SXin Li bar_small(&s);
111*67e74705SXin Li }
112*67e74705SXin Li }
113*67e74705SXin Li
large_auto_object()114*67e74705SXin Li void large_auto_object() {
115*67e74705SXin Li // CHECK-LABEL: define void @large_auto_object
116*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
117*67e74705SXin Li // CHECK: call void @_Z9bar_largeP7S_large
118*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
119*67e74705SXin Li // CHECK: call void @llvm.lifetime.start
120*67e74705SXin Li // CHECK: call void @_Z9bar_largeP7S_large
121*67e74705SXin Li // CHECK: call void @llvm.lifetime.end
122*67e74705SXin Li
123*67e74705SXin Li {
124*67e74705SXin Li S_large s;
125*67e74705SXin Li bar_large(&s);
126*67e74705SXin Li }
127*67e74705SXin Li {
128*67e74705SXin Li S_large s;
129*67e74705SXin Li bar_large(&s);
130*67e74705SXin Li }
131*67e74705SXin Li }
132*67e74705SXin Li
large_combiner_test(S_large s)133*67e74705SXin Li int large_combiner_test(S_large s) {
134*67e74705SXin Li // CHECK-LABEL: define i32 @large_combiner_test
135*67e74705SXin Li // CHECK: [[T1:%.*]] = alloca %struct.Combiner
136*67e74705SXin Li // CHECK: [[T2:%.*]] = alloca %struct.Combiner
137*67e74705SXin Li // CHECK: [[T3:%.*]] = call %struct.Combiner* @_ZN8CombinerC1E7S_large(%struct.Combiner* nonnull [[T1]], [9 x i32] %s.coerce)
138*67e74705SXin Li // CHECK: call void @_ZN8Combiner1fEv(%struct.Combiner* nonnull sret [[T2]], %struct.Combiner* nonnull [[T1]])
139*67e74705SXin Li // CHECK: [[T4:%.*]] = getelementptr inbounds %struct.Combiner, %struct.Combiner* [[T2]], i32 0, i32 0, i32 0, i32 0
140*67e74705SXin Li // CHECK: [[T5:%.*]] = load i32, i32* [[T4]]
141*67e74705SXin Li // CHECK: ret i32 [[T5]]
142*67e74705SXin Li
143*67e74705SXin Li return Combiner(s).f().a.a[0];
144*67e74705SXin Li }
145*67e74705SXin Li
146*67e74705SXin Li }
147