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