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