Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s -mtriple=i686-windows | FileCheck %s -check-prefix=NORMAL
      2 ; RUN: llc < %s -mtriple=x86_64-windows | FileCheck %s -check-prefix=X64
      3 ; RUN: llc < %s -mtriple=i686-windows -force-align-stack -stack-alignment=32 | FileCheck %s -check-prefix=ALIGNED 
      4 
      5 declare void @good(i32 %a, i32 %b, i32 %c, i32 %d)
      6 declare void @inreg(i32 %a, i32 inreg %b, i32 %c, i32 %d)
      7 declare void @oneparam(i32 %a)
      8 declare void @eightparams(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h)
      9 
     10 
     11 ; Here, we should have a reserved frame, so we don't expect pushes
     12 ; NORMAL-LABEL: test1:
     13 ; NORMAL: subl    $16, %esp
     14 ; NORMAL-NEXT: movl    $4, 12(%esp)
     15 ; NORMAL-NEXT: movl    $3, 8(%esp)
     16 ; NORMAL-NEXT: movl    $2, 4(%esp)
     17 ; NORMAL-NEXT: movl    $1, (%esp)
     18 ; NORMAL-NEXT: call
     19 ; NORMAL-NEXT: addl $16, %esp
     20 define void @test1() {
     21 entry:
     22   call void @good(i32 1, i32 2, i32 3, i32 4)
     23   ret void
     24 }
     25 
     26 ; We're optimizing for code size, so we should get pushes for x86,
     27 ; even though there is a reserved call frame.
     28 ; Make sure we don't touch x86-64
     29 ; NORMAL-LABEL: test1b:
     30 ; NORMAL-NOT: subl {{.*}} %esp
     31 ; NORMAL: pushl   $4
     32 ; NORMAL-NEXT: pushl   $3
     33 ; NORMAL-NEXT: pushl   $2
     34 ; NORMAL-NEXT: pushl   $1
     35 ; NORMAL-NEXT: call
     36 ; NORMAL-NEXT: addl $16, %esp
     37 ; X64-LABEL: test1b:
     38 ; X64: movl    $1, %ecx
     39 ; X64-NEXT: movl    $2, %edx
     40 ; X64-NEXT: movl    $3, %r8d
     41 ; X64-NEXT: movl    $4, %r9d
     42 ; X64-NEXT: callq   good
     43 define void @test1b() optsize {
     44 entry:
     45   call void @good(i32 1, i32 2, i32 3, i32 4)
     46   ret void
     47 }
     48 
     49 ; Same as above, but for minsize
     50 ; NORMAL-LABEL: test1c:
     51 ; NORMAL-NOT: subl {{.*}} %esp
     52 ; NORMAL: pushl   $4
     53 ; NORMAL-NEXT: pushl   $3
     54 ; NORMAL-NEXT: pushl   $2
     55 ; NORMAL-NEXT: pushl   $1
     56 ; NORMAL-NEXT: call
     57 ; NORMAL-NEXT: addl $16, %esp
     58 define void @test1c() minsize {
     59 entry:
     60   call void @good(i32 1, i32 2, i32 3, i32 4)
     61   ret void
     62 }
     63 
     64 ; If we have a reserved frame, we should have pushes
     65 ; NORMAL-LABEL: test2:
     66 ; NORMAL-NOT: subl {{.*}} %esp
     67 ; NORMAL: pushl   $4
     68 ; NORMAL-NEXT: pushl   $3
     69 ; NORMAL-NEXT: pushl   $2
     70 ; NORMAL-NEXT: pushl   $1
     71 ; NORMAL-NEXT: call
     72 define void @test2(i32 %k) {
     73 entry:
     74   %a = alloca i32, i32 %k
     75   call void @good(i32 1, i32 2, i32 3, i32 4)
     76   ret void
     77 }
     78 
     79 ; Again, we expect a sequence of 4 immediate pushes
     80 ; Checks that we generate the right pushes for >8bit immediates
     81 ; NORMAL-LABEL: test2b:
     82 ; NORMAL-NOT: subl {{.*}} %esp
     83 ; NORMAL: pushl   $4096
     84 ; NORMAL-NEXT: pushl   $3072
     85 ; NORMAL-NEXT: pushl   $2048
     86 ; NORMAL-NEXT: pushl   $1024
     87 ; NORMAL-NEXT: call
     88 ; NORMAL-NEXT: addl $16, %esp
     89 define void @test2b() optsize {
     90 entry:
     91   call void @good(i32 1024, i32 2048, i32 3072, i32 4096)
     92   ret void
     93 }
     94 
     95 ; The first push should push a register
     96 ; NORMAL-LABEL: test3:
     97 ; NORMAL-NOT: subl {{.*}} %esp
     98 ; NORMAL: pushl   $4
     99 ; NORMAL-NEXT: pushl   $3
    100 ; NORMAL-NEXT: pushl   $2
    101 ; NORMAL-NEXT: pushl   %e{{..}}
    102 ; NORMAL-NEXT: call
    103 ; NORMAL-NEXT: addl $16, %esp
    104 define void @test3(i32 %k) optsize {
    105 entry:
    106   %f = add i32 %k, 1
    107   call void @good(i32 %f, i32 2, i32 3, i32 4)
    108   ret void
    109 }
    110 
    111 ; We don't support weird calling conventions
    112 ; NORMAL-LABEL: test4:
    113 ; NORMAL: subl    $12, %esp
    114 ; NORMAL-NEXT: movl    $4, 8(%esp)
    115 ; NORMAL-NEXT: movl    $3, 4(%esp)
    116 ; NORMAL-NEXT: movl    $1, (%esp)
    117 ; NORMAL-NEXT: movl    $2, %eax
    118 ; NORMAL-NEXT: call
    119 ; NORMAL-NEXT: addl $12, %esp
    120 define void @test4() optsize {
    121 entry:
    122   call void @inreg(i32 1, i32 2, i32 3, i32 4)
    123   ret void
    124 }
    125 
    126 ; When there is no reserved call frame, check that additional alignment
    127 ; is added when the pushes don't add up to the required alignment.
    128 ; ALIGNED-LABEL: test5:
    129 ; ALIGNED: subl    $16, %esp
    130 ; ALIGNED-NEXT: pushl   $4
    131 ; ALIGNED-NEXT: pushl   $3
    132 ; ALIGNED-NEXT: pushl   $2
    133 ; ALIGNED-NEXT: pushl   $1
    134 ; ALIGNED-NEXT: call
    135 define void @test5(i32 %k) {
    136 entry:
    137   %a = alloca i32, i32 %k
    138   call void @good(i32 1, i32 2, i32 3, i32 4)
    139   ret void
    140 }
    141 
    142 ; When the alignment adds up, do the transformation
    143 ; ALIGNED-LABEL: test5b:
    144 ; ALIGNED: pushl   $8
    145 ; ALIGNED-NEXT: pushl   $7
    146 ; ALIGNED-NEXT: pushl   $6
    147 ; ALIGNED-NEXT: pushl   $5
    148 ; ALIGNED-NEXT: pushl   $4
    149 ; ALIGNED-NEXT: pushl   $3
    150 ; ALIGNED-NEXT: pushl   $2
    151 ; ALIGNED-NEXT: pushl   $1
    152 ; ALIGNED-NEXT: call
    153 define void @test5b() optsize {
    154 entry:
    155   call void @eightparams(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8)
    156   ret void
    157 }
    158 
    159 ; When having to compensate for the alignment isn't worth it,
    160 ; don't use pushes.
    161 ; ALIGNED-LABEL: test5c:
    162 ; ALIGNED: movl $1, (%esp)
    163 ; ALIGNED-NEXT: call
    164 define void @test5c() optsize {
    165 entry:
    166   call void @oneparam(i32 1)
    167   ret void
    168 }
    169 
    170 ; Check that pushing the addresses of globals (Or generally, things that 
    171 ; aren't exactly immediates) isn't broken.
    172 ; Fixes PR21878.
    173 ; NORMAL-LABEL: test6:
    174 ; NORMAL: pushl    $_ext
    175 ; NORMAL-NEXT: call
    176 declare void @f(i8*)
    177 @ext = external constant i8
    178 
    179 define void @test6() {
    180   call void @f(i8* @ext)
    181   br label %bb
    182 bb:
    183   alloca i32
    184   ret void
    185 }
    186 
    187 ; Check that we fold simple cases into the push
    188 ; NORMAL-LABEL: test7:
    189 ; NORMAL-NOT: subl {{.*}} %esp
    190 ; NORMAL: movl 4(%esp), [[EAX:%e..]]
    191 ; NORMAL-NEXT: pushl   $4
    192 ; NORMAL-NEXT: pushl   ([[EAX]])
    193 ; NORMAL-NEXT: pushl   $2
    194 ; NORMAL-NEXT: pushl   $1
    195 ; NORMAL-NEXT: call
    196 ; NORMAL-NEXT: addl $16, %esp
    197 define void @test7(i32* %ptr) optsize {
    198 entry:
    199   %val = load i32, i32* %ptr
    200   call void @good(i32 1, i32 2, i32 %val, i32 4)
    201   ret void
    202 }
    203 
    204 ; Fold stack-relative loads into the push, with correct offset
    205 ; In particular, at the second push, %b was at 12(%esp) and
    206 ; %a wast at 8(%esp), but the second push bumped %esp, so %a
    207 ; is now it at 12(%esp)
    208 ; NORMAL-LABEL: test8:
    209 ; NORMAL: pushl   $4
    210 ; NORMAL-NEXT: pushl   12(%esp)
    211 ; NORMAL-NEXT: pushl   12(%esp)
    212 ; NORMAL-NEXT: pushl   $1
    213 ; NORMAL-NEXT: call
    214 ; NORMAL-NEXT: addl $16, %esp
    215 define void @test8(i32 %a, i32 %b) optsize {
    216 entry:
    217   call void @good(i32 1, i32 %a, i32 %b, i32 4)
    218   ret void
    219 }
    220 
    221 ; If one function is using push instructions, and the other isn't
    222 ; (because it has frame-index references), then we must resolve
    223 ; these references correctly.
    224 ; NORMAL-LABEL: test9:
    225 ; NORMAL-NOT: leal (%esp), 
    226 ; NORMAL: pushl $4
    227 ; NORMAL-NEXT: pushl $3
    228 ; NORMAL-NEXT: pushl $2
    229 ; NORMAL-NEXT: pushl $1
    230 ; NORMAL-NEXT: call
    231 ; NORMAL-NEXT: addl $16, %esp
    232 ; NORMAL-NEXT: subl $16, %esp
    233 ; NORMAL-NEXT: leal 16(%esp), [[EAX:%e..]]
    234 ; NORMAL-NEXT: movl    [[EAX]], 12(%esp)
    235 ; NORMAL-NEXT: movl    $7, 8(%esp)
    236 ; NORMAL-NEXT: movl    $6, 4(%esp)
    237 ; NORMAL-NEXT: movl    $5, (%esp)
    238 ; NORMAL-NEXT: call
    239 ; NORMAL-NEXT: addl $16, %esp
    240 define void @test9() optsize {
    241 entry:
    242   %p = alloca i32, align 4
    243   call void @good(i32 1, i32 2, i32 3, i32 4)
    244   %0 = ptrtoint i32* %p to i32
    245   call void @good(i32 5, i32 6, i32 7, i32 %0)
    246   ret void
    247 }
    248 
    249 ; We can end up with an indirect call which gets reloaded on the spot.
    250 ; Make sure we reference the correct stack slot - we spill into (%esp)
    251 ; and reload from 16(%esp) due to the pushes.
    252 ; NORMAL-LABEL: test10:
    253 ; NORMAL: movl $_good, [[ALLOC:.*]]
    254 ; NORMAL-NEXT: movl [[ALLOC]], [[EAX:%e..]]
    255 ; NORMAL-NEXT: movl [[EAX]], (%esp) # 4-byte Spill
    256 ; NORMAL: nop
    257 ; NORMAL: pushl $4
    258 ; NORMAL-NEXT: pushl $3
    259 ; NORMAL-NEXT: pushl $2
    260 ; NORMAL-NEXT: pushl $1
    261 ; NORMAL-NEXT: calll *16(%esp)
    262 ; NORMAL-NEXT: addl $16, %esp
    263 define void @test10() optsize {
    264   %stack_fptr = alloca void (i32, i32, i32, i32)*
    265   store void (i32, i32, i32, i32)* @good, void (i32, i32, i32, i32)** %stack_fptr
    266   %good_ptr = load volatile void (i32, i32, i32, i32)*, void (i32, i32, i32, i32)** %stack_fptr
    267   call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di}"()
    268   call void (i32, i32, i32, i32) %good_ptr(i32 1, i32 2, i32 3, i32 4)
    269   ret void
    270 }
    271 
    272 ; We can't fold the load from the global into the push because of 
    273 ; interference from the store
    274 ; NORMAL-LABEL: test11:
    275 ; NORMAL: movl    _the_global, [[EAX:%e..]]
    276 ; NORMAL-NEXT: movl    $42, _the_global
    277 ; NORMAL-NEXT: pushl $4
    278 ; NORMAL-NEXT: pushl $3
    279 ; NORMAL-NEXT: pushl $2
    280 ; NORMAL-NEXT: pushl [[EAX]]
    281 ; NORMAL-NEXT: call
    282 ; NORMAL-NEXT: addl $16, %esp
    283 @the_global = external global i32
    284 define void @test11() optsize {
    285   %myload = load i32, i32* @the_global
    286   store i32 42, i32* @the_global
    287   call void @good(i32 %myload, i32 2, i32 3, i32 4)
    288   ret void
    289 }
    290 
    291 ; Converting one mov into a push isn't worth it when 
    292 ; doing so forces too much overhead for other calls.
    293 ; NORMAL-LABEL: test12:
    294 ; NORMAL: subl    $16, %esp
    295 ; NORMAL-NEXT: movl    $4, 8(%esp)
    296 ; NORMAL-NEXT: movl    $3, 4(%esp)
    297 ; NORMAL-NEXT: movl    $1, (%esp)
    298 ; NORMAL-NEXT: movl    $2, %eax
    299 ; NORMAL-NEXT: calll _inreg
    300 ; NORMAL-NEXT: movl    $8, 12(%esp)
    301 ; NORMAL-NEXT: movl    $7, 8(%esp)
    302 ; NORMAL-NEXT: movl    $6, 4(%esp)
    303 ; NORMAL-NEXT: movl    $5, (%esp)
    304 ; NORMAL-NEXT: calll _good
    305 ; NORMAL-NEXT: movl    $12, 8(%esp)
    306 ; NORMAL-NEXT: movl    $11, 4(%esp)
    307 ; NORMAL-NEXT: movl    $9, (%esp)
    308 ; NORMAL-NEXT: movl    $10, %eax
    309 ; NORMAL-NEXT: calll _inreg
    310 ; NORMAL-NEXT: addl $16, %esp
    311 define void @test12() optsize {
    312 entry:
    313   call void @inreg(i32 1, i32 2, i32 3, i32 4)
    314   call void @good(i32 5, i32 6, i32 7, i32 8)
    315   call void @inreg(i32 9, i32 10, i32 11, i32 12)
    316   ret void
    317 }
    318 
    319 ; But if the gains outweigh the overhead, we should do it
    320 ; NORMAL-LABEL: test12b:
    321 ; NORMAL: pushl    $4
    322 ; NORMAL-NEXT: pushl    $3
    323 ; NORMAL-NEXT: pushl    $2
    324 ; NORMAL-NEXT: pushl    $1
    325 ; NORMAL-NEXT: calll _good
    326 ; NORMAL-NEXT: addl    $16, %esp
    327 ; NORMAL-NEXT: subl    $12, %esp
    328 ; NORMAL-NEXT: movl    $8, 8(%esp)
    329 ; NORMAL-NEXT: movl    $7, 4(%esp)
    330 ; NORMAL-NEXT: movl    $5, (%esp)
    331 ; NORMAL-NEXT: movl    $6, %eax
    332 ; NORMAL-NEXT: calll _inreg
    333 ; NORMAL-NEXT: addl    $12, %esp
    334 ; NORMAL-NEXT: pushl    $12
    335 ; NORMAL-NEXT: pushl    $11
    336 ; NORMAL-NEXT: pushl    $10
    337 ; NORMAL-NEXT: pushl    $9
    338 ; NORMAL-NEXT: calll _good
    339 ; NORMAL-NEXT: addl $16, %esp
    340 define void @test12b() optsize {
    341 entry:
    342   call void @good(i32 1, i32 2, i32 3, i32 4)
    343   call void @inreg(i32 5, i32 6, i32 7, i32 8)
    344   call void @good(i32 9, i32 10, i32 11, i32 12)
    345   ret void
    346 }
    347