Home | History | Annotate | Download | only in X86
      1 ; RUN: llc -mtriple=i686-windows < %s | FileCheck %s
      2 
      3 declare void @addrof_i1(i1*)
      4 declare void @addrof_i32(i32*)
      5 declare void @addrof_i64(i64*)
      6 declare void @addrof_i128(i128*)
      7 declare void @addrof_i32_x3(i32*, i32*, i32*)
      8 
      9 define void @simple(i32 %x) {
     10 entry:
     11   %x.addr = alloca i32
     12   store i32 %x, i32* %x.addr
     13   call void @addrof_i32(i32* %x.addr)
     14   ret void
     15 }
     16 
     17 ; CHECK-LABEL: _simple:
     18 ; CHECK: leal 4(%esp), %[[reg:[^ ]*]]
     19 ; CHECK: pushl %[[reg]]
     20 ; CHECK: calll _addrof_i32
     21 ; CHECK: retl
     22 
     23 
     24 ; We need to load %x before calling addrof_i32 now because it could mutate %x in
     25 ; place.
     26 
     27 define i32 @use_arg(i32 %x) {
     28 entry:
     29   %x.addr = alloca i32
     30   store i32 %x, i32* %x.addr
     31   call void @addrof_i32(i32* %x.addr)
     32   ret i32 %x
     33 }
     34 
     35 ; CHECK-LABEL: _use_arg:
     36 ; CHECK: pushl %[[csr:[^ ]*]]
     37 ; CHECK-DAG: movl 8(%esp), %[[csr]]
     38 ; CHECK-DAG: leal 8(%esp), %[[reg:[^ ]*]]
     39 ; CHECK: pushl %[[reg]]
     40 ; CHECK: calll _addrof_i32
     41 ; CHECK: movl %[[csr]], %eax
     42 ; CHECK: popl %[[csr]]
     43 ; CHECK: retl
     44 
     45 ; We won't copy elide for types needing legalization such as i64 or i1.
     46 
     47 define i64 @split_i64(i64 %x) {
     48 entry:
     49   %x.addr = alloca i64, align 4
     50   store i64 %x, i64* %x.addr, align 4
     51   call void @addrof_i64(i64* %x.addr)
     52   ret i64 %x
     53 }
     54 
     55 ; CHECK-LABEL: _split_i64:
     56 ; CHECK: pushl %ebp
     57 ; CHECK: movl %esp, %ebp
     58 ; CHECK: pushl %[[csr2:[^ ]*]]
     59 ; CHECK: pushl %[[csr1:[^ ]*]]
     60 ; CHECK: andl $-8, %esp
     61 ; CHECK-DAG: movl 8(%ebp), %[[csr1]]
     62 ; CHECK-DAG: movl 12(%ebp), %[[csr2]]
     63 ; CHECK-DAG: leal 8(%ebp), %[[reg:[^ ]*]]
     64 ; CHECK: pushl %[[reg]]
     65 ; CHECK: calll _addrof_i64
     66 ; CHECK-DAG: movl %[[csr1]], %eax
     67 ; CHECK-DAG: movl %[[csr2]], %edx
     68 ; CHECK: leal -8(%ebp), %esp
     69 ; CHECK: popl %[[csr1]]
     70 ; CHECK: popl %[[csr2]]
     71 ; CHECK: popl %ebp
     72 ; CHECK: retl
     73 
     74 define i1 @i1_arg(i1 %x) {
     75   %x.addr = alloca i1
     76   store i1 %x, i1* %x.addr
     77   call void @addrof_i1(i1* %x.addr)
     78   ret i1 %x
     79 }
     80 
     81 ; CHECK-LABEL: _i1_arg:
     82 ; CHECK: pushl   %ebx
     83 ; CHECK: movb 8(%esp), %bl
     84 ; CHECK: leal 8(%esp), %eax
     85 ; CHECK: pushl %eax
     86 ; CHECK: calll _addrof_i1
     87 ; CHECK: addl $4, %esp
     88 ; CHECK: movl %ebx, %eax
     89 ; CHECK: popl %ebx
     90 ; CHECK: retl
     91 
     92 ; We can't copy elide when an i64 is split between registers and memory in a
     93 ; fastcc function.
     94 
     95 define fastcc i64 @fastcc_split_i64(i64* %p, i64 %x) {
     96 entry:
     97   %x.addr = alloca i64, align 4
     98   store i64 %x, i64* %x.addr, align 4
     99   call void @addrof_i64(i64* %x.addr)
    100   ret i64 %x
    101 }
    102 
    103 ; CHECK-LABEL: _fastcc_split_i64:
    104 ; CHECK: pushl %ebp
    105 ; CHECK: movl %esp, %ebp
    106 ; CHECK-DAG: movl %edx, %[[r1:[^ ]*]]
    107 ; CHECK-DAG: movl 8(%ebp), %[[r2:[^ ]*]]
    108 ; CHECK-DAG: movl %[[r2]], 4(%esp)
    109 ; CHECK-DAG: movl %edx, (%esp)
    110 ; CHECK: movl %esp, %[[reg:[^ ]*]]
    111 ; CHECK: pushl %[[reg]]
    112 ; CHECK: calll _addrof_i64
    113 ; CHECK: popl %ebp
    114 ; CHECK: retl
    115 
    116 
    117 ; We can't copy elide when it would reduce the user requested alignment.
    118 
    119 define void @high_alignment(i32 %x) {
    120 entry:
    121   %x.p = alloca i32, align 128
    122   store i32 %x, i32* %x.p
    123   call void @addrof_i32(i32* %x.p)
    124   ret void
    125 }
    126 
    127 ; CHECK-LABEL: _high_alignment:
    128 ; CHECK: andl $-128, %esp
    129 ; CHECK: movl 8(%ebp), %[[reg:[^ ]*]]
    130 ; CHECK: movl %[[reg]], (%esp)
    131 ; CHECK: movl %esp, %[[reg:[^ ]*]]
    132 ; CHECK: pushl %[[reg]]
    133 ; CHECK: calll _addrof_i32
    134 ; CHECK: retl
    135 
    136 
    137 ; We can't copy elide when it would reduce the ABI required alignment.
    138 ; FIXME: We should lower the ABI alignment of i64 on Windows, since MSVC
    139 ; doesn't guarantee it.
    140 
    141 define void @abi_alignment(i64 %x) {
    142 entry:
    143   %x.p = alloca i64
    144   store i64 %x, i64* %x.p
    145   call void @addrof_i64(i64* %x.p)
    146   ret void
    147 }
    148 
    149 ; CHECK-LABEL: _abi_alignment:
    150 ; CHECK: andl $-8, %esp
    151 ; CHECK: movl 8(%ebp), %[[reg:[^ ]*]]
    152 ; CHECK: movl %[[reg]], (%esp)
    153 ; CHECK: movl %esp, %[[reg:[^ ]*]]
    154 ; CHECK: pushl %[[reg]]
    155 ; CHECK: calll _addrof_i64
    156 ; CHECK: retl
    157 
    158 
    159 ; The code we generate for this is unimportant. This is mostly a crash test.
    160 
    161 define void @split_i128(i128* %sret, i128 %x) {
    162 entry:
    163   %x.addr = alloca i128
    164   store i128 %x, i128* %x.addr
    165   call void @addrof_i128(i128* %x.addr)
    166   store i128 %x, i128* %sret
    167   ret void
    168 }
    169 
    170 ; CHECK-LABEL: _split_i128:
    171 ; CHECK: pushl %ebp
    172 ; CHECK: calll _addrof_i128
    173 ; CHECK: retl
    174 
    175 
    176 ; Check that we load all of x, y, and z before the call.
    177 
    178 define i32 @three_args(i32 %x, i32 %y, i32 %z) {
    179 entry:
    180   %z.addr = alloca i32, align 4
    181   %y.addr = alloca i32, align 4
    182   %x.addr = alloca i32, align 4
    183   store i32 %z, i32* %z.addr, align 4
    184   store i32 %y, i32* %y.addr, align 4
    185   store i32 %x, i32* %x.addr, align 4
    186   call void @addrof_i32_x3(i32* %x.addr, i32* %y.addr, i32* %z.addr)
    187   %s1 = add i32 %x, %y
    188   %sum = add i32 %s1, %z
    189   ret i32 %sum
    190 }
    191 
    192 ; CHECK-LABEL: _three_args:
    193 ; CHECK: pushl %[[csr:[^ ]*]]
    194 ; CHECK-DAG: movl {{[0-9]+}}(%esp), %[[csr]]
    195 ; CHECK-DAG: addl {{[0-9]+}}(%esp), %[[csr]]
    196 ; CHECK-DAG: addl {{[0-9]+}}(%esp), %[[csr]]
    197 ; CHECK-DAG: leal 8(%esp), %[[x:[^ ]*]]
    198 ; CHECK-DAG: leal 12(%esp), %[[y:[^ ]*]]
    199 ; CHECK-DAG: leal 16(%esp), %[[z:[^ ]*]]
    200 ; CHECK: pushl %[[z]]
    201 ; CHECK: pushl %[[y]]
    202 ; CHECK: pushl %[[x]]
    203 ; CHECK: calll _addrof_i32_x3
    204 ; CHECK: movl %[[csr]], %eax
    205 ; CHECK: popl %[[csr]]
    206 ; CHECK: retl
    207 
    208 
    209 define void @two_args_same_alloca(i32 %x, i32 %y) {
    210 entry:
    211   %x.addr = alloca i32
    212   store i32 %x, i32* %x.addr
    213   store i32 %y, i32* %x.addr
    214   call void @addrof_i32(i32* %x.addr)
    215   ret void
    216 }
    217 
    218 ; CHECK-LABEL: _two_args_same_alloca:
    219 ; CHECK: movl 8(%esp), {{.*}}
    220 ; CHECK: movl {{.*}}, 4(%esp)
    221 ; CHECK: leal 4(%esp), %[[reg:[^ ]*]]
    222 ; CHECK: pushl %[[reg]]
    223 ; CHECK: calll _addrof_i32
    224 ; CHECK: retl
    225 
    226 
    227 define void @avoid_byval(i32* byval %x) {
    228 entry:
    229   %x.p.p = alloca i32*
    230   store i32* %x, i32** %x.p.p
    231   call void @addrof_i32(i32* %x)
    232   ret void
    233 }
    234 
    235 ; CHECK-LABEL: _avoid_byval:
    236 ; CHECK: leal {{[0-9]+}}(%esp), %[[reg:[^ ]*]]
    237 ; CHECK: pushl %[[reg]]
    238 ; CHECK: calll _addrof_i32
    239 ; CHECK: retl
    240 
    241 
    242 define void @avoid_inalloca(i32* inalloca %x) {
    243 entry:
    244   %x.p.p = alloca i32*
    245   store i32* %x, i32** %x.p.p
    246   call void @addrof_i32(i32* %x)
    247   ret void
    248 }
    249 
    250 ; CHECK-LABEL: _avoid_inalloca:
    251 ; CHECK: leal {{[0-9]+}}(%esp), %[[reg:[^ ]*]]
    252 ; CHECK: pushl %[[reg]]
    253 ; CHECK: calll _addrof_i32
    254 ; CHECK: retl
    255 
    256 ; Don't elide the copy when the alloca is escaped with a store.
    257 define void @escape_with_store(i32 %x) {
    258   %x1 = alloca i32
    259   %x2 = alloca i32*
    260   store i32* %x1, i32** %x2
    261   %x3 = load i32*, i32** %x2
    262   store i32 0, i32* %x3
    263   store i32 %x, i32* %x1
    264   call void @addrof_i32(i32* %x1)
    265   ret void
    266 }
    267 
    268 ; CHECK-LABEL: _escape_with_store:
    269 ; CHECK: movl {{.*}}(%esp), %[[reg:[^ ]*]]
    270 ; CHECK: movl %[[reg]], [[offs:[0-9]*]](%esp)
    271 ; CHECK: calll _addrof_i32
    272 
    273 
    274 ; This test case exposed issues with the use of TokenFactor.
    275 
    276 define void @sret_and_elide(i32* sret %sret, i32 %v) {
    277   %v.p = alloca i32
    278   store i32 %v, i32* %v.p
    279   call void @addrof_i32(i32* %v.p)
    280   store i32 %v, i32* %sret
    281   ret void
    282 }
    283 
    284 ; CHECK-LABEL: _sret_and_elide:
    285 ; CHECK: pushl
    286 ; CHECK: pushl
    287 ; CHECK: movl 12(%esp), %[[sret:[^ ]*]]
    288 ; CHECK: movl 16(%esp), %[[v:[^ ]*]]
    289 ; CHECK: leal 16(%esp), %[[reg:[^ ]*]]
    290 ; CHECK: pushl %[[reg]]
    291 ; CHECK: calll _addrof_i32
    292 ; CHECK: movl %[[v]], (%[[sret]])
    293 ; CHECK: movl %[[sret]], %eax
    294 ; CHECK: popl
    295 ; CHECK: popl
    296 ; CHECK: retl
    297