1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -max-registers-for-gc-values=4 -fixup-allow-gcptr-in-csr=true < %s | FileCheck %s 3 4target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" 5target triple = "x86_64-pc-linux-gnu" 6 7declare i1 @return_i1() 8declare void @func() 9declare void @consume(ptr addrspace(1)) 10declare i32 @consume1(i32) gc "statepoint-example" 11declare void @consume2(ptr addrspace(1), ptr addrspace(1)) 12declare void @consume3(float) gc "statepoint-example" 13declare float @consume4(i64) gc "statepoint-example" 14declare void @consume5(ptr addrspace(1), ptr addrspace(1), ptr addrspace(1), ptr addrspace(1), ptr addrspace(1)) 15 16declare void @use1(ptr addrspace(1), ptr addrspace(1)) 17 18; test most simple relocate 19define i1 @test_relocate(ptr addrspace(1) %a) gc "statepoint-example" { 20; CHECK-LABEL: test_relocate: 21; CHECK: # %bb.0: # %entry 22; CHECK-NEXT: pushq %rbp 23; CHECK-NEXT: .cfi_def_cfa_offset 16 24; CHECK-NEXT: pushq %rbx 25; CHECK-NEXT: .cfi_def_cfa_offset 24 26; CHECK-NEXT: pushq %rax 27; CHECK-NEXT: .cfi_def_cfa_offset 32 28; CHECK-NEXT: .cfi_offset %rbx, -24 29; CHECK-NEXT: .cfi_offset %rbp, -16 30; CHECK-NEXT: movq %rdi, %rbx 31; CHECK-NEXT: callq return_i1@PLT 32; CHECK-NEXT: .Ltmp0: 33; CHECK-NEXT: movl %eax, %ebp 34; CHECK-NEXT: movq %rbx, %rdi 35; CHECK-NEXT: callq consume@PLT 36; CHECK-NEXT: movl %ebp, %eax 37; CHECK-NEXT: addq $8, %rsp 38; CHECK-NEXT: .cfi_def_cfa_offset 24 39; CHECK-NEXT: popq %rbx 40; CHECK-NEXT: .cfi_def_cfa_offset 16 41; CHECK-NEXT: popq %rbp 42; CHECK-NEXT: .cfi_def_cfa_offset 8 43; CHECK-NEXT: retq 44entry: 45 %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) %a)] 46 %rel1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) 47 %res1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token) 48 call void @consume(ptr addrspace(1) %rel1) 49 ret i1 %res1 50} 51 52; test pointer variables intermixed with pointer constants 53define void @test_mixed(ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %c) gc "statepoint-example" { 54; CHECK-LABEL: test_mixed: 55; CHECK: # %bb.0: # %entry 56; CHECK-NEXT: pushq %r15 57; CHECK-NEXT: .cfi_def_cfa_offset 16 58; CHECK-NEXT: pushq %r14 59; CHECK-NEXT: .cfi_def_cfa_offset 24 60; CHECK-NEXT: pushq %rbx 61; CHECK-NEXT: .cfi_def_cfa_offset 32 62; CHECK-NEXT: .cfi_offset %rbx, -32 63; CHECK-NEXT: .cfi_offset %r14, -24 64; CHECK-NEXT: .cfi_offset %r15, -16 65; CHECK-NEXT: movq %rdx, %rbx 66; CHECK-NEXT: movq %rsi, %r14 67; CHECK-NEXT: movq %rdi, %r15 68; CHECK-NEXT: callq func@PLT 69; CHECK-NEXT: .Ltmp1: 70; CHECK-NEXT: movq %r15, %rdi 71; CHECK-NEXT: xorl %esi, %esi 72; CHECK-NEXT: movq %r14, %rdx 73; CHECK-NEXT: xorl %ecx, %ecx 74; CHECK-NEXT: movq %rbx, %r8 75; CHECK-NEXT: callq consume5@PLT 76; CHECK-NEXT: popq %rbx 77; CHECK-NEXT: .cfi_def_cfa_offset 24 78; CHECK-NEXT: popq %r14 79; CHECK-NEXT: .cfi_def_cfa_offset 16 80; CHECK-NEXT: popq %r15 81; CHECK-NEXT: .cfi_def_cfa_offset 8 82; CHECK-NEXT: retq 83entry: 84 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %a, ptr addrspace(1) null, ptr addrspace(1) %b, ptr addrspace(1) null, ptr addrspace(1) %c)] 85 %rel1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) 86 %rel2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 1, i32 1) 87 %rel3 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 2, i32 2) 88 %rel4 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 3, i32 3) 89 %rel5 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 4, i32 4) 90 call void @consume5(ptr addrspace(1) %rel1, ptr addrspace(1) %rel2, ptr addrspace(1) %rel3, ptr addrspace(1) %rel4, ptr addrspace(1) %rel5) 91 ret void 92} 93 94; same as above, but for alloca 95define ptr addrspace(1) @test_alloca(ptr addrspace(1) %ptr) gc "statepoint-example" { 96; CHECK-LABEL: test_alloca: 97; CHECK: # %bb.0: # %entry 98; CHECK-NEXT: pushq %r14 99; CHECK-NEXT: .cfi_def_cfa_offset 16 100; CHECK-NEXT: pushq %rbx 101; CHECK-NEXT: .cfi_def_cfa_offset 24 102; CHECK-NEXT: pushq %rax 103; CHECK-NEXT: .cfi_def_cfa_offset 32 104; CHECK-NEXT: .cfi_offset %rbx, -24 105; CHECK-NEXT: .cfi_offset %r14, -16 106; CHECK-NEXT: movq %rdi, %rbx 107; CHECK-NEXT: movq %rdi, (%rsp) 108; CHECK-NEXT: callq return_i1@PLT 109; CHECK-NEXT: .Ltmp2: 110; CHECK-NEXT: movq (%rsp), %r14 111; CHECK-NEXT: movq %rbx, %rdi 112; CHECK-NEXT: callq consume@PLT 113; CHECK-NEXT: movq %r14, %rax 114; CHECK-NEXT: addq $8, %rsp 115; CHECK-NEXT: .cfi_def_cfa_offset 24 116; CHECK-NEXT: popq %rbx 117; CHECK-NEXT: .cfi_def_cfa_offset 16 118; CHECK-NEXT: popq %r14 119; CHECK-NEXT: .cfi_def_cfa_offset 8 120; CHECK-NEXT: retq 121entry: 122 %alloca = alloca ptr addrspace(1), align 8 123 store ptr addrspace(1) %ptr, ptr %alloca 124 %safepoint_token = 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 %alloca, ptr addrspace(1) %ptr)] 125 %rel1 = load ptr addrspace(1), ptr %alloca 126 %rel2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 1, i32 1) 127 call void @consume(ptr addrspace(1) %rel2) 128 ret ptr addrspace(1) %rel1 129} 130 131; test base != derived 132define void @test_base_derived(ptr addrspace(1) %base, ptr addrspace(1) %derived) gc "statepoint-example" { 133; CHECK-LABEL: test_base_derived: 134; CHECK: # %bb.0: 135; CHECK-NEXT: pushq %r14 136; CHECK-NEXT: .cfi_def_cfa_offset 16 137; CHECK-NEXT: pushq %rbx 138; CHECK-NEXT: .cfi_def_cfa_offset 24 139; CHECK-NEXT: pushq %rax 140; CHECK-NEXT: .cfi_def_cfa_offset 32 141; CHECK-NEXT: .cfi_offset %rbx, -24 142; CHECK-NEXT: .cfi_offset %r14, -16 143; CHECK-NEXT: movq %rsi, %rbx 144; CHECK-NEXT: movq %rdi, %r14 145; CHECK-NEXT: callq func@PLT 146; CHECK-NEXT: .Ltmp3: 147; CHECK-NEXT: movq %rbx, %rdi 148; CHECK-NEXT: callq consume@PLT 149; CHECK-NEXT: addq $8, %rsp 150; CHECK-NEXT: .cfi_def_cfa_offset 24 151; CHECK-NEXT: popq %rbx 152; CHECK-NEXT: .cfi_def_cfa_offset 16 153; CHECK-NEXT: popq %r14 154; CHECK-NEXT: .cfi_def_cfa_offset 8 155; CHECK-NEXT: retq 156 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %base, ptr addrspace(1) %derived)] 157 %reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1) 158 call void @consume(ptr addrspace(1) %reloc) 159 ret void 160} 161 162; deopt GC pointer not present in GC args goes on reg. 163define void @test_deopt_gcpointer(ptr addrspace(1) %a, ptr addrspace(1) %b) gc "statepoint-example" { 164; CHECK-LABEL: test_deopt_gcpointer: 165; CHECK: # %bb.0: 166; CHECK-NEXT: pushq %r14 167; CHECK-NEXT: .cfi_def_cfa_offset 16 168; CHECK-NEXT: pushq %rbx 169; CHECK-NEXT: .cfi_def_cfa_offset 24 170; CHECK-NEXT: pushq %rax 171; CHECK-NEXT: .cfi_def_cfa_offset 32 172; CHECK-NEXT: .cfi_offset %rbx, -24 173; CHECK-NEXT: .cfi_offset %r14, -16 174; CHECK-NEXT: movq %rsi, %rbx 175; CHECK-NEXT: movq %rdi, %r14 176; CHECK-NEXT: callq func@PLT 177; CHECK-NEXT: .Ltmp4: 178; CHECK-NEXT: movq %rbx, %rdi 179; CHECK-NEXT: callq consume@PLT 180; CHECK-NEXT: addq $8, %rsp 181; CHECK-NEXT: .cfi_def_cfa_offset 24 182; CHECK-NEXT: popq %rbx 183; CHECK-NEXT: .cfi_def_cfa_offset 16 184; CHECK-NEXT: popq %r14 185; CHECK-NEXT: .cfi_def_cfa_offset 8 186; CHECK-NEXT: retq 187 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (ptr addrspace(1) %a), "gc-live" (ptr addrspace(1) %b)] 188 %rel = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) 189 call void @consume(ptr addrspace(1) %rel) 190 ret void 191} 192 193;; Two gc.relocates of the same input, should require only a single spill/fill 194define void @test_gcrelocate_uniqueing(ptr addrspace(1) %ptr) gc "statepoint-example" { 195; CHECK-LABEL: test_gcrelocate_uniqueing: 196; CHECK: # %bb.0: 197; CHECK-NEXT: pushq %rbx 198; CHECK-NEXT: .cfi_def_cfa_offset 16 199; CHECK-NEXT: .cfi_offset %rbx, -16 200; CHECK-NEXT: movq %rdi, %rbx 201; CHECK-NEXT: callq func@PLT 202; CHECK-NEXT: .Ltmp5: 203; CHECK-NEXT: movq %rbx, %rdi 204; CHECK-NEXT: movq %rbx, %rsi 205; CHECK-NEXT: callq consume2@PLT 206; CHECK-NEXT: popq %rbx 207; CHECK-NEXT: .cfi_def_cfa_offset 8 208; CHECK-NEXT: retq 209 %tok = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (ptr addrspace(1) %ptr, i32 undef), "gc-live" (ptr addrspace(1) %ptr, ptr addrspace(1) %ptr)] 210 %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0) 211 %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 1, i32 1) 212 call void @consume2(ptr addrspace(1) %a, ptr addrspace(1) %b) 213 ret void 214} 215 216; Two gc.relocates of a bitcasted pointer should only require a single spill/fill 217define void @test_gcptr_uniqueing(ptr addrspace(1) %ptr) gc "statepoint-example" { 218; CHECK-LABEL: test_gcptr_uniqueing: 219; CHECK: # %bb.0: 220; CHECK-NEXT: pushq %rbx 221; CHECK-NEXT: .cfi_def_cfa_offset 16 222; CHECK-NEXT: .cfi_offset %rbx, -16 223; CHECK-NEXT: movq %rdi, %rbx 224; CHECK-NEXT: callq func@PLT 225; CHECK-NEXT: .Ltmp6: 226; CHECK-NEXT: movq %rbx, %rdi 227; CHECK-NEXT: movq %rbx, %rsi 228; CHECK-NEXT: callq use1@PLT 229; CHECK-NEXT: popq %rbx 230; CHECK-NEXT: .cfi_def_cfa_offset 8 231; CHECK-NEXT: retq 232 %tok = tail call token (i64, i32, ptr, i32, i32, ...) 233 @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (ptr addrspace(1) %ptr, i32 undef), "gc-live" (ptr addrspace(1) %ptr, ptr addrspace(1) %ptr)] 234 %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0) 235 %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 1, i32 1) 236 call void @use1(ptr addrspace(1) %a, ptr addrspace(1) %b) 237 ret void 238} 239 240; 241; Cross-basicblock relocates are handled with spilling for now. 242define i1 @test_cross_bb(ptr addrspace(1) %a, i1 %external_cond) gc "statepoint-example" { 243; CHECK-LABEL: test_cross_bb: 244; CHECK: # %bb.0: # %entry 245; CHECK-NEXT: pushq %rbp 246; CHECK-NEXT: .cfi_def_cfa_offset 16 247; CHECK-NEXT: pushq %rbx 248; CHECK-NEXT: .cfi_def_cfa_offset 24 249; CHECK-NEXT: pushq %rax 250; CHECK-NEXT: .cfi_def_cfa_offset 32 251; CHECK-NEXT: .cfi_offset %rbx, -24 252; CHECK-NEXT: .cfi_offset %rbp, -16 253; CHECK-NEXT: movl %esi, %ebp 254; CHECK-NEXT: movq %rdi, %rbx 255; CHECK-NEXT: callq return_i1@PLT 256; CHECK-NEXT: .Ltmp7: 257; CHECK-NEXT: testb $1, %bpl 258; CHECK-NEXT: je .LBB7_2 259; CHECK-NEXT: # %bb.1: # %left 260; CHECK-NEXT: movq %rbx, %rdi 261; CHECK-NEXT: movl %eax, %ebx 262; CHECK-NEXT: callq consume@PLT 263; CHECK-NEXT: movl %ebx, %eax 264; CHECK-NEXT: jmp .LBB7_3 265; CHECK-NEXT: .LBB7_2: # %right 266; CHECK-NEXT: movb $1, %al 267; CHECK-NEXT: .LBB7_3: # %right 268; CHECK-NEXT: addq $8, %rsp 269; CHECK-NEXT: .cfi_def_cfa_offset 24 270; CHECK-NEXT: popq %rbx 271; CHECK-NEXT: .cfi_def_cfa_offset 16 272; CHECK-NEXT: popq %rbp 273; CHECK-NEXT: .cfi_def_cfa_offset 8 274; CHECK-NEXT: retq 275entry: 276 %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) %a)] 277 br i1 %external_cond, label %left, label %right 278 279left: 280 %call1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) 281 %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token) 282 call void @consume(ptr addrspace(1) %call1) 283 ret i1 %call2 284 285right: 286 ret i1 true 287} 288 289; No need to check post-regalloc output as it is the same 290define i1 @duplicate_reloc() gc "statepoint-example" { 291; CHECK-LABEL: duplicate_reloc: 292; CHECK: # %bb.0: # %entry 293; CHECK-NEXT: pushq %rax 294; CHECK-NEXT: .cfi_def_cfa_offset 16 295; CHECK-NEXT: callq func@PLT 296; CHECK-NEXT: .Ltmp8: 297; CHECK-NEXT: callq func@PLT 298; CHECK-NEXT: .Ltmp9: 299; CHECK-NEXT: movb $1, %al 300; CHECK-NEXT: popq %rcx 301; CHECK-NEXT: .cfi_def_cfa_offset 8 302; CHECK-NEXT: retq 303entry: 304 %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) null, ptr addrspace(1) null)] 305 %base = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) 306 %derived = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 1) 307 %safepoint_token2 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %base, ptr addrspace(1) %derived)] 308 %base_reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token2, i32 0, i32 0) 309 %derived_reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token2, i32 0, i32 1) 310 %cmp1 = icmp eq ptr addrspace(1) %base_reloc, null 311 %cmp2 = icmp eq ptr addrspace(1) %derived_reloc, null 312 %cmp = and i1 %cmp1, %cmp2 313 ret i1 %cmp 314} 315 316; Vectors cannot go in VRegs 317; No need to check post-regalloc output as it is lowered using old scheme 318define <2 x ptr addrspace(1)> @test_vector(<2 x ptr addrspace(1)> %obj) gc "statepoint-example" { 319; CHECK-LABEL: test_vector: 320; CHECK: # %bb.0: # %entry 321; CHECK-NEXT: subq $24, %rsp 322; CHECK-NEXT: .cfi_def_cfa_offset 32 323; CHECK-NEXT: movaps %xmm0, (%rsp) 324; CHECK-NEXT: callq func@PLT 325; CHECK-NEXT: .Ltmp10: 326; CHECK-NEXT: movaps (%rsp), %xmm0 327; CHECK-NEXT: addq $24, %rsp 328; CHECK-NEXT: .cfi_def_cfa_offset 8 329; CHECK-NEXT: retq 330entry: 331 %safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (<2 x ptr addrspace(1)> %obj)] 332 %obj.relocated = call coldcc <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token %safepoint_token, i32 0, i32 0) ; (%obj, %obj) 333 ret <2 x ptr addrspace(1)> %obj.relocated 334} 335 336 337; test limit on amount of vregs 338define void @test_limit(ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %c, ptr addrspace(1) %d, ptr addrspace(1) %e) gc "statepoint-example" { 339; CHECK-LABEL: test_limit: 340; CHECK: # %bb.0: # %entry 341; CHECK-NEXT: pushq %r15 342; CHECK-NEXT: .cfi_def_cfa_offset 16 343; CHECK-NEXT: pushq %r14 344; CHECK-NEXT: .cfi_def_cfa_offset 24 345; CHECK-NEXT: pushq %r12 346; CHECK-NEXT: .cfi_def_cfa_offset 32 347; CHECK-NEXT: pushq %rbx 348; CHECK-NEXT: .cfi_def_cfa_offset 40 349; CHECK-NEXT: pushq %rax 350; CHECK-NEXT: .cfi_def_cfa_offset 48 351; CHECK-NEXT: .cfi_offset %rbx, -40 352; CHECK-NEXT: .cfi_offset %r12, -32 353; CHECK-NEXT: .cfi_offset %r14, -24 354; CHECK-NEXT: .cfi_offset %r15, -16 355; CHECK-NEXT: movq %r8, %rbx 356; CHECK-NEXT: movq %rcx, %r14 357; CHECK-NEXT: movq %rdx, %r15 358; CHECK-NEXT: movq %rsi, %r12 359; CHECK-NEXT: movq %rdi, (%rsp) 360; CHECK-NEXT: callq func@PLT 361; CHECK-NEXT: .Ltmp11: 362; CHECK-NEXT: movq (%rsp), %rdi 363; CHECK-NEXT: movq %r12, %rsi 364; CHECK-NEXT: movq %r15, %rdx 365; CHECK-NEXT: movq %r14, %rcx 366; CHECK-NEXT: movq %rbx, %r8 367; CHECK-NEXT: callq consume5@PLT 368; CHECK-NEXT: addq $8, %rsp 369; CHECK-NEXT: .cfi_def_cfa_offset 40 370; CHECK-NEXT: popq %rbx 371; CHECK-NEXT: .cfi_def_cfa_offset 32 372; CHECK-NEXT: popq %r12 373; CHECK-NEXT: .cfi_def_cfa_offset 24 374; CHECK-NEXT: popq %r14 375; CHECK-NEXT: .cfi_def_cfa_offset 16 376; CHECK-NEXT: popq %r15 377; CHECK-NEXT: .cfi_def_cfa_offset 8 378; CHECK-NEXT: retq 379entry: 380 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %c, ptr addrspace(1) %d, ptr addrspace(1) %e)] 381 %rel1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) 382 %rel2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 1, i32 1) 383 %rel3 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 2, i32 2) 384 %rel4 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 3, i32 3) 385 %rel5 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 4, i32 4) 386 call void @consume5(ptr addrspace(1) %rel1, ptr addrspace(1) %rel2, ptr addrspace(1) %rel3, ptr addrspace(1) %rel4, ptr addrspace(1) %rel5) 387 ret void 388} 389 390; test ISEL for constant base pointer - must properly tie operands 391define void @test_const_base(ptr addrspace(1) %a) gc "statepoint-example" { 392; CHECK-LABEL: test_const_base: 393; CHECK: # %bb.0: # %entry 394; CHECK-NEXT: pushq %rbx 395; CHECK-NEXT: .cfi_def_cfa_offset 16 396; CHECK-NEXT: .cfi_offset %rbx, -16 397; CHECK-NEXT: movq %rdi, %rbx 398; CHECK-NEXT: callq func@PLT 399; CHECK-NEXT: .Ltmp12: 400; CHECK-NEXT: movq %rbx, %rdi 401; CHECK-NEXT: callq consume@PLT 402; CHECK-NEXT: popq %rbx 403; CHECK-NEXT: .cfi_def_cfa_offset 8 404; CHECK-NEXT: retq 405entry: 406 %token1 = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 0, i32 1, i32 7, ptr addrspace(1) null, i32 9), "gc-live" (ptr addrspace(1) null, ptr addrspace(1) %a)] 407 %rel = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token1, i32 0, i32 1) 408 call void @consume(ptr addrspace(1) %rel) 409 ret void 410} 411 412; test multiple statepoints/relocates within single block. 413; relocates must be properly scheduled w.r.t. statepoints 414define void @test_sched(float %0, i32 %1, ptr addrspace(1) %2) gc "statepoint-example" { 415; CHECK-LABEL: test_sched: 416; CHECK: # %bb.0: # %entry 417; CHECK-NEXT: pushq %rbp 418; CHECK-NEXT: .cfi_def_cfa_offset 16 419; CHECK-NEXT: pushq %rbx 420; CHECK-NEXT: .cfi_def_cfa_offset 24 421; CHECK-NEXT: subq $24, %rsp 422; CHECK-NEXT: .cfi_def_cfa_offset 48 423; CHECK-NEXT: .cfi_offset %rbx, -24 424; CHECK-NEXT: .cfi_offset %rbp, -16 425; CHECK-NEXT: movq %rsi, %rbx 426; CHECK-NEXT: movl %edi, %ebp 427; CHECK-NEXT: movss %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill 428; CHECK-NEXT: callq consume3@PLT 429; CHECK-NEXT: .Ltmp13: 430; CHECK-NEXT: xorps %xmm0, %xmm0 431; CHECK-NEXT: cvtsi2sd %ebp, %xmm0 432; CHECK-NEXT: movsd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill 433; CHECK-NEXT: nopl 8(%rax,%rax) 434; CHECK-NEXT: .Ltmp14: 435; CHECK-NEXT: movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload 436; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero 437; CHECK-NEXT: movss %xmm0, (%rsp) 438; CHECK-NEXT: movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 8-byte Reload 439; CHECK-NEXT: # xmm0 = mem[0],zero 440; CHECK-NEXT: movsd %xmm0, {{[0-9]+}}(%rsp) 441; CHECK-NEXT: nopl 8(%rax,%rax) 442; CHECK-NEXT: .Ltmp15: 443; CHECK-NEXT: movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload 444; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero 445; CHECK-NEXT: movss %xmm0, (%rsp) 446; CHECK-NEXT: movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 8-byte Reload 447; CHECK-NEXT: # xmm1 = mem[0],zero 448; CHECK-NEXT: movsd %xmm1, {{[0-9]+}}(%rsp) 449; CHECK-NEXT: nopl 8(%rax,%rax) 450; CHECK-NEXT: .Ltmp16: 451; CHECK-NEXT: xorl %eax, %eax 452; CHECK-NEXT: xorpd %xmm0, %xmm0 453; CHECK-NEXT: movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 8-byte Reload 454; CHECK-NEXT: # xmm1 = mem[0],zero 455; CHECK-NEXT: ucomisd %xmm0, %xmm1 456; CHECK-NEXT: movabsq $9223372036854775807, %rdi # imm = 0x7FFFFFFFFFFFFFFF 457; CHECK-NEXT: cmovbeq %rax, %rdi 458; CHECK-NEXT: movsd %xmm1, {{[0-9]+}}(%rsp) 459; CHECK-NEXT: movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload 460; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero 461; CHECK-NEXT: movss %xmm0, (%rsp) 462; CHECK-NEXT: nopl 8(%rax,%rax) 463; CHECK-NEXT: .Ltmp17: 464; CHECK-NEXT: addq $24, %rsp 465; CHECK-NEXT: .cfi_def_cfa_offset 24 466; CHECK-NEXT: popq %rbx 467; CHECK-NEXT: .cfi_def_cfa_offset 16 468; CHECK-NEXT: popq %rbp 469; CHECK-NEXT: .cfi_def_cfa_offset 8 470; CHECK-NEXT: retq 471entry: 472 %token0 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2, i32 0, ptr nonnull elementtype(void (float)) @consume3, i32 1, i32 0, float %0, i32 0, i32 0) [ "gc-live"(ptr addrspace(1) %2) ] 473 %reloc1 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token0, i32 0, i32 0) ; (%2, %2) 474 %tmp1 = sitofp i32 %1 to double 475 %to_max.i29 = fcmp ogt double %tmp1, 0.000000e+00 476 %token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2, i32 5, ptr nonnull elementtype(i32 (i32)) @consume1, i32 1, i32 0, i32 undef, i32 0, i32 0) [ "gc-live"(ptr addrspace(1) %reloc1) ] 477 %reloc2 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token1, i32 0, i32 0) ; (%reloc1, %reloc1) 478 %reloc3 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token1, i32 0, i32 0) ; (%reloc1, %reloc1) 479 %token2 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2, i32 5, ptr nonnull elementtype(i32 (i32)) @consume1, i32 1, i32 0, i32 undef, i32 0, i32 0) [ "deopt"(float %0, double %tmp1), "gc-live"(ptr addrspace(1) %reloc2, ptr addrspace(1) %reloc3) ] 480 %reloc4 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token2, i32 0, i32 0) ; (%reloc3, %reloc2) 481 %reloc5 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token2, i32 1, i32 1) ; (%reloc3, %reloc3) 482 %token3 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2, i32 5, ptr nonnull elementtype(void (float)) @consume3, i32 1, i32 0, float %0, i32 0, i32 0) [ "deopt"(float %0, double %tmp1), "gc-live"(ptr addrspace(1) %reloc4, ptr addrspace(1) %reloc5) ] 483 %reloc6 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token3, i32 1, i32 0) ; (%reloc5, %reloc4) 484 %tmp5 = select i1 %to_max.i29, i64 9223372036854775807, i64 0 485 %token4 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2, i32 5, ptr nonnull elementtype(float (i64)) @consume4, i32 1, i32 0, i64 %tmp5, i32 0, i32 0) [ "deopt"(float %0, double %tmp1), "gc-live"() ] 486ret void 487} 488 489declare token @llvm.experimental.gc.statepoint.p0(i64 immarg, i32 immarg, ptr, i32 immarg, i32 immarg, ...) 490declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32) 491declare <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token, i32, i32) 492declare i1 @llvm.experimental.gc.result.i1(token) 493