150
|
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)
|
173
|
138 // CHECK: call void @_ZN8Combiner1fEv(%struct.Combiner* nonnull sret align 4 [[T2]], %struct.Combiner* nonnull [[T1]])
|
150
|
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 }
|