1; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-linux-gnu" | FileCheck %s 2; RUN: llc < %s -verify-machineinstrs -stack-symbol-ordering=0 -mtriple="x86_64-pc-unknown-elf" | FileCheck %s 3 4; This test is a basic correctness check to ensure statepoints are generating 5; StackMap sections correctly. This is not intended to be a rigorous test of 6; 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 the 16; alloca? 17; CHECK: subq $40, %rsp 18; CHECK: movq $0, 24(%rsp) 19; CHECK: movq %rdi, 16(%rsp) 20; CHECK: movq %rax, 8(%rsp) 21; CHECK: callq return_i1 22; CHECK: addq $40, %rsp 23; CHECK: retq 24entry: 25 %metadata1 = alloca ptr addrspace(1), i32 2, align 8 26 store ptr addrspace(1) null, ptr %metadata1 27 %ptr_derived = getelementptr i32, ptr addrspace(1) %ptr_base, i32 %arg 28 %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 %call1 35} 36 37; This is similar to the previous test except that we have derived pointer as 38; argument to the function. Despite that this can not happen after the 39; 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_arg 44; Do we see two spills for the local values and the store to the 45; alloca? 46; CHECK: subq $40, %rsp 47; CHECK: movq $0, 24(%rsp) 48; CHECK: movq %rdi, 16(%rsp) 49; CHECK: movq %rsi, 8(%rsp) 50; CHECK: callq return_i1 51; CHECK: addq $40, %rsp 52; CHECK: retq 53entry: 54 %metadata1 = alloca ptr addrspace(1), i32 2, align 8 55 store ptr addrspace(1) null, ptr %metadata1 56 %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 %call1 63} 64 65; Simple test case to check that we emit the ID field correctly 66define i1 @test_id() gc "statepoint-example" { 67; CHECK-LABEL: test_id 68entry: 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 %call1 72} 73 74; This test checks that when SP is changed in the function 75; (e.g. passing arguments on stack), the stack map entry 76; 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_spadj 81 ; CHECK: movq %rdi, (%rsp) 82 ; CHECK: xorl %edi, %edi 83 ; CHECK: xorl %esi, %esi 84 ; CHECK: xorl %edx, %edx 85 ; CHECK: xorl %ecx, %ecx 86 ; CHECK: xorl %r8d, %r8d 87 ; CHECK: xorl %r9d, %r9d 88 ; CHECK: pushq $0 89 ; CHECK: pushq $0 90 ; CHECK: callq many_arg 91 ; CHECK: addq $16, %rsp 92 ; 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.relocated 96 ret i32 %ld 97} 98 99; Test that function arguments at fixed stack offset 100; can be directly encoded in the stack map, without 101; 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_arg 108; CHECK: pushq %rax 109; CHECK: leaq 16(%rsp), %rdi 110; Should not spill fixed stack address. 111; CHECK-NOT: movq %rdi, (%rsp) 112; CHECK: callq use 113; CHECK: popq %rax 114; CHECK: retq 115entry: 116 br label %bb 117 118bb: ; preds = %entry 119 %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 void 121} 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) #3 126 127; CHECK-LABEL: .section .llvm_stackmaps 128; CHECK-NEXT: __LLVM_StackMaps: 129; Header 130; CHECK-NEXT: .byte 3 131; CHECK-NEXT: .byte 0 132; CHECK-NEXT: .short 0 133; Num Functions 134; CHECK-NEXT: .long 5 135; Num LargeConstants 136; CHECK-NEXT: .long 0 137; Num Callsites 138; CHECK-NEXT: .long 5 139 140; Functions and stack size 141; CHECK-NEXT: .quad test 142; CHECK-NEXT: .quad 40 143; CHECK-NEXT: .quad 1 144; CHECK-NEXT: .quad test_derived_arg 145; CHECK-NEXT: .quad 40 146; CHECK-NEXT: .quad 1 147; CHECK-NEXT: .quad test_id 148; CHECK-NEXT: .quad 8 149; CHECK-NEXT: .quad 1 150; CHECK-NEXT: .quad test_spadj 151; CHECK-NEXT: .quad 8 152; CHECK-NEXT: .quad 1 153; CHECK-NEXT: .quad test_fixed_arg 154; CHECK-NEXT: .quad 8 155; CHECK-NEXT: .quad 1 156 157; 158; test 159; 160 161; Statepoint ID 162; CHECK-NEXT: .quad 0 163 164; Callsites 165; Constant arguments 166; CHECK-NEXT: .long .Ltmp0-test 167; CHECK: .short 0 168; CHECK: .short 11 169; SmallConstant (0) 170; CHECK: .byte 4 171; CHECK-NEXT: .byte 0 172; CHECK: .short 8 173; CHECK: .short 0 174; CHECK-NEXT: .short 0 175; CHECK: .long 0 176; SmallConstant (0) 177; CHECK: .byte 4 178; CHECK-NEXT: .byte 0 179; CHECK: .short 8 180; CHECK: .short 0 181; CHECK-NEXT: .short 0 182; CHECK: .long 0 183; SmallConstant (2) 184; CHECK: .byte 4 185; CHECK-NEXT: .byte 0 186; CHECK: .short 8 187; CHECK: .short 0 188; CHECK-NEXT: .short 0 189; CHECK: .long 2 190; Indirect Spill Slot [RSP+0] 191; CHECK: .byte 3 192; CHECK-NEXT: .byte 0 193; CHECK: .short 8 194; CHECK: .short 7 195; CHECK-NEXT: .short 0 196; CHECK: .long 16 197; SmallConstant (0) 198; CHECK: .byte 4 199; CHECK-NEXT: .byte 0 200; CHECK: .short 8 201; CHECK: .short 0 202; CHECK-NEXT: .short 0 203; CHECK: .long 0 204; SmallConstant (0) 205; CHECK: .byte 4 206; CHECK-NEXT: .byte 0 207; CHECK: .short 8 208; CHECK: .short 0 209; CHECK-NEXT: .short 0 210; CHECK: .long 0 211; SmallConstant (0) 212; CHECK: .byte 4 213; CHECK-NEXT: .byte 0 214; CHECK: .short 8 215; CHECK: .short 0 216; CHECK-NEXT: .short 0 217; CHECK: .long 0 218; Indirect Spill Slot [RSP+16] 219; CHECK: .byte 3 220; CHECK-NEXT: .byte 0 221; CHECK: .short 8 222; CHECK: .short 7 223; CHECK-NEXT: .short 0 224; CHECK: .long 16 225; Indirect Spill Slot [RSP+8] 226; CHECK: .byte 3 227; CHECK-NEXT: .byte 0 228; CHECK: .short 8 229; CHECK: .short 7 230; CHECK-NEXT: .short 0 231; CHECK: .long 8 232; Indirect Spill Slot [RSP+16] 233; CHECK: .byte 3 234; CHECK-NEXT: .byte 0 235; CHECK: .short 8 236; CHECK: .short 7 237; CHECK-NEXT: .short 0 238; CHECK: .long 16 239; Indirect Spill Slot [RSP+16] 240; CHECK: .byte 3 241; CHECK-NEXT: .byte 0 242; CHECK: .short 8 243; CHECK: .short 7 244; CHECK-NEXT: .short 0 245; CHECK: .long 16 246 247; No Padding or LiveOuts 248; CHECK: .short 0 249; CHECK: .short 0 250; CHECK: .p2align 3 251 252; 253; test_derived_arg 254 255; Statepoint ID 256; CHECK-NEXT: .quad 0 257 258; Callsites 259; Constant arguments 260; CHECK-NEXT: .long .Ltmp1-test_derived_arg 261; CHECK: .short 0 262; CHECK: .short 11 263; SmallConstant (0) 264; CHECK: .byte 4 265; CHECK-NEXT: .byte 0 266; CHECK: .short 8 267; CHECK: .short 0 268; CHECK-NEXT: .short 0 269; CHECK: .long 0 270; SmallConstant (2) 271; CHECK: .byte 4 272; CHECK-NEXT: .byte 0 273; CHECK: .short 8 274; CHECK: .short 0 275; CHECK-NEXT: .short 0 276; CHECK: .long 2 277; Indirect Spill Slot [RSP+0] 278; CHECK: .byte 3 279; CHECK-NEXT: .byte 0 280; CHECK: .short 8 281; CHECK: .short 7 282; CHECK-NEXT: .short 0 283; CHECK: .long 16 284; SmallConstant (0) 285; CHECK: .byte 4 286; CHECK-NEXT: .byte 0 287; CHECK: .short 8 288; CHECK: .short 0 289; CHECK-NEXT: .short 0 290; CHECK: .long 0 291; SmallConstant (0) 292; CHECK: .byte 4 293; CHECK-NEXT: .byte 0 294; CHECK: .short 8 295; CHECK: .short 0 296; CHECK-NEXT: .short 0 297; CHECK: .long 0 298; SmallConstant (0) 299; CHECK: .byte 4 300; CHECK-NEXT: .byte 0 301; CHECK: .short 8 302; CHECK: .short 0 303; CHECK-NEXT: .short 0 304; CHECK: .long 0 305; Indirect Spill Slot [RSP+16] 306; CHECK: .byte 3 307; CHECK-NEXT: .byte 0 308; CHECK: .short 8 309; CHECK: .short 7 310; CHECK-NEXT: .short 0 311; CHECK: .long 16 312; Indirect Spill Slot [RSP+8] 313; CHECK: .byte 3 314; CHECK-NEXT: .byte 0 315; CHECK: .short 8 316; CHECK: .short 7 317; CHECK-NEXT: .short 0 318; CHECK: .long 8 319; Indirect Spill Slot [RSP+16] 320; CHECK: .byte 3 321; CHECK-NEXT: .byte 0 322; CHECK: .short 8 323; CHECK: .short 7 324; CHECK-NEXT: .short 0 325; CHECK: .long 16 326; Indirect Spill Slot [RSP+16] 327; CHECK: .byte 3 328; CHECK-NEXT: .byte 0 329; CHECK: .short 8 330; CHECK: .short 7 331; CHECK-NEXT: .short 0 332; CHECK: .long 16 333 334; No Padding or LiveOuts 335; CHECK: .short 0 336; CHECK: .short 0 337; CHECK: .p2align 3 338 339; Records for the test_id function: 340 341; The Statepoint ID: 342; CHECK-NEXT: .quad 237 343 344; Instruction Offset 345; CHECK-NEXT: .long .Ltmp2-test_id 346 347; Reserved: 348; CHECK: .short 0 349 350; NumLocations: 351; CHECK: .short 3 352 353; StkMapRecord[0]: 354; SmallConstant(0): 355; CHECK: .byte 4 356; CHECK-NEXT: .byte 0 357; CHECK: .short 8 358; CHECK: .short 0 359; CHECK-NEXT: .short 0 360; CHECK: .long 0 361 362; StkMapRecord[1]: 363; SmallConstant(0): 364; CHECK: .byte 4 365; CHECK-NEXT: .byte 0 366; CHECK: .short 8 367; CHECK: .short 0 368; CHECK-NEXT: .short 0 369; CHECK: .long 0 370 371; StkMapRecord[2]: 372; SmallConstant(0): 373; CHECK: .byte 4 374; CHECK-NEXT: .byte 0 375; CHECK: .short 8 376; CHECK: .short 0 377; CHECK-NEXT: .short 0 378; CHECK: .long 0 379 380; No padding or LiveOuts 381; CHECK: .short 0 382; CHECK: .short 0 383; CHECK: .p2align 3 384 385; 386; test_spadj 387 388; Statepoint ID 389; CHECK-NEXT: .quad 0 390 391; Instruction Offset 392; CHECK-NEXT: .long .Ltmp3-test_spadj 393 394; Reserved: 395; CHECK: .short 0 396 397; NumLocations: 398; CHECK: .short 5 399 400; StkMapRecord[0]: 401; SmallConstant(0): 402; CHECK: .byte 4 403; CHECK-NEXT: .byte 0 404; CHECK: .short 8 405; CHECK: .short 0 406; CHECK-NEXT: .short 0 407; CHECK: .long 0 408 409; StkMapRecord[1]: 410; SmallConstant(0): 411; CHECK: .byte 4 412; CHECK-NEXT: .byte 0 413; CHECK: .short 8 414; CHECK: .short 0 415; CHECK-NEXT: .short 0 416; CHECK: .long 0 417 418; StkMapRecord[2]: 419; SmallConstant(0): 420; CHECK: .byte 4 421; CHECK-NEXT: .byte 0 422; CHECK: .short 8 423; CHECK: .short 0 424; CHECK-NEXT: .short 0 425; CHECK: .long 0 426 427; StkMapRecord[3]: 428; Indirect Spill Slot [RSP+16] 429; CHECK: .byte 3 430; CHECK-NEXT: .byte 0 431; CHECK: .short 8 432; CHECK: .short 7 433; CHECK-NEXT: .short 0 434; CHECK: .long 16 435 436; StkMapRecord[4]: 437; Indirect Spill Slot [RSP+16] 438; CHECK: .byte 3 439; CHECK-NEXT: .byte 0 440; CHECK: .short 8 441; CHECK: .short 7 442; CHECK-NEXT: .short 0 443; CHECK: .long 16 444 445; No padding or LiveOuts 446; CHECK: .short 0 447; CHECK: .short 0 448; CHECK: .p2align 3 449 450; 451; test_fixed_arg 452 453; Statepoint ID 454; CHECK-NEXT: .quad 0 455 456; Instruction Offset 457; CHECK-NEXT: .long .Ltmp4-test_fixed_arg 458 459; Reserved: 460; CHECK: .short 0 461 462; NumLocations: 463; CHECK: .short 4 464 465; StkMapRecord[0]: 466; SmallConstant(0): 467; CHECK: .byte 4 468; CHECK-NEXT: .byte 0 469; CHECK: .short 8 470; CHECK: .short 0 471; CHECK-NEXT: .short 0 472; CHECK: .long 0 473 474; StkMapRecord[1]: 475; SmallConstant(0): 476; CHECK: .byte 4 477; CHECK-NEXT: .byte 0 478; CHECK: .short 8 479; CHECK: .short 0 480; CHECK-NEXT: .short 0 481; CHECK: .long 0 482 483; StkMapRecord[2]: 484; SmallConstant(1): 485; CHECK: .byte 4 486; CHECK-NEXT: .byte 0 487; CHECK: .short 8 488; CHECK: .short 0 489; CHECK-NEXT: .short 0 490; CHECK: .long 1 491 492; StkMapRecord[3]: 493; Direct RSP+16 494; CHECK: .byte 2 495; CHECK-NEXT: .byte 0 496; CHECK: .short 8 497; CHECK: .short 7 498; CHECK-NEXT: .short 0 499; CHECK: .long 16 500 501; No padding or LiveOuts 502; CHECK: .short 0 503; CHECK: .short 0 504; CHECK: .p2align 3 505