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