Home | History | Annotate | Download | only in CodeGenCXX
      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