Mercurial > hg > CbC > CbC_llvm
comparison clang/test/CodeGenCXX/stack-reuse.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 0572611fdcc8 |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 // RUN: %clang_cc1 -triple armv7-unknown-linux-gnueabihf %s -o - -emit-llvm -O2 | 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 | |
10 struct S_small { | |
11 int a[8]; | |
12 }; | |
13 | |
14 // 36B | |
15 struct S_large { | |
16 int a[9]; | |
17 }; | |
18 | |
19 // Helper class for lifetime scope absence testing | |
20 struct Combiner { | |
21 S_large a, b; | |
22 | |
23 Combiner(S_large); | |
24 Combiner f(); | |
25 }; | |
26 | |
27 extern S_small foo_small(); | |
28 extern S_large foo_large(); | |
29 extern void bar_small(S_small*); | |
30 extern void bar_large(S_large*); | |
31 | |
32 // Prevent mangling of function names. | |
33 extern "C" { | |
34 | |
35 void 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 | |
48 void 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 | |
61 void 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 | |
78 void 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 | |
95 void 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 | |
114 void 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 | |
133 int large_combiner_test(S_large s) { | |
134 // CHECK-LABEL: define i32 @large_combiner_test | |
135 // CHECK: [[T2:%.*]] = alloca %struct.Combiner | |
136 // CHECK: [[T1:%.*]] = 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 } |