Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s -stack-symbol-ordering=0 -disable-fp-elim -mtriple=x86_64-pc-linux-gnu -mcpu=corei7 -o - | FileCheck %s
      2 ;  This test is fairly fragile.  The goal is to ensure that "large" stack
      3 ;  objects are allocated closest to the stack protector (i.e., farthest away 
      4 ;  from the Stack Pointer.)  In standard SSP mode this means that large (>=
      5 ;  ssp-buffer-size) arrays and structures containing such arrays are
      6 ;  closet to the protector.  With sspstrong and sspreq this means large
      7 ;  arrays/structures-with-arrays are closest, followed by small (< ssp-buffer-size)
      8 ;  arrays/structures-with-arrays, and then addr-taken variables.
      9 ;
     10 ;  Ideally, we only want verify that the objects appear in the correct groups
     11 ;  and that the groups have the correct relative stack offset.  The ordering
     12 ;  within a group is not relevant to this test.  Unfortunately, there is not
     13 ;  an elegant way to do this, so just match the offset for each object.
     14 ; RUN: llc < %s -disable-fp-elim -mtriple=x86_64-unknown-unknown -O0 -mcpu=corei7 -o - \
     15 ; RUN:   | FileCheck --check-prefix=FAST-NON-LIN %s
     16 ; FastISel was not setting the StackProtectorIndex when lowering
     17 ; Intrinsic::stackprotector and as a result the stack re-arrangement code was
     18 ; never applied.  This problem only shows up on non-Linux platforms because on
     19 ; Linux the stack protector cookie is loaded from a special address space which
     20 ; always triggers standard ISel.  Run a basic test to ensure that at -O0
     21 ; on a non-linux target the data layout rules are triggered.
     22 
     23 %struct.struct_large_char = type { [8 x i8] }
     24 %struct.struct_small_char = type { [2 x i8] }
     25 %struct.struct_large_nonchar = type { [8 x i32] }
     26 %struct.struct_small_nonchar = type { [2 x i16] }
     27 
     28 define void @layout_ssp() ssp {
     29 entry:
     30 ; Expected stack layout for ssp is
     31 ;  -16 large_char          . Group 1, nested arrays, arrays >= ssp-buffer-size
     32 ;  -24 struct_large_char   .
     33 ;  -28 scalar1             | Everything else
     34 ;  -32 scalar2
     35 ;  -36 scalar3
     36 ;  -40 addr-of
     37 ;  -44 small_nonchar
     38 ;  -80 large_nonchar
     39 ;  -82 small_char
     40 ;  -88 struct_small_char
     41 ;  -120 struct_large_nonchar
     42 ;  -128 struct_small_nonchar
     43 
     44 ; CHECK: layout_ssp:
     45 ; CHECK: call{{l|q}} get_scalar1
     46 ; CHECK: movl %eax, -28(
     47 ; CHECK: call{{l|q}} end_scalar1
     48 
     49 ; CHECK: call{{l|q}} get_scalar2
     50 ; CHECK: movl %eax, -32(
     51 ; CHECK: call{{l|q}} end_scalar2
     52 
     53 ; CHECK: call{{l|q}} get_scalar3
     54 ; CHECK: movl %eax, -36(
     55 ; CHECK: call{{l|q}} end_scalar3
     56 
     57 ; CHECK: call{{l|q}} get_addrof
     58 ; CHECK: movl %eax, -40(
     59 ; CHECK: call{{l|q}} end_addrof
     60 
     61 ; CHECK: get_small_nonchar
     62 ; CHECK: movw %ax, -44(
     63 ; CHECK: call{{l|q}} end_small_nonchar
     64 
     65 ; CHECK: call{{l|q}} get_large_nonchar
     66 ; CHECK: movl %eax, -80(
     67 ; CHECK: call{{l|q}} end_large_nonchar
     68 
     69 ; CHECK: call{{l|q}} get_small_char
     70 ; CHECK: movb %al, -82(
     71 ; CHECK: call{{l|q}} end_small_char
     72 
     73 ; CHECK: call{{l|q}} get_large_char
     74 ; CHECK: movb %al, -16(
     75 ; CHECK: call{{l|q}} end_large_char
     76 
     77 ; CHECK: call{{l|q}} get_struct_large_char
     78 ; CHECK: movb %al, -24(
     79 ; CHECK: call{{l|q}} end_struct_large_char
     80 
     81 ; CHECK: call{{l|q}} get_struct_small_char
     82 ; CHECK: movb %al, -88(
     83 ; CHECK: call{{l|q}} end_struct_small_char
     84 
     85 ; CHECK: call{{l|q}} get_struct_large_nonchar
     86 ; CHECK: movl %eax, -120(
     87 ; CHECK: call{{l|q}} end_struct_large_nonchar
     88 
     89 ; CHECK: call{{l|q}} get_struct_small_nonchar
     90 ; CHECK: movw %ax, -128(
     91 ; CHECK: call{{l|q}} end_struct_small_nonchar
     92   %x = alloca i32, align 4
     93   %y = alloca i32, align 4
     94   %z = alloca i32, align 4
     95   %ptr = alloca i32, align 4
     96   %small2 = alloca [2 x i16], align 2
     97   %large2 = alloca [8 x i32], align 16
     98   %small = alloca [2 x i8], align 1
     99   %large = alloca [8 x i8], align 1
    100   %a = alloca %struct.struct_large_char, align 1
    101   %b = alloca %struct.struct_small_char, align 1
    102   %c = alloca %struct.struct_large_nonchar, align 8
    103   %d = alloca %struct.struct_small_nonchar, align 2
    104   %call = call i32 @get_scalar1()
    105   store i32 %call, i32* %x, align 4
    106   call void @end_scalar1()
    107   %call1 = call i32 @get_scalar2()
    108   store i32 %call1, i32* %y, align 4
    109   call void @end_scalar2()
    110   %call2 = call i32 @get_scalar3()
    111   store i32 %call2, i32* %z, align 4
    112   call void @end_scalar3()
    113   %call3 = call i32 @get_addrof()
    114   store i32 %call3, i32* %ptr, align 4
    115   call void @end_addrof()
    116   %call4 = call signext i16 @get_small_nonchar()
    117   %arrayidx = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i64 0
    118   store i16 %call4, i16* %arrayidx, align 2
    119   call void @end_small_nonchar()
    120   %call5 = call i32 @get_large_nonchar()
    121   %arrayidx6 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i64 0
    122   store i32 %call5, i32* %arrayidx6, align 4
    123   call void @end_large_nonchar()
    124   %call7 = call signext i8 @get_small_char()
    125   %arrayidx8 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i64 0
    126   store i8 %call7, i8* %arrayidx8, align 1
    127   call void @end_small_char()
    128   %call9 = call signext i8 @get_large_char()
    129   %arrayidx10 = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i64 0
    130   store i8 %call9, i8* %arrayidx10, align 1
    131   call void @end_large_char()
    132   %call11 = call signext i8 @get_struct_large_char()
    133   %foo = getelementptr inbounds %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
    134   %arrayidx12 = getelementptr inbounds [8 x i8], [8 x i8]* %foo, i32 0, i64 0
    135   store i8 %call11, i8* %arrayidx12, align 1
    136   call void @end_struct_large_char()
    137   %call13 = call signext i8 @get_struct_small_char()
    138   %foo14 = getelementptr inbounds %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
    139   %arrayidx15 = getelementptr inbounds [2 x i8], [2 x i8]* %foo14, i32 0, i64 0
    140   store i8 %call13, i8* %arrayidx15, align 1
    141   call void @end_struct_small_char()
    142   %call16 = call i32 @get_struct_large_nonchar()
    143   %foo17 = getelementptr inbounds %struct.struct_large_nonchar, %struct.struct_large_nonchar* %c, i32 0, i32 0
    144   %arrayidx18 = getelementptr inbounds [8 x i32], [8 x i32]* %foo17, i32 0, i64 0
    145   store i32 %call16, i32* %arrayidx18, align 4
    146   call void @end_struct_large_nonchar()
    147   %call19 = call signext i16 @get_struct_small_nonchar()
    148   %foo20 = getelementptr inbounds %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
    149   %arrayidx21 = getelementptr inbounds [2 x i16], [2 x i16]* %foo20, i32 0, i64 0
    150   store i16 %call19, i16* %arrayidx21, align 2
    151   call void @end_struct_small_nonchar()
    152   %arraydecay = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i32 0
    153   %arraydecay22 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i32 0
    154   %arraydecay23 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i32 0
    155   %arraydecay24 = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i32 0
    156   %0 = load i32, i32* %x, align 4
    157   %1 = load i32, i32* %y, align 4
    158   %2 = load i32, i32* %z, align 4
    159   %coerce.dive = getelementptr %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
    160   %3 = bitcast [8 x i8]* %coerce.dive to i64*
    161   %4 = load i64, i64* %3, align 1
    162   %coerce.dive25 = getelementptr %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
    163   %5 = bitcast [2 x i8]* %coerce.dive25 to i16*
    164   %6 = load i16, i16* %5, align 1
    165   %coerce.dive26 = getelementptr %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
    166   %7 = bitcast [2 x i16]* %coerce.dive26 to i32*
    167   %8 = load i32, i32* %7, align 1
    168   call void @takes_all(i64 %4, i16 %6, %struct.struct_large_nonchar* byval align 8 %c, i32 %8, i8* %arraydecay, i8* %arraydecay22, i32* %arraydecay23, i16* %arraydecay24, i32* %ptr, i32 %0, i32 %1, i32 %2)
    169   ret void
    170 }
    171 
    172 define void @layout_sspstrong() nounwind uwtable sspstrong {
    173 entry:
    174 ; Expected stack layout for sspstrong is
    175 ;   -48   large_nonchar          . Group 1, nested arrays,
    176 ;   -56   large_char             .  arrays >= ssp-buffer-size
    177 ;   -64   struct_large_char      .
    178 ;   -96   struct_large_nonchar   .
    179 ;   -100  small_non_char         | Group 2, nested arrays, 
    180 ;   -102  small_char             |  arrays < ssp-buffer-size
    181 ;   -104  struct_small_char      |
    182 ;   -112  struct_small_nonchar   |
    183 ;   -116  addrof                 * Group 3, addr-of local
    184 ;   -120  scalar                 + Group 4, everything else
    185 ;   -124  scalar                 +
    186 ;   -128  scalar                 +
    187 ;   
    188 ; CHECK: layout_sspstrong:
    189 ; CHECK: call{{l|q}} get_scalar1
    190 ; CHECK: movl %eax, -120(
    191 ; CHECK: call{{l|q}} end_scalar1
    192 
    193 ; CHECK: call{{l|q}} get_scalar2
    194 ; CHECK: movl %eax, -124(
    195 ; CHECK: call{{l|q}} end_scalar2
    196 
    197 ; CHECK: call{{l|q}} get_scalar3
    198 ; CHECK: movl %eax, -128(
    199 ; CHECK: call{{l|q}} end_scalar3
    200 
    201 ; CHECK: call{{l|q}} get_addrof
    202 ; CHECK: movl %eax, -116(
    203 ; CHECK: call{{l|q}} end_addrof
    204 
    205 ; CHECK: get_small_nonchar
    206 ; CHECK: movw %ax, -100(
    207 ; CHECK: call{{l|q}} end_small_nonchar
    208 
    209 ; CHECK: call{{l|q}} get_large_nonchar
    210 ; CHECK: movl %eax, -48(
    211 ; CHECK: call{{l|q}} end_large_nonchar
    212 
    213 ; CHECK: call{{l|q}} get_small_char
    214 ; CHECK: movb %al, -102(
    215 ; CHECK: call{{l|q}} end_small_char
    216 
    217 ; CHECK: call{{l|q}} get_large_char
    218 ; CHECK: movb %al, -56(
    219 ; CHECK: call{{l|q}} end_large_char
    220 
    221 ; CHECK: call{{l|q}} get_struct_large_char
    222 ; CHECK: movb %al, -64(
    223 ; CHECK: call{{l|q}} end_struct_large_char
    224 
    225 ; CHECK: call{{l|q}} get_struct_small_char
    226 ; CHECK: movb %al, -104(
    227 ; CHECK: call{{l|q}} end_struct_small_char
    228 
    229 ; CHECK: call{{l|q}} get_struct_large_nonchar
    230 ; CHECK: movl %eax, -96(
    231 ; CHECK: call{{l|q}} end_struct_large_nonchar
    232 
    233 ; CHECK: call{{l|q}} get_struct_small_nonchar
    234 ; CHECK: movw %ax, -112(
    235 ; CHECK: call{{l|q}} end_struct_small_nonchar
    236   %x = alloca i32, align 4
    237   %y = alloca i32, align 4
    238   %z = alloca i32, align 4
    239   %ptr = alloca i32, align 4
    240   %small2 = alloca [2 x i16], align 2
    241   %large2 = alloca [8 x i32], align 16
    242   %small = alloca [2 x i8], align 1
    243   %large = alloca [8 x i8], align 1
    244   %a = alloca %struct.struct_large_char, align 1
    245   %b = alloca %struct.struct_small_char, align 1
    246   %c = alloca %struct.struct_large_nonchar, align 8
    247   %d = alloca %struct.struct_small_nonchar, align 2
    248   %call = call i32 @get_scalar1()
    249   store i32 %call, i32* %x, align 4
    250   call void @end_scalar1()
    251   %call1 = call i32 @get_scalar2()
    252   store i32 %call1, i32* %y, align 4
    253   call void @end_scalar2()
    254   %call2 = call i32 @get_scalar3()
    255   store i32 %call2, i32* %z, align 4
    256   call void @end_scalar3()
    257   %call3 = call i32 @get_addrof()
    258   store i32 %call3, i32* %ptr, align 4
    259   call void @end_addrof()
    260   %call4 = call signext i16 @get_small_nonchar()
    261   %arrayidx = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i64 0
    262   store i16 %call4, i16* %arrayidx, align 2
    263   call void @end_small_nonchar()
    264   %call5 = call i32 @get_large_nonchar()
    265   %arrayidx6 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i64 0
    266   store i32 %call5, i32* %arrayidx6, align 4
    267   call void @end_large_nonchar()
    268   %call7 = call signext i8 @get_small_char()
    269   %arrayidx8 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i64 0
    270   store i8 %call7, i8* %arrayidx8, align 1
    271   call void @end_small_char()
    272   %call9 = call signext i8 @get_large_char()
    273   %arrayidx10 = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i64 0
    274   store i8 %call9, i8* %arrayidx10, align 1
    275   call void @end_large_char()
    276   %call11 = call signext i8 @get_struct_large_char()
    277   %foo = getelementptr inbounds %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
    278   %arrayidx12 = getelementptr inbounds [8 x i8], [8 x i8]* %foo, i32 0, i64 0
    279   store i8 %call11, i8* %arrayidx12, align 1
    280   call void @end_struct_large_char()
    281   %call13 = call signext i8 @get_struct_small_char()
    282   %foo14 = getelementptr inbounds %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
    283   %arrayidx15 = getelementptr inbounds [2 x i8], [2 x i8]* %foo14, i32 0, i64 0
    284   store i8 %call13, i8* %arrayidx15, align 1
    285   call void @end_struct_small_char()
    286   %call16 = call i32 @get_struct_large_nonchar()
    287   %foo17 = getelementptr inbounds %struct.struct_large_nonchar, %struct.struct_large_nonchar* %c, i32 0, i32 0
    288   %arrayidx18 = getelementptr inbounds [8 x i32], [8 x i32]* %foo17, i32 0, i64 0
    289   store i32 %call16, i32* %arrayidx18, align 4
    290   call void @end_struct_large_nonchar()
    291   %call19 = call signext i16 @get_struct_small_nonchar()
    292   %foo20 = getelementptr inbounds %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
    293   %arrayidx21 = getelementptr inbounds [2 x i16], [2 x i16]* %foo20, i32 0, i64 0
    294   store i16 %call19, i16* %arrayidx21, align 2
    295   call void @end_struct_small_nonchar()
    296   %arraydecay = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i32 0
    297   %arraydecay22 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i32 0
    298   %arraydecay23 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i32 0
    299   %arraydecay24 = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i32 0
    300   %0 = load i32, i32* %x, align 4
    301   %1 = load i32, i32* %y, align 4
    302   %2 = load i32, i32* %z, align 4
    303   %coerce.dive = getelementptr %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
    304   %3 = bitcast [8 x i8]* %coerce.dive to i64*
    305   %4 = load i64, i64* %3, align 1
    306   %coerce.dive25 = getelementptr %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
    307   %5 = bitcast [2 x i8]* %coerce.dive25 to i16*
    308   %6 = load i16, i16* %5, align 1
    309   %coerce.dive26 = getelementptr %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
    310   %7 = bitcast [2 x i16]* %coerce.dive26 to i32*
    311   %8 = load i32, i32* %7, align 1
    312   call void @takes_all(i64 %4, i16 %6, %struct.struct_large_nonchar* byval align 8 %c, i32 %8, i8* %arraydecay, i8* %arraydecay22, i32* %arraydecay23, i16* %arraydecay24, i32* %ptr, i32 %0, i32 %1, i32 %2)
    313   ret void
    314 }
    315 
    316 define void @layout_sspreq() nounwind uwtable sspreq {
    317 entry:
    318 ; Expected stack layout for sspreq is the same as sspstrong
    319 ;   
    320 ; CHECK: layout_sspreq:
    321 ; CHECK: call{{l|q}} get_scalar1
    322 ; CHECK: movl %eax, -120(
    323 ; CHECK: call{{l|q}} end_scalar1
    324 
    325 ; CHECK: call{{l|q}} get_scalar2
    326 ; CHECK: movl %eax, -124(
    327 ; CHECK: call{{l|q}} end_scalar2
    328 
    329 ; CHECK: call{{l|q}} get_scalar3
    330 ; CHECK: movl %eax, -128(
    331 ; CHECK: call{{l|q}} end_scalar3
    332 
    333 ; CHECK: call{{l|q}} get_addrof
    334 ; CHECK: movl %eax, -116(
    335 ; CHECK: call{{l|q}} end_addrof
    336 
    337 ; CHECK: get_small_nonchar
    338 ; CHECK: movw %ax, -100(
    339 ; CHECK: call{{l|q}} end_small_nonchar
    340 
    341 ; CHECK: call{{l|q}} get_large_nonchar
    342 ; CHECK: movl %eax, -48(
    343 ; CHECK: call{{l|q}} end_large_nonchar
    344 
    345 ; CHECK: call{{l|q}} get_small_char
    346 ; CHECK: movb %al, -102(
    347 ; CHECK: call{{l|q}} end_small_char
    348 
    349 ; CHECK: call{{l|q}} get_large_char
    350 ; CHECK: movb %al, -56(
    351 ; CHECK: call{{l|q}} end_large_char
    352 
    353 ; CHECK: call{{l|q}} get_struct_large_char
    354 ; CHECK: movb %al, -64(
    355 ; CHECK: call{{l|q}} end_struct_large_char
    356 
    357 ; CHECK: call{{l|q}} get_struct_small_char
    358 ; CHECK: movb %al, -104(
    359 ; CHECK: call{{l|q}} end_struct_small_char
    360 
    361 ; CHECK: call{{l|q}} get_struct_large_nonchar
    362 ; CHECK: movl %eax, -96(
    363 ; CHECK: call{{l|q}} end_struct_large_nonchar
    364 
    365 ; CHECK: call{{l|q}} get_struct_small_nonchar
    366 ; CHECK: movw %ax, -112(
    367 ; CHECK: call{{l|q}} end_struct_small_nonchar
    368   %x = alloca i32, align 4
    369   %y = alloca i32, align 4
    370   %z = alloca i32, align 4
    371   %ptr = alloca i32, align 4
    372   %small2 = alloca [2 x i16], align 2
    373   %large2 = alloca [8 x i32], align 16
    374   %small = alloca [2 x i8], align 1
    375   %large = alloca [8 x i8], align 1
    376   %a = alloca %struct.struct_large_char, align 1
    377   %b = alloca %struct.struct_small_char, align 1
    378   %c = alloca %struct.struct_large_nonchar, align 8
    379   %d = alloca %struct.struct_small_nonchar, align 2
    380   %call = call i32 @get_scalar1()
    381   store i32 %call, i32* %x, align 4
    382   call void @end_scalar1()
    383   %call1 = call i32 @get_scalar2()
    384   store i32 %call1, i32* %y, align 4
    385   call void @end_scalar2()
    386   %call2 = call i32 @get_scalar3()
    387   store i32 %call2, i32* %z, align 4
    388   call void @end_scalar3()
    389   %call3 = call i32 @get_addrof()
    390   store i32 %call3, i32* %ptr, align 4
    391   call void @end_addrof()
    392   %call4 = call signext i16 @get_small_nonchar()
    393   %arrayidx = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i64 0
    394   store i16 %call4, i16* %arrayidx, align 2
    395   call void @end_small_nonchar()
    396   %call5 = call i32 @get_large_nonchar()
    397   %arrayidx6 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i64 0
    398   store i32 %call5, i32* %arrayidx6, align 4
    399   call void @end_large_nonchar()
    400   %call7 = call signext i8 @get_small_char()
    401   %arrayidx8 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i64 0
    402   store i8 %call7, i8* %arrayidx8, align 1
    403   call void @end_small_char()
    404   %call9 = call signext i8 @get_large_char()
    405   %arrayidx10 = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i64 0
    406   store i8 %call9, i8* %arrayidx10, align 1
    407   call void @end_large_char()
    408   %call11 = call signext i8 @get_struct_large_char()
    409   %foo = getelementptr inbounds %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
    410   %arrayidx12 = getelementptr inbounds [8 x i8], [8 x i8]* %foo, i32 0, i64 0
    411   store i8 %call11, i8* %arrayidx12, align 1
    412   call void @end_struct_large_char()
    413   %call13 = call signext i8 @get_struct_small_char()
    414   %foo14 = getelementptr inbounds %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
    415   %arrayidx15 = getelementptr inbounds [2 x i8], [2 x i8]* %foo14, i32 0, i64 0
    416   store i8 %call13, i8* %arrayidx15, align 1
    417   call void @end_struct_small_char()
    418   %call16 = call i32 @get_struct_large_nonchar()
    419   %foo17 = getelementptr inbounds %struct.struct_large_nonchar, %struct.struct_large_nonchar* %c, i32 0, i32 0
    420   %arrayidx18 = getelementptr inbounds [8 x i32], [8 x i32]* %foo17, i32 0, i64 0
    421   store i32 %call16, i32* %arrayidx18, align 4
    422   call void @end_struct_large_nonchar()
    423   %call19 = call signext i16 @get_struct_small_nonchar()
    424   %foo20 = getelementptr inbounds %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
    425   %arrayidx21 = getelementptr inbounds [2 x i16], [2 x i16]* %foo20, i32 0, i64 0
    426   store i16 %call19, i16* %arrayidx21, align 2
    427   call void @end_struct_small_nonchar()
    428   %arraydecay = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i32 0
    429   %arraydecay22 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i32 0
    430   %arraydecay23 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i32 0
    431   %arraydecay24 = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i32 0
    432   %0 = load i32, i32* %x, align 4
    433   %1 = load i32, i32* %y, align 4
    434   %2 = load i32, i32* %z, align 4
    435   %coerce.dive = getelementptr %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
    436   %3 = bitcast [8 x i8]* %coerce.dive to i64*
    437   %4 = load i64, i64* %3, align 1
    438   %coerce.dive25 = getelementptr %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
    439   %5 = bitcast [2 x i8]* %coerce.dive25 to i16*
    440   %6 = load i16, i16* %5, align 1
    441   %coerce.dive26 = getelementptr %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
    442   %7 = bitcast [2 x i16]* %coerce.dive26 to i32*
    443   %8 = load i32, i32* %7, align 1
    444   call void @takes_all(i64 %4, i16 %6, %struct.struct_large_nonchar* byval align 8 %c, i32 %8, i8* %arraydecay, i8* %arraydecay22, i32* %arraydecay23, i16* %arraydecay24, i32* %ptr, i32 %0, i32 %1, i32 %2)
    445   ret void
    446 }
    447 
    448 define void @fast_non_linux() ssp {
    449 entry:
    450 ; FAST-NON-LIN: fast_non_linux:
    451 ; FAST-NON-LIN: call{{l|q}} get_scalar1
    452 ; FAST-NON-LIN: movl %eax, -20(
    453 ; FAST-NON-LIN: call{{l|q}} end_scalar1
    454 
    455 ; FAST-NON-LIN: call{{l|q}} get_large_char
    456 ; FAST-NON-LIN: movb %al, -16(
    457 ; FAST-NON-LIN: call{{l|q}} end_large_char
    458   %x = alloca i32, align 4
    459   %large = alloca [8 x i8], align 1
    460   %call = call i32 @get_scalar1()
    461   store i32 %call, i32* %x, align 4
    462   call void @end_scalar1()
    463   %call1 = call signext i8 @get_large_char()
    464   %arrayidx = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i64 0
    465   store i8 %call1, i8* %arrayidx, align 1
    466   call void @end_large_char()
    467   %0 = load i32, i32* %x, align 4
    468   %arraydecay = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i32 0
    469   call void @takes_two(i32 %0, i8* %arraydecay)
    470   ret void
    471 }
    472 
    473 declare i32 @get_scalar1()
    474 declare void @end_scalar1()
    475 
    476 declare i32 @get_scalar2()
    477 declare void @end_scalar2()
    478 
    479 declare i32 @get_scalar3()
    480 declare void @end_scalar3()
    481 
    482 declare i32 @get_addrof()
    483 declare void @end_addrof()
    484 
    485 declare signext i16 @get_small_nonchar()
    486 declare void @end_small_nonchar()
    487 
    488 declare i32 @get_large_nonchar()
    489 declare void @end_large_nonchar()
    490 
    491 declare signext i8 @get_small_char()
    492 declare void @end_small_char()
    493 
    494 declare signext i8 @get_large_char()
    495 declare void @end_large_char()
    496 
    497 declare signext i8 @get_struct_large_char()
    498 declare void @end_struct_large_char()
    499 
    500 declare signext i8 @get_struct_small_char()
    501 declare void @end_struct_small_char()
    502 
    503 declare i32 @get_struct_large_nonchar()
    504 declare void @end_struct_large_nonchar()
    505 
    506 declare signext i16 @get_struct_small_nonchar()
    507 declare void @end_struct_small_nonchar()
    508 
    509 declare void @takes_all(i64, i16, %struct.struct_large_nonchar* byval align 8, i32, i8*, i8*, i32*, i16*, i32*, i32, i32, i32)
    510 declare void @takes_two(i32, i8*)
    511