xref: /aosp_15_r20/external/clang/test/CodeGenCXX/stack-reuse.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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