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