505 lines · plain
1; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-linux-gnu" | FileCheck %s2; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-unknown-elf" | FileCheck %s3 4; This test is a basic correctness check to ensure statepoints are generating5; StackMap sections correctly. This is not intended to be a rigorous test of6; the StackMap format (see the stackmap tests for that).7 8target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"9 10declare zeroext i1 @return_i1()11 12define i1 @test(ptr addrspace(1) %ptr_base, i32 %arg)13 gc "statepoint-example" {14; CHECK-LABEL: test:15; Do we see two spills for the local values and the store to the16; alloca?17; CHECK: subq $40, %rsp18; CHECK: movq $0, 24(%rsp)19; CHECK: movq %rdi, 16(%rsp)20; CHECK: movq %rax, 8(%rsp)21; CHECK: callq return_i122; CHECK: addq $40, %rsp23; CHECK: retq24entry:25 %metadata1 = alloca ptr addrspace(1), i32 2, align 826 store ptr addrspace(1) null, ptr %metadata127 %ptr_derived = getelementptr i32, ptr addrspace(1) %ptr_base, i32 %arg28 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %ptr_base, ptr addrspace(1) %ptr_derived, ptr addrspace(1) null), "deopt" (ptr addrspace(1) %ptr_base, ptr addrspace(1) null)]29 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)30 %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)31 %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1)32 %c = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 2, i32 2)33; 34 ret i1 %call135}36 37; This is similar to the previous test except that we have derived pointer as38; argument to the function. Despite that this can not happen after the39; RewriteSafepointForGC pass, lowering should be able to handle it anyway.40define i1 @test_derived_arg(ptr addrspace(1) %ptr_base,41 ptr addrspace(1) %ptr_derived)42 gc "statepoint-example" {43; CHECK-LABEL: test_derived_arg44; Do we see two spills for the local values and the store to the45; alloca?46; CHECK: subq $40, %rsp47; CHECK: movq $0, 24(%rsp)48; CHECK: movq %rdi, 16(%rsp)49; CHECK: movq %rsi, 8(%rsp)50; CHECK: callq return_i151; CHECK: addq $40, %rsp52; CHECK: retq53entry:54 %metadata1 = alloca ptr addrspace(1), i32 2, align 855 store ptr addrspace(1) null, ptr %metadata156 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %ptr_base, ptr addrspace(1) %ptr_derived, ptr addrspace(1) null), "deopt" (ptr addrspace(1) %ptr_base, ptr addrspace(1) null)]57 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)58 %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)59 %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1)60 %c = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 2, i32 2)61; 62 ret i1 %call163}64 65; Simple test case to check that we emit the ID field correctly66define i1 @test_id() gc "statepoint-example" {67; CHECK-LABEL: test_id68entry:69 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 237, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0)70 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)71 ret i1 %call172}73 74; This test checks that when SP is changed in the function75; (e.g. passing arguments on stack), the stack map entry76; takes this adjustment into account.77declare void @many_arg(i64, i64, i64, i64, i64, i64, i64, i64)78 79define i32 @test_spadj(ptr addrspace(1) %p) gc "statepoint-example" {80 ; CHECK-LABEL: test_spadj81 ; CHECK: movq %rdi, (%rsp)82 ; CHECK: xorl %edi, %edi83 ; CHECK: xorl %esi, %esi84 ; CHECK: xorl %edx, %edx85 ; CHECK: xorl %ecx, %ecx86 ; CHECK: xorl %r8d, %r8d87 ; CHECK: xorl %r9d, %r9d88 ; CHECK: pushq $089 ; CHECK: pushq $090 ; CHECK: callq many_arg91 ; CHECK: addq $16, %rsp92 ; CHECK: movq (%rsp)93 %statepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (i64, i64, i64, i64, i64, i64, i64, i64)) @many_arg, i32 8, i32 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %p)]94 %p.relocated = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %statepoint_token, i32 0, i32 0) ; (%p, %p)95 %ld = load i32, ptr addrspace(1) %p.relocated96 ret i32 %ld97}98 99; Test that function arguments at fixed stack offset100; can be directly encoded in the stack map, without101; spilling.102%struct = type { i64, i64, i64 }103 104declare void @use(ptr)105 106define void @test_fixed_arg(ptr byval(%struct) %x) gc "statepoint-example" {107; CHECK-LABEL: test_fixed_arg108; CHECK: pushq %rax109; CHECK: leaq 16(%rsp), %rdi110; Should not spill fixed stack address.111; CHECK-NOT: movq %rdi, (%rsp)112; CHECK: callq use113; CHECK: popq %rax114; CHECK: retq115entry:116 br label %bb117 118bb: ; preds = %entry119 %statepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (ptr)) @use, i32 1, i32 0, ptr %x, i32 0, i32 0) ["deopt" (ptr %x)]120 ret void121}122 123declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)124declare i1 @llvm.experimental.gc.result.i1(token)125declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32) #3126 127; CHECK-LABEL: .section .llvm_stackmaps128; CHECK-NEXT: __LLVM_StackMaps:129; Header130; CHECK-NEXT: .byte 3131; CHECK-NEXT: .byte 0132; CHECK-NEXT: .short 0133; Num Functions134; CHECK-NEXT: .long 5135; Num LargeConstants136; CHECK-NEXT: .long 0137; Num Callsites138; CHECK-NEXT: .long 5139 140; Functions and stack size141; CHECK-NEXT: .quad test142; CHECK-NEXT: .quad 40143; CHECK-NEXT: .quad 1144; CHECK-NEXT: .quad test_derived_arg145; CHECK-NEXT: .quad 40146; CHECK-NEXT: .quad 1147; CHECK-NEXT: .quad test_id148; CHECK-NEXT: .quad 8149; CHECK-NEXT: .quad 1150; CHECK-NEXT: .quad test_spadj151; CHECK-NEXT: .quad 8152; CHECK-NEXT: .quad 1153; CHECK-NEXT: .quad test_fixed_arg154; CHECK-NEXT: .quad 8155; CHECK-NEXT: .quad 1156 157;158; test159;160 161; Statepoint ID162; CHECK-NEXT: .quad 0163 164; Callsites165; Constant arguments166; CHECK-NEXT: .long .Ltmp0-test167; CHECK: .short 0168; CHECK: .short 11169; SmallConstant (0)170; CHECK: .byte 4171; CHECK-NEXT: .byte 0172; CHECK: .short 8173; CHECK: .short 0174; CHECK-NEXT: .short 0175; CHECK: .long 0176; SmallConstant (0)177; CHECK: .byte 4178; CHECK-NEXT: .byte 0179; CHECK: .short 8180; CHECK: .short 0181; CHECK-NEXT: .short 0182; CHECK: .long 0183; SmallConstant (2)184; CHECK: .byte 4185; CHECK-NEXT: .byte 0186; CHECK: .short 8187; CHECK: .short 0188; CHECK-NEXT: .short 0189; CHECK: .long 2190; Indirect Spill Slot [RSP+0]191; CHECK: .byte 3192; CHECK-NEXT: .byte 0193; CHECK: .short 8194; CHECK: .short 7195; CHECK-NEXT: .short 0196; CHECK: .long 16197; SmallConstant (0)198; CHECK: .byte 4199; CHECK-NEXT: .byte 0200; CHECK: .short 8201; CHECK: .short 0202; CHECK-NEXT: .short 0203; CHECK: .long 0204; SmallConstant (0)205; CHECK: .byte 4206; CHECK-NEXT: .byte 0207; CHECK: .short 8208; CHECK: .short 0209; CHECK-NEXT: .short 0210; CHECK: .long 0211; SmallConstant (0)212; CHECK: .byte 4213; CHECK-NEXT: .byte 0214; CHECK: .short 8215; CHECK: .short 0216; CHECK-NEXT: .short 0217; CHECK: .long 0218; Indirect Spill Slot [RSP+16]219; CHECK: .byte 3220; CHECK-NEXT: .byte 0221; CHECK: .short 8222; CHECK: .short 7223; CHECK-NEXT: .short 0224; CHECK: .long 16225; Indirect Spill Slot [RSP+8]226; CHECK: .byte 3227; CHECK-NEXT: .byte 0228; CHECK: .short 8229; CHECK: .short 7230; CHECK-NEXT: .short 0231; CHECK: .long 8232; Indirect Spill Slot [RSP+16]233; CHECK: .byte 3234; CHECK-NEXT: .byte 0235; CHECK: .short 8236; CHECK: .short 7237; CHECK-NEXT: .short 0238; CHECK: .long 16239; Indirect Spill Slot [RSP+16]240; CHECK: .byte 3241; CHECK-NEXT: .byte 0242; CHECK: .short 8243; CHECK: .short 7244; CHECK-NEXT: .short 0245; CHECK: .long 16246 247; No Padding or LiveOuts248; CHECK: .short 0249; CHECK: .short 0250; CHECK: .p2align 3251 252;253; test_derived_arg254 255; Statepoint ID256; CHECK-NEXT: .quad 0257 258; Callsites259; Constant arguments260; CHECK-NEXT: .long .Ltmp1-test_derived_arg261; CHECK: .short 0262; CHECK: .short 11263; SmallConstant (0)264; CHECK: .byte 4265; CHECK-NEXT: .byte 0266; CHECK: .short 8267; CHECK: .short 0268; CHECK-NEXT: .short 0269; CHECK: .long 0270; SmallConstant (2)271; CHECK: .byte 4272; CHECK-NEXT: .byte 0273; CHECK: .short 8274; CHECK: .short 0275; CHECK-NEXT: .short 0276; CHECK: .long 2277; Indirect Spill Slot [RSP+0]278; CHECK: .byte 3279; CHECK-NEXT: .byte 0280; CHECK: .short 8281; CHECK: .short 7282; CHECK-NEXT: .short 0283; CHECK: .long 16284; SmallConstant (0)285; CHECK: .byte 4286; CHECK-NEXT: .byte 0287; CHECK: .short 8288; CHECK: .short 0289; CHECK-NEXT: .short 0290; CHECK: .long 0291; SmallConstant (0)292; CHECK: .byte 4293; CHECK-NEXT: .byte 0294; CHECK: .short 8295; CHECK: .short 0296; CHECK-NEXT: .short 0297; CHECK: .long 0298; SmallConstant (0)299; CHECK: .byte 4300; CHECK-NEXT: .byte 0301; CHECK: .short 8302; CHECK: .short 0303; CHECK-NEXT: .short 0304; CHECK: .long 0305; Indirect Spill Slot [RSP+16]306; CHECK: .byte 3307; CHECK-NEXT: .byte 0308; CHECK: .short 8309; CHECK: .short 7310; CHECK-NEXT: .short 0311; CHECK: .long 16312; Indirect Spill Slot [RSP+8]313; CHECK: .byte 3314; CHECK-NEXT: .byte 0315; CHECK: .short 8316; CHECK: .short 7317; CHECK-NEXT: .short 0318; CHECK: .long 8319; Indirect Spill Slot [RSP+16]320; CHECK: .byte 3321; CHECK-NEXT: .byte 0322; CHECK: .short 8323; CHECK: .short 7324; CHECK-NEXT: .short 0325; CHECK: .long 16326; Indirect Spill Slot [RSP+16]327; CHECK: .byte 3328; CHECK-NEXT: .byte 0329; CHECK: .short 8330; CHECK: .short 7331; CHECK-NEXT: .short 0332; CHECK: .long 16333 334; No Padding or LiveOuts335; CHECK: .short 0336; CHECK: .short 0337; CHECK: .p2align 3338 339; Records for the test_id function:340 341; The Statepoint ID:342; CHECK-NEXT: .quad 237343 344; Instruction Offset345; CHECK-NEXT: .long .Ltmp2-test_id346 347; Reserved:348; CHECK: .short 0349 350; NumLocations:351; CHECK: .short 3352 353; StkMapRecord[0]:354; SmallConstant(0):355; CHECK: .byte 4356; CHECK-NEXT: .byte 0357; CHECK: .short 8358; CHECK: .short 0359; CHECK-NEXT: .short 0360; CHECK: .long 0361 362; StkMapRecord[1]:363; SmallConstant(0):364; CHECK: .byte 4365; CHECK-NEXT: .byte 0366; CHECK: .short 8367; CHECK: .short 0368; CHECK-NEXT: .short 0369; CHECK: .long 0370 371; StkMapRecord[2]:372; SmallConstant(0):373; CHECK: .byte 4374; CHECK-NEXT: .byte 0375; CHECK: .short 8376; CHECK: .short 0377; CHECK-NEXT: .short 0378; CHECK: .long 0379 380; No padding or LiveOuts381; CHECK: .short 0382; CHECK: .short 0383; CHECK: .p2align 3384 385;386; test_spadj387 388; Statepoint ID389; CHECK-NEXT: .quad 0390 391; Instruction Offset392; CHECK-NEXT: .long .Ltmp3-test_spadj393 394; Reserved:395; CHECK: .short 0396 397; NumLocations:398; CHECK: .short 5399 400; StkMapRecord[0]:401; SmallConstant(0):402; CHECK: .byte 4403; CHECK-NEXT: .byte 0404; CHECK: .short 8405; CHECK: .short 0406; CHECK-NEXT: .short 0407; CHECK: .long 0408 409; StkMapRecord[1]:410; SmallConstant(0):411; CHECK: .byte 4412; CHECK-NEXT: .byte 0413; CHECK: .short 8414; CHECK: .short 0415; CHECK-NEXT: .short 0416; CHECK: .long 0417 418; StkMapRecord[2]:419; SmallConstant(0):420; CHECK: .byte 4421; CHECK-NEXT: .byte 0422; CHECK: .short 8423; CHECK: .short 0424; CHECK-NEXT: .short 0425; CHECK: .long 0426 427; StkMapRecord[3]:428; Indirect Spill Slot [RSP+16]429; CHECK: .byte 3430; CHECK-NEXT: .byte 0431; CHECK: .short 8432; CHECK: .short 7433; CHECK-NEXT: .short 0434; CHECK: .long 16435 436; StkMapRecord[4]:437; Indirect Spill Slot [RSP+16]438; CHECK: .byte 3439; CHECK-NEXT: .byte 0440; CHECK: .short 8441; CHECK: .short 7442; CHECK-NEXT: .short 0443; CHECK: .long 16444 445; No padding or LiveOuts446; CHECK: .short 0447; CHECK: .short 0448; CHECK: .p2align 3449 450;451; test_fixed_arg452 453; Statepoint ID454; CHECK-NEXT: .quad 0455 456; Instruction Offset457; CHECK-NEXT: .long .Ltmp4-test_fixed_arg458 459; Reserved:460; CHECK: .short 0461 462; NumLocations:463; CHECK: .short 4464 465; StkMapRecord[0]:466; SmallConstant(0):467; CHECK: .byte 4468; CHECK-NEXT: .byte 0469; CHECK: .short 8470; CHECK: .short 0471; CHECK-NEXT: .short 0472; CHECK: .long 0473 474; StkMapRecord[1]:475; SmallConstant(0):476; CHECK: .byte 4477; CHECK-NEXT: .byte 0478; CHECK: .short 8479; CHECK: .short 0480; CHECK-NEXT: .short 0481; CHECK: .long 0482 483; StkMapRecord[2]:484; SmallConstant(1):485; CHECK: .byte 4486; CHECK-NEXT: .byte 0487; CHECK: .short 8488; CHECK: .short 0489; CHECK-NEXT: .short 0490; CHECK: .long 1491 492; StkMapRecord[3]:493; Direct RSP+16494; CHECK: .byte 2495; CHECK-NEXT: .byte 0496; CHECK: .short 8497; CHECK: .short 7498; CHECK-NEXT: .short 0499; CHECK: .long 16500 501; No padding or LiveOuts502; CHECK: .short 0503; CHECK: .short 0504; CHECK: .p2align 3505