brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.3 KiB · 22929fa Raw
488 lines · plain
1; RUN: llc < %s -mtriple=i686-windows | FileCheck %s -check-prefix=NORMAL2; RUN: llc < %s -mtriple=i686-windows -no-x86-call-frame-opt | FileCheck %s -check-prefix=NOPUSH3; RUN: llc < %s -mtriple=x86_64-windows | FileCheck %s -check-prefix=X644; RUN: llc < %s -mtriple=x86_64-uefi | FileCheck %s -check-prefix=X645; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s -check-prefix=LINUX6 7%class.Class = type { i32 }8%struct.s = type { i64 }9 10declare void @good(i32 %a, i32 %b, i32 %c, i32 %d)11declare void @inreg(i32 %a, i32 inreg %b, i32 %c, i32 %d)12declare x86_thiscallcc void @thiscall(ptr %class, i32 %a, i32 %b, i32 %c, i32 %d)13declare void @oneparam(i32 %a)14declare void @eightparams(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h)15declare void @eightparams16(i16 %a, i16 %b, i16 %c, i16 %d, i16 %e, i16 %f, i16 %g, i16 %h)16declare void @eightparams64(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i64 %g, i64 %h)17declare void @struct(ptr byval(%struct.s) %a, i32 %b, i32 %c, i32 %d)18declare void @inalloca(ptr inalloca(<{ %struct.s }>))19 20declare ptr @llvm.stacksave()21declare void @llvm.stackrestore(ptr)22 23; We should get pushes for x86, even though there is a reserved call frame.24; Make sure we don't touch x86-64, and that turning it off works.25; NORMAL-LABEL: test1:26; NORMAL-NOT: subl {{.*}} %esp27; NORMAL: pushl   $428; NORMAL-NEXT: pushl   $329; NORMAL-NEXT: pushl   $230; NORMAL-NEXT: pushl   $131; NORMAL-NEXT: call32; NORMAL-NEXT: addl $16, %esp33; X64-LABEL: test1:34; X64: movl    $1, %ecx35; X64-NEXT: movl    $2, %edx36; X64-NEXT: movl    $3, %r8d37; X64-NEXT: movl    $4, %r9d38; X64-NEXT: callq   good39; NOPUSH-LABEL: test1:40; NOPUSH: subl    $16, %esp41; NOPUSH-NEXT: movl    $4, 12(%esp)42; NOPUSH-NEXT: movl    $3, 8(%esp)43; NOPUSH-NEXT: movl    $2, 4(%esp)44; NOPUSH-NEXT: movl    $1, (%esp)45; NOPUSH-NEXT: call46; NOPUSH-NEXT: addl $16, %esp47define void @test1() {48entry:49  call void @good(i32 1, i32 2, i32 3, i32 4)50  ret void51}52 53; If we have a reserved frame, we should have pushes54; NORMAL-LABEL: test2:55; NORMAL-NOT: subl {{.*}} %esp56; NORMAL: pushl   $457; NORMAL-NEXT: pushl   $358; NORMAL-NEXT: pushl   $259; NORMAL-NEXT: pushl   $160; NORMAL-NEXT: call61define void @test2(i32 %k) {62entry:63  %a = alloca i32, i32 %k64  call void @good(i32 1, i32 2, i32 3, i32 4)65  ret void66}67 68; Again, we expect a sequence of 4 immediate pushes69; Checks that we generate the right pushes for >8bit immediates70; NORMAL-LABEL: test2b:71; NORMAL-NOT: subl {{.*}} %esp72; NORMAL: pushl   $409673; NORMAL-NEXT: pushl   $307274; NORMAL-NEXT: pushl   $204875; NORMAL-NEXT: pushl   $102476; NORMAL-NEXT: call77; NORMAL-NEXT: addl $16, %esp78define void @test2b() optsize {79entry:80  call void @good(i32 1024, i32 2048, i32 3072, i32 4096)81  ret void82}83 84; The first push should push a register85; NORMAL-LABEL: test3:86; NORMAL-NOT: subl {{.*}} %esp87; NORMAL: pushl   $488; NORMAL-NEXT: pushl   $389; NORMAL-NEXT: pushl   $290; NORMAL-NEXT: pushl   %e{{..}}91; NORMAL-NEXT: call92; NORMAL-NEXT: addl $16, %esp93define void @test3(i32 %k) optsize {94entry:95  %f = add i32 %k, 196  call void @good(i32 %f, i32 2, i32 3, i32 4)97  ret void98}99 100; We support weird calling conventions101; NORMAL-LABEL: test4:102; NORMAL: movl    $2, %eax103; NORMAL-NEXT: pushl   $4104; NORMAL-NEXT: pushl   $3105; NORMAL-NEXT: pushl   $1106; NORMAL-NEXT: call107; NORMAL-NEXT: addl $12, %esp108define void @test4() optsize {109entry:110  call void @inreg(i32 1, i32 inreg 2, i32 3, i32 4)111  ret void112}113 114; NORMAL-LABEL: test4b:115; NORMAL: movl 4(%esp), %ecx116; NORMAL-NEXT: pushl   $4117; NORMAL-NEXT: pushl   $3118; NORMAL-NEXT: pushl   $2119; NORMAL-NEXT: pushl   $1120; NORMAL-NEXT: call121; NORMAL-NEXT: ret122define void @test4b(ptr %f) optsize {123entry:124  call x86_thiscallcc void @thiscall(ptr %f, i32 1, i32 2, i32 3, i32 4)125  ret void126}127 128; Check that pushing the addresses of globals (Or generally, things that129; aren't exactly immediates) isn't broken.130; Fixes PR21878.131; NORMAL-LABEL: test6:132; NORMAL: pushl    $_ext133; NORMAL-NEXT: call134declare void @f(ptr)135@ext = external dso_local constant i8136 137define void @test6() {138  call void @f(ptr @ext)139  br label %bb140bb:141  alloca i32142  ret void143}144 145; Check that we fold simple cases into the push146; NORMAL-LABEL: test7:147; NORMAL-NOT: subl {{.*}} %esp148; NORMAL: movl 4(%esp), [[EAX:%e..]]149; NORMAL-NEXT: pushl   $4150; NORMAL-NEXT: pushl   ([[EAX]])151; NORMAL-NEXT: pushl   $2152; NORMAL-NEXT: pushl   $1153; NORMAL-NEXT: call154; NORMAL-NEXT: addl $16, %esp155define void @test7(ptr %ptr) optsize {156entry:157  %val = load i32, ptr %ptr158  call void @good(i32 1, i32 2, i32 %val, i32 4)159  ret void160}161 162; Fold stack-relative loads into the push, with correct offset163; In particular, at the second push, %b was at 12(%esp) and164; %a wast at 8(%esp), but the second push bumped %esp, so %a165; is now it at 12(%esp)166; NORMAL-LABEL: test8:167; NORMAL: pushl   $4168; NORMAL-NEXT: pushl   12(%esp)169; NORMAL-NEXT: pushl   12(%esp)170; NORMAL-NEXT: pushl   $1171; NORMAL-NEXT: call172; NORMAL-NEXT: addl $16, %esp173define void @test8(i32 %a, i32 %b) optsize {174entry:175  call void @good(i32 1, i32 %a, i32 %b, i32 4)176  ret void177}178 179; If one function is using push instructions, and the other isn't180; (because it has frame-index references), then we must resolve181; these references correctly.182; NORMAL-LABEL: test9:183; NORMAL-NOT: leal (%esp),184; NORMAL: pushl $4185; NORMAL-NEXT: pushl $3186; NORMAL-NEXT: pushl $2187; NORMAL-NEXT: pushl $1188; NORMAL-NEXT: call189; NORMAL-NEXT: addl $16, %esp190; NORMAL-NEXT: movl (%esp), [[E1:%e..]]191; NORMAL-NEXT: movl 4(%esp), [[E2:%e..]]192; NORMAL-NEXT: leal 16(%esp), [[E3:%e..]]193; NORMAL-NEXT: leal 12(%esp), [[E4:%e..]]194; NORMAL-NEXT: pushl   [[E3]]195; NORMAL-NEXT: pushl   [[E4]]196; NORMAL-NEXT: pushl   $6197; NORMAL-NEXT: pushl   [[E2]]198; NORMAL-NEXT: pushl   [[E1]]199; NORMAL-NEXT: call200; NORMAL-NEXT: addl $20, %esp201define void @test9() optsize {202entry:203  %p = alloca i32, align 4204  %q = alloca i32, align 4205  %s = alloca %struct.s, align 8206  call void @good(i32 1, i32 2, i32 3, i32 4)207  %pv = ptrtoint ptr %p to i32208  %qv = ptrtoint ptr %q to i32209  call void @struct(ptr byval(%struct.s) %s, i32 6, i32 %qv, i32 %pv)210  ret void211}212 213; We can end up with an indirect call which gets reloaded on the spot.214; Make sure we reference the correct stack slot - we spill into (%esp)215; and reload from 16(%esp) due to the pushes.216; NORMAL-LABEL: test10:217; NORMAL: movl $_good, [[ALLOC:.*]]218; NORMAL-NEXT: movl [[ALLOC]], [[EAX:%e..]]219; NORMAL-NEXT: movl [[EAX]], (%esp) # 4-byte Spill220; NORMAL: nop221; NORMAL: pushl $4222; NORMAL-NEXT: pushl $3223; NORMAL-NEXT: pushl $2224; NORMAL-NEXT: pushl $1225; NORMAL-NEXT: calll *16(%esp)226; NORMAL-NEXT: addl $24, %esp227define void @test10() optsize {228  %stack_fptr = alloca ptr229  store ptr @good, ptr %stack_fptr230  %good_ptr = load volatile ptr, ptr %stack_fptr231  call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di}"()232  call void (i32, i32, i32, i32) %good_ptr(i32 1, i32 2, i32 3, i32 4)233  ret void234}235 236; We can't fold the load from the global into the push because of237; interference from the store238; NORMAL-LABEL: test11:239; NORMAL: movl    _the_global, [[EAX:%e..]]240; NORMAL-NEXT: movl    $42, _the_global241; NORMAL-NEXT: pushl $4242; NORMAL-NEXT: pushl $3243; NORMAL-NEXT: pushl $2244; NORMAL-NEXT: pushl [[EAX]]245; NORMAL-NEXT: call246; NORMAL-NEXT: addl $16, %esp247@the_global = external dso_local global i32248define void @test11() optsize {249  %myload = load i32, ptr @the_global250  store i32 42, ptr @the_global251  call void @good(i32 %myload, i32 2, i32 3, i32 4)252  ret void253}254 255; Converting one mov into a push isn't worth it when256; doing so forces too much overhead for other calls.257; NORMAL-LABEL: test12:258; NORMAL:       pushl  $8259; NORMAL-NEXT:  pushl  $7260; NORMAL-NEXT:  pushl  $6261; NORMAL-NEXT:  pushl  $5262; NORMAL-NEXT: calll _good263define void @test12() optsize {264entry:265  %s = alloca %struct.s, align 4266  call void @struct(ptr byval(%struct.s) %s, i32 2, i32 3, i32 4)267  call void @good(i32 5, i32 6, i32 7, i32 8)268  call void @struct(ptr byval(%struct.s) %s, i32 10, i32 11, i32 12)269  ret void270}271 272; But if the gains outweigh the overhead, we should do it273; NORMAL-LABEL: test12b:274; NORMAL: pushl    $4275; NORMAL-NEXT: pushl    $3276; NORMAL-NEXT: pushl    $2277; NORMAL-NEXT: pushl    $1278; NORMAL-NEXT: calll _good279; NORMAL-NEXT: addl    $16, %esp280; NORMAL=NEXT: movl  (%esp), %eax281; NORMAL=NEXT: movl  4(%esp), %ecx282; NORMAL=NEXT: pushl  $8283; NORMAL=NEXT: pushl  $7284; NORMAL=NEXT: pushl  $6285; NORMAL=NEXT: pushl  %ecx286; NORMAL=NEXT: pushl  %eax287; NORMAL=NEXT: calll  _struct288; NORMAL=NEXT: addl  $20, %esp289; NORMAL=NEXT: pushl  $12290; NORMAL=NEXT: pushl  $11291; NORMAL=NEXT: pushl  $10292; NORMAL=NEXT: pushl  $9293; NORMAL=NEXT: calll  _good294; NORMAL=NEXT: addl  $16, %esp295define void @test12b() optsize {296entry:297  %s = alloca %struct.s, align 4298  call void @good(i32 1, i32 2, i32 3, i32 4)299  call void @struct(ptr byval(%struct.s) %s, i32 6, i32 7, i32 8)300  call void @good(i32 9, i32 10, i32 11, i32 12)301  ret void302}303 304; Make sure the add does not prevent folding loads into pushes.305; val1 and val2 will not be folded into pushes since they have306; an additional use, but val3 should be.307; NORMAL-LABEL: test13:308; NORMAL: movl ([[P1:%e..]]), [[V1:%e..]]309; NORMAL-NEXT: movl ([[P2:%e..]]), [[V2:%e..]]310; NORMAL-NEXT: , [[ADD:%e..]]311; NORMAL-NEXT: pushl [[ADD]]312; NORMAL-NEXT: pushl ([[P3:%e..]])313; NORMAL-NEXT: pushl [[V2]]314; NORMAL-NEXT: pushl [[V1]]315; NORMAL-NEXT: calll _good316; NORMAL: movl [[P3]], %eax317define ptr @test13(ptr inreg %ptr1, ptr inreg %ptr2, ptr inreg %ptr3) optsize {318entry:319  %val1 = load i32, ptr %ptr1320  %val2 = load i32, ptr %ptr2321  %val3 = load i32, ptr %ptr3322  %add = add i32 %val1, %val2323  call void @good(i32 %val1, i32 %val2, i32 %val3, i32 %add)324  ret ptr %ptr3325}326 327; Make sure to fold adjacent stack adjustments.328; LINUX-LABEL: pr27140:329; LINUX: subl    $12, %esp330; LINUX: .cfi_def_cfa_offset 16331; LINUX-NOT: sub332; LINUX: pushl   $4333; LINUX: .cfi_adjust_cfa_offset 4334; LINUX: pushl   $3335; LINUX: .cfi_adjust_cfa_offset 4336; LINUX: pushl   $2337; LINUX: .cfi_adjust_cfa_offset 4338; LINUX: pushl   $1339; LINUX: .cfi_adjust_cfa_offset 4340; LINUX: calll   good341; LINUX: addl    $28, %esp342; LINUX: .cfi_adjust_cfa_offset -28343; LINUX-NOT: add344; LINUX: retl345define void @pr27140() optsize {346entry:347  tail call void @good(i32 1, i32 2, i32 3, i32 4)348  ret void349}350 351; Check that a stack restore (leal -4(%ebp), %esp) doesn't get merged with a352; stack adjustment (addl $12, %esp). Just because it's a lea doesn't mean it's353; simply decreasing the stack pointer.354; NORMAL-LABEL: test14:355; NORMAL: calll _B_func356; NORMAL: leal -4(%ebp), %esp357; NORMAL-NOT: %esp358; NORMAL: retl359%struct.A = type { i32, i32 }360%struct.B = type { i8 }361declare x86_thiscallcc ptr @B_ctor(ptr returned, ptr byval(%struct.A))362declare void @B_func(ptr sret(%struct.B), ptr, i32)363define void @test14(ptr %a) {364entry:365  %ref.tmp = alloca %struct.B, align 1366  %agg.tmp = alloca i64, align 8367  %tmp = alloca %struct.B, align 1368  %0 = load i64, ptr %a, align 4369  store i64 %0, ptr %agg.tmp, align 4370  %call = call x86_thiscallcc ptr @B_ctor(ptr returned %ref.tmp, ptr byval(%struct.A) %agg.tmp)371  call void @B_func(ptr sret(%struct.B) %tmp, ptr %ref.tmp, i32 1)372  ret void373}374 375; NORMAL-LABEL: pr34863_16376; NORMAL:       movl  4(%esp), %eax377; NORMAL-NEXT:  pushl  $65535378; NORMAL-NEXT:  pushl  $0379; NORMAL-NEXT:  pushl  %eax380; NORMAL-NEXT:  pushl  %eax381; NORMAL-NEXT:  pushl  %eax382; NORMAL-NEXT:  pushl  %eax383; NORMAL-NEXT:  pushl  %eax384; NORMAL-NEXT:  pushl  %eax385; NORMAL-NEXT:  calll  _eightparams16386; NORMAL-NEXT:  addl  $32, %esp387;388; NOPUSH-LABEL: pr34863_16389; NOPUSH:       subl  $32, %esp390; NOPUSH-NEXT:  movl  36(%esp), %eax391; NOPUSH-NEXT:  movl  %eax, 20(%esp)392; NOPUSH-NEXT:  movl  %eax, 16(%esp)393; NOPUSH-NEXT:  movl  %eax, 12(%esp)394; NOPUSH-NEXT:  movl  %eax, 8(%esp)395; NOPUSH-NEXT:  movl  %eax, 4(%esp)396; NOPUSH-NEXT:  movl  %eax, (%esp)397; NOPUSH-NEXT:  movl  $65535, 28(%esp)398; NOPUSH-NEXT:  andl  $0, 24(%esp)399; NOPUSH-NEXT:  calll  _eightparams16400; NOPUSH-NEXT:   addl  $32, %esp401define void @pr34863_16(i16 %x) minsize nounwind {402entry:403  tail call void @eightparams16(i16 %x, i16 %x, i16 %x, i16 %x, i16 %x, i16 %x, i16 0, i16 -1)404  ret void405}406 407; NORMAL-LABEL: pr34863_32408; NORMAL:      movl  4(%esp), %eax409; NORMAL-NEXT: pushl  $-1410; NORMAL-NEXT: pushl  $0411; NORMAL-NEXT: pushl  %eax412; NORMAL-NEXT: pushl  %eax413; NORMAL-NEXT: pushl  %eax414; NORMAL-NEXT: pushl  %eax415; NORMAL-NEXT: pushl  %eax416; NORMAL-NEXT: pushl  %eax417; NORMAL-NEXT: calll  _eightparams418; NORMAL-NEXT: addl  $32, %esp419;420; NOPUSH-LABEL: pr34863_32421; NOPUSH:      subl  $32, %esp422; NOPUSH-NEXT: movl  36(%esp), %eax423; NOPUSH-NEXT: movl  %eax, 20(%esp)424; NOPUSH-NEXT: movl  %eax, 16(%esp)425; NOPUSH-NEXT: movl  %eax, 12(%esp)426; NOPUSH-NEXT: movl  %eax, 8(%esp)427; NOPUSH-NEXT: movl  %eax, 4(%esp)428; NOPUSH-NEXT: movl  %eax, (%esp)429; NOPUSH-NEXT: orl  $-1, 28(%esp)430; NOPUSH-NEXT: andl  $0, 24(%esp)431; NOPUSH-NEXT: calll  _eightparams432; NOPUSH-NEXT: addl  $32, %esp433define void @pr34863_32(i32 %x) minsize nounwind {434entry:435  tail call void @eightparams(i32 %x, i32 %x, i32 %x, i32 %x, i32 %x, i32 %x, i32 0, i32 -1)436  ret void437}438 439; NORMAL-LABEL: pr34863_64440; NORMAL:      movl  4(%esp), %eax441; NORMAL-NEXT: movl  8(%esp), %ecx442; NORMAL-NEXT: pushl  $-1443; NORMAL-NEXT: pushl  $-1444; NORMAL-NEXT: pushl  $0445; NORMAL-NEXT: pushl  $0446; NORMAL-NEXT: pushl  %ecx447; NORMAL-NEXT: pushl  %eax448; NORMAL-NEXT: pushl  %ecx449; NORMAL-NEXT: pushl  %eax450; NORMAL-NEXT: pushl  %ecx451; NORMAL-NEXT: pushl  %eax452; NORMAL-NEXT: pushl  %ecx453; NORMAL-NEXT: pushl  %eax454; NORMAL-NEXT: pushl  %ecx455; NORMAL-NEXT: pushl  %eax456; NORMAL-NEXT: pushl  %ecx457; NORMAL-NEXT: pushl  %eax458; NORMAL-NEXT: calll  _eightparams64459; NORMAL-NEXT: addl  $64, %esp460;461; NOPUSH-LABEL: pr34863_64462; NOPUSH:      subl  $64, %esp463; NOPUSH-NEXT: movl  68(%esp), %eax464; NOPUSH-NEXT: movl  72(%esp), %ecx465; NOPUSH-NEXT: movl  %ecx, 44(%esp)466; NOPUSH-NEXT: movl  %eax, 40(%esp)467; NOPUSH-NEXT: movl  %ecx, 36(%esp)468; NOPUSH-NEXT: movl  %eax, 32(%esp)469; NOPUSH-NEXT: movl  %ecx, 28(%esp)470; NOPUSH-NEXT: movl  %eax, 24(%esp)471; NOPUSH-NEXT: movl  %ecx, 20(%esp)472; NOPUSH-NEXT: movl  %eax, 16(%esp)473; NOPUSH-NEXT: movl  %ecx, 12(%esp)474; NOPUSH-NEXT: movl  %eax, 8(%esp)475; NOPUSH-NEXT: movl  %ecx, 4(%esp)476; NOPUSH-NEXT: movl  %eax, (%esp)477; NOPUSH-NEXT: orl  $-1, 60(%esp)478; NOPUSH-NEXT: orl  $-1, 56(%esp)479; NOPUSH-NEXT: andl  $0, 52(%esp)480; NOPUSH-NEXT: andl  $0, 48(%esp)481; NOPUSH-NEXT: calll  _eightparams64482; NOPUSH-NEXT: addl  $64, %esp483define void @pr34863_64(i64 %x) minsize nounwind {484entry:485  tail call void @eightparams64(i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, i64 0, i64 -1)486  ret void487}488