422 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=i686-windows < %s | FileCheck %s3 4declare void @addrof_i1(ptr)5declare void @addrof_i32(ptr)6declare void @addrof_i64(ptr)7declare void @addrof_i128(ptr)8declare void @addrof_i32_x3(ptr, ptr, ptr)9 10define void @simple(i32 %x) {11; CHECK-LABEL: simple:12; CHECK: # %bb.0: # %entry13; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax14; CHECK-NEXT: pushl %eax15; CHECK-NEXT: calll _addrof_i3216; CHECK-NEXT: addl $4, %esp17; CHECK-NEXT: retl18entry:19 %x.addr = alloca i3220 store i32 %x, ptr %x.addr21 call void @addrof_i32(ptr %x.addr)22 ret void23}24 25; We need to load %x before calling addrof_i32 now because it could mutate %x in26; place.27 28define i32 @use_arg(i32 %x) {29; CHECK-LABEL: use_arg:30; CHECK: # %bb.0: # %entry31; CHECK-NEXT: pushl %esi32; CHECK-NEXT: movl {{[0-9]+}}(%esp), %esi33; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax34; CHECK-NEXT: pushl %eax35; CHECK-NEXT: calll _addrof_i3236; CHECK-NEXT: addl $4, %esp37; CHECK-NEXT: movl %esi, %eax38; CHECK-NEXT: popl %esi39; CHECK-NEXT: retl40entry:41 %x.addr = alloca i3242 store i32 %x, ptr %x.addr43 call void @addrof_i32(ptr %x.addr)44 ret i32 %x45}46 47; We won't copy elide for types needing legalization such as i64 or i1.48 49define i64 @split_i64(i64 %x) {50; CHECK-LABEL: split_i64:51; CHECK: # %bb.0: # %entry52; CHECK-NEXT: pushl %edi53; CHECK-NEXT: pushl %esi54; CHECK-NEXT: movl {{[0-9]+}}(%esp), %esi55; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edi56; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax57; CHECK-NEXT: pushl %eax58; CHECK-NEXT: calll _addrof_i6459; CHECK-NEXT: addl $4, %esp60; CHECK-NEXT: movl %esi, %eax61; CHECK-NEXT: movl %edi, %edx62; CHECK-NEXT: popl %esi63; CHECK-NEXT: popl %edi64; CHECK-NEXT: retl65entry:66 %x.addr = alloca i64, align 467 store i64 %x, ptr %x.addr, align 468 call void @addrof_i64(ptr %x.addr)69 ret i64 %x70}71 72define i1 @i1_arg(i1 %x) {73; CHECK-LABEL: i1_arg:74; CHECK: # %bb.0:75; CHECK-NEXT: pushl %ebx76; CHECK-NEXT: pushl %eax77; CHECK-NEXT: movzbl {{[0-9]+}}(%esp), %ebx78; CHECK-NEXT: movl %ebx, %eax79; CHECK-NEXT: andb $1, %al80; CHECK-NEXT: movb %al, {{[0-9]+}}(%esp)81; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax82; CHECK-NEXT: pushl %eax83; CHECK-NEXT: calll _addrof_i184; CHECK-NEXT: addl $4, %esp85; CHECK-NEXT: movl %ebx, %eax86; CHECK-NEXT: addl $4, %esp87; CHECK-NEXT: popl %ebx88; CHECK-NEXT: retl89 %x.addr = alloca i190 store i1 %x, ptr %x.addr91 call void @addrof_i1(ptr %x.addr)92 ret i1 %x93}94 95; We can't copy elide when an i64 is split between registers and memory in a96; fastcc function.97 98define fastcc i64 @fastcc_split_i64(ptr %p, i64 %x) {99; CHECK-LABEL: fastcc_split_i64:100; CHECK: # %bb.0: # %entry101; CHECK-NEXT: pushl %edi102; CHECK-NEXT: pushl %esi103; CHECK-NEXT: subl $8, %esp104; CHECK-NEXT: movl %edx, %esi105; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edi106; CHECK-NEXT: movl %edi, {{[0-9]+}}(%esp)107; CHECK-NEXT: movl %edx, (%esp)108; CHECK-NEXT: movl %esp, %eax109; CHECK-NEXT: pushl %eax110; CHECK-NEXT: calll _addrof_i64111; CHECK-NEXT: addl $4, %esp112; CHECK-NEXT: movl %esi, %eax113; CHECK-NEXT: movl %edi, %edx114; CHECK-NEXT: addl $8, %esp115; CHECK-NEXT: popl %esi116; CHECK-NEXT: popl %edi117; CHECK-NEXT: retl118entry:119 %x.addr = alloca i64, align 4120 store i64 %x, ptr %x.addr, align 4121 call void @addrof_i64(ptr %x.addr)122 ret i64 %x123}124 125; We can't copy elide when it would reduce the user requested alignment.126 127define void @high_alignment(i32 %x) {128; CHECK-LABEL: high_alignment:129; CHECK: # %bb.0: # %entry130; CHECK-NEXT: pushl %ebp131; CHECK-NEXT: movl %esp, %ebp132; CHECK-NEXT: andl $-128, %esp133; CHECK-NEXT: subl $128, %esp134; CHECK-NEXT: movl 8(%ebp), %eax135; CHECK-NEXT: movl %eax, (%esp)136; CHECK-NEXT: movl %esp, %eax137; CHECK-NEXT: pushl %eax138; CHECK-NEXT: calll _addrof_i32139; CHECK-NEXT: addl $4, %esp140; CHECK-NEXT: movl %ebp, %esp141; CHECK-NEXT: popl %ebp142; CHECK-NEXT: retl143entry:144 %x.p = alloca i32, align 128145 store i32 %x, ptr %x.p146 call void @addrof_i32(ptr %x.p)147 ret void148}149 150; We can't copy elide when it would reduce the ABI required alignment.151; FIXME: We should lower the ABI alignment of i64 on Windows, since MSVC152; doesn't guarantee it.153 154define void @abi_alignment(i64 %x) {155; CHECK-LABEL: abi_alignment:156; CHECK: # %bb.0: # %entry157; CHECK-NEXT: pushl %ebp158; CHECK-NEXT: movl %esp, %ebp159; CHECK-NEXT: andl $-8, %esp160; CHECK-NEXT: subl $8, %esp161; CHECK-NEXT: movl 8(%ebp), %eax162; CHECK-NEXT: movl 12(%ebp), %ecx163; CHECK-NEXT: movl %ecx, {{[0-9]+}}(%esp)164; CHECK-NEXT: movl %eax, (%esp)165; CHECK-NEXT: movl %esp, %eax166; CHECK-NEXT: pushl %eax167; CHECK-NEXT: calll _addrof_i64168; CHECK-NEXT: addl $4, %esp169; CHECK-NEXT: movl %ebp, %esp170; CHECK-NEXT: popl %ebp171; CHECK-NEXT: retl172entry:173 %x.p = alloca i64174 store i64 %x, ptr %x.p175 call void @addrof_i64(ptr %x.p)176 ret void177}178 179; The code we generate for this is unimportant. This is mostly a crash test.180 181define void @split_i128(ptr %sret, i128 %x) {182; CHECK-LABEL: split_i128:183; CHECK: # %bb.0: # %entry184; CHECK-NEXT: pushl %ebp185; CHECK-NEXT: movl %esp, %ebp186; CHECK-NEXT: pushl %ebx187; CHECK-NEXT: pushl %edi188; CHECK-NEXT: pushl %esi189; CHECK-NEXT: andl $-16, %esp190; CHECK-NEXT: subl $48, %esp191; CHECK-NEXT: movl 24(%ebp), %eax192; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill193; CHECK-NEXT: movl 28(%ebp), %ebx194; CHECK-NEXT: movl 32(%ebp), %esi195; CHECK-NEXT: movl 36(%ebp), %edi196; CHECK-NEXT: movl %edi, {{[0-9]+}}(%esp)197; CHECK-NEXT: movl %esi, {{[0-9]+}}(%esp)198; CHECK-NEXT: movl %ebx, {{[0-9]+}}(%esp)199; CHECK-NEXT: movl %eax, {{[0-9]+}}(%esp)200; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax201; CHECK-NEXT: pushl %eax202; CHECK-NEXT: calll _addrof_i128203; CHECK-NEXT: addl $4, %esp204; CHECK-NEXT: movl 8(%ebp), %eax205; CHECK-NEXT: movl %edi, 12(%eax)206; CHECK-NEXT: movl %esi, 8(%eax)207; CHECK-NEXT: movl %ebx, 4(%eax)208; CHECK-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload209; CHECK-NEXT: movl %ecx, (%eax)210; CHECK-NEXT: leal -12(%ebp), %esp211; CHECK-NEXT: popl %esi212; CHECK-NEXT: popl %edi213; CHECK-NEXT: popl %ebx214; CHECK-NEXT: popl %ebp215; CHECK-NEXT: retl216entry:217 %x.addr = alloca i128218 store i128 %x, ptr %x.addr219 call void @addrof_i128(ptr %x.addr)220 store i128 %x, ptr %sret221 ret void222}223 224; Check that we load all of x, y, and z before the call.225 226define i32 @three_args(i32 %x, i32 %y, i32 %z) {227; CHECK-LABEL: three_args:228; CHECK: # %bb.0: # %entry229; CHECK-NEXT: pushl %esi230; CHECK-NEXT: movl {{[0-9]+}}(%esp), %esi231; CHECK-NEXT: addl {{[0-9]+}}(%esp), %esi232; CHECK-NEXT: addl {{[0-9]+}}(%esp), %esi233; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax234; CHECK-NEXT: leal {{[0-9]+}}(%esp), %ecx235; CHECK-NEXT: leal {{[0-9]+}}(%esp), %edx236; CHECK-NEXT: pushl %eax237; CHECK-NEXT: pushl %ecx238; CHECK-NEXT: pushl %edx239; CHECK-NEXT: calll _addrof_i32_x3240; CHECK-NEXT: addl $12, %esp241; CHECK-NEXT: movl %esi, %eax242; CHECK-NEXT: popl %esi243; CHECK-NEXT: retl244entry:245 %z.addr = alloca i32, align 4246 %y.addr = alloca i32, align 4247 %x.addr = alloca i32, align 4248 store i32 %z, ptr %z.addr, align 4249 store i32 %y, ptr %y.addr, align 4250 store i32 %x, ptr %x.addr, align 4251 call void @addrof_i32_x3(ptr %x.addr, ptr %y.addr, ptr %z.addr)252 %s1 = add i32 %x, %y253 %sum = add i32 %s1, %z254 ret i32 %sum255}256 257define void @two_args_same_alloca(i32 %x, i32 %y) {258; CHECK-LABEL: two_args_same_alloca:259; CHECK: # %bb.0: # %entry260; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax261; CHECK-NEXT: movl %eax, {{[0-9]+}}(%esp)262; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax263; CHECK-NEXT: pushl %eax264; CHECK-NEXT: calll _addrof_i32265; CHECK-NEXT: addl $4, %esp266; CHECK-NEXT: retl267entry:268 %x.addr = alloca i32269 store i32 %x, ptr %x.addr270 store i32 %y, ptr %x.addr271 call void @addrof_i32(ptr %x.addr)272 ret void273}274 275define void @avoid_byval(ptr byval(i32) %x) {276; CHECK-LABEL: avoid_byval:277; CHECK: # %bb.0: # %entry278; CHECK-NEXT: pushl %eax279; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax280; CHECK-NEXT: movl %eax, (%esp)281; CHECK-NEXT: pushl %eax282; CHECK-NEXT: calll _addrof_i32283; CHECK-NEXT: addl $4, %esp284; CHECK-NEXT: popl %eax285; CHECK-NEXT: retl286entry:287 %x.p.p = alloca ptr288 store ptr %x, ptr %x.p.p289 call void @addrof_i32(ptr %x)290 ret void291}292 293define void @avoid_inalloca(ptr inalloca(i32) %x) {294; CHECK-LABEL: avoid_inalloca:295; CHECK: # %bb.0: # %entry296; CHECK-NEXT: pushl %eax297; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax298; CHECK-NEXT: movl %eax, (%esp)299; CHECK-NEXT: pushl %eax300; CHECK-NEXT: calll _addrof_i32301; CHECK-NEXT: addl $4, %esp302; CHECK-NEXT: popl %eax303; CHECK-NEXT: retl304entry:305 %x.p.p = alloca ptr306 store ptr %x, ptr %x.p.p307 call void @addrof_i32(ptr %x)308 ret void309}310 311define void @avoid_preallocated(ptr preallocated(i32) %x) {312; CHECK-LABEL: avoid_preallocated:313; CHECK: # %bb.0: # %entry314; CHECK-NEXT: pushl %eax315; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax316; CHECK-NEXT: movl %eax, (%esp)317; CHECK-NEXT: pushl %eax318; CHECK-NEXT: calll _addrof_i32319; CHECK-NEXT: addl $4, %esp320; CHECK-NEXT: popl %eax321; CHECK-NEXT: retl322entry:323 %x.p.p = alloca ptr324 store ptr %x, ptr %x.p.p325 call void @addrof_i32(ptr %x)326 ret void327}328 329; Don't elide the copy when the alloca is escaped with a store.330define void @escape_with_store(i32 %x) {331; CHECK-LABEL: escape_with_store:332; CHECK: # %bb.0:333; CHECK-NEXT: subl $8, %esp334; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax335; CHECK-NEXT: movl %esp, %ecx336; CHECK-NEXT: movl %ecx, {{[0-9]+}}(%esp)337; CHECK-NEXT: movl %eax, (%esp)338; CHECK-NEXT: pushl %ecx339; CHECK-NEXT: calll _addrof_i32340; CHECK-NEXT: addl $12, %esp341; CHECK-NEXT: retl342 %x1 = alloca i32343 %x2 = alloca ptr344 store ptr %x1, ptr %x2345 %x3 = load ptr, ptr %x2346 store i32 0, ptr %x3347 store i32 %x, ptr %x1348 call void @addrof_i32(ptr %x1)349 ret void350}351 352; This test case exposed issues with the use of TokenFactor.353 354define void @sret_and_elide(ptr sret(i32) %sret, i32 %v) {355; CHECK-LABEL: sret_and_elide:356; CHECK: # %bb.0:357; CHECK-NEXT: pushl %edi358; CHECK-NEXT: pushl %esi359; CHECK-NEXT: movl {{[0-9]+}}(%esp), %esi360; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edi361; CHECK-NEXT: leal {{[0-9]+}}(%esp), %eax362; CHECK-NEXT: pushl %eax363; CHECK-NEXT: calll _addrof_i32364; CHECK-NEXT: addl $4, %esp365; CHECK-NEXT: movl %edi, (%esi)366; CHECK-NEXT: movl %esi, %eax367; CHECK-NEXT: popl %esi368; CHECK-NEXT: popl %edi369; CHECK-NEXT: retl370 %v.p = alloca i32371 store i32 %v, ptr %v.p372 call void @addrof_i32(ptr %v.p)373 store i32 %v, ptr %sret374 ret void375}376 377define void @avoid_partially_initialized_alloca(i32 %x) {378; CHECK-LABEL: avoid_partially_initialized_alloca:379; CHECK: # %bb.0:380; CHECK-NEXT: pushl %ebp381; CHECK-NEXT: movl %esp, %ebp382; CHECK-NEXT: andl $-8, %esp383; CHECK-NEXT: subl $8, %esp384; CHECK-NEXT: movl 8(%ebp), %eax385; CHECK-NEXT: movl %eax, (%esp)386; CHECK-NEXT: movl %esp, %eax387; CHECK-NEXT: pushl %eax388; CHECK-NEXT: calll _addrof_i32389; CHECK-NEXT: addl $4, %esp390; CHECK-NEXT: movl %ebp, %esp391; CHECK-NEXT: popl %ebp392; CHECK-NEXT: retl393 %a = alloca i64394 store i32 %x, ptr %a395 call void @addrof_i32(ptr %a)396 ret void397}398 399; Ensure no copy elision happens as the two i3 values fed into icmp may have400; garbage in the upper bits, a truncation is needed.401 402define i1 @use_i3(i3 %a1, i3 %a2) {403; CHECK-LABEL: use_i3:404; CHECK: # %bb.0:405; CHECK-NEXT: pushl %eax406; CHECK-NEXT: movzbl {{[0-9]+}}(%esp), %eax407; CHECK-NEXT: andb $7, %al408; CHECK-NEXT: movzbl {{[0-9]+}}(%esp), %ecx409; CHECK-NEXT: andb $7, %cl410; CHECK-NEXT: movb %cl, {{[0-9]+}}(%esp)411; CHECK-NEXT: cmpb %cl, %al412; CHECK-NEXT: sete %al413; CHECK-NEXT: popl %ecx414; CHECK-NEXT: retl415 %tmp = alloca i3416 store i3 %a2, ptr %tmp417 %val = load i3, ptr %tmp418 %res = icmp eq i3 %a1, %val419 ret i1 %res420}421 422