1 // RUN: %clang_cc1 -triple armv7-unknown-linux-gnueabihf %s -o - -emit-llvm -O1 | 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: [[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