|  | ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | 
|  | ; RUN: llc -max-registers-for-gc-values=4 -fixup-allow-gcptr-in-csr=true < %s | FileCheck %s | 
|  |  | 
|  | target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" | 
|  | target triple = "x86_64-pc-linux-gnu" | 
|  |  | 
|  | declare i1 @return_i1() | 
|  | declare void @func() | 
|  | declare void @consume(ptr addrspace(1)) | 
|  | declare i32 @consume1(i32) gc "statepoint-example" | 
|  | declare void @consume2(ptr addrspace(1), ptr addrspace(1)) | 
|  | declare void @consume3(float) gc "statepoint-example" | 
|  | declare float @consume4(i64) gc "statepoint-example" | 
|  | declare void @consume5(ptr addrspace(1), ptr addrspace(1), ptr addrspace(1), ptr addrspace(1), ptr addrspace(1)) | 
|  |  | 
|  | declare void @use1(ptr addrspace(1), ptr addrspace(1)) | 
|  |  | 
|  | ; test most simple relocate | 
|  | define i1 @test_relocate(ptr addrspace(1) %a) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_relocate: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    pushq %rbp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    pushq %rax | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -24 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbp, -16 | 
|  | ; CHECK-NEXT:    movq %rdi, %rbx | 
|  | ; CHECK-NEXT:    callq return_i1@PLT | 
|  | ; CHECK-NEXT:  .Ltmp0: | 
|  | ; CHECK-NEXT:    movl %eax, %ebp | 
|  | ; CHECK-NEXT:    movq %rbx, %rdi | 
|  | ; CHECK-NEXT:    callq consume@PLT | 
|  | ; CHECK-NEXT:    movl %ebp, %eax | 
|  | ; CHECK-NEXT:    addq $8, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    popq %rbp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | entry: | 
|  | %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)] | 
|  | %rel1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 0, i32 0) | 
|  | %res1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token) | 
|  | call void @consume(ptr addrspace(1) %rel1) | 
|  | ret i1 %res1 | 
|  | } | 
|  |  | 
|  | ; test pointer variables intermixed with pointer constants | 
|  | define void @test_mixed(ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %c) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_mixed: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    pushq %r15 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    pushq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -32 | 
|  | ; CHECK-NEXT:    .cfi_offset %r14, -24 | 
|  | ; CHECK-NEXT:    .cfi_offset %r15, -16 | 
|  | ; CHECK-NEXT:    movq %rdx, %rbx | 
|  | ; CHECK-NEXT:    movq %rsi, %r14 | 
|  | ; CHECK-NEXT:    movq %rdi, %r15 | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp1: | 
|  | ; CHECK-NEXT:    movq %r15, %rdi | 
|  | ; CHECK-NEXT:    xorl %esi, %esi | 
|  | ; CHECK-NEXT:    movq %r14, %rdx | 
|  | ; CHECK-NEXT:    xorl %ecx, %ecx | 
|  | ; CHECK-NEXT:    movq %rbx, %r8 | 
|  | ; CHECK-NEXT:    callq consume5@PLT | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    popq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    popq %r15 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | entry: | 
|  | %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)] | 
|  | %rel1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 0, i32 0) | 
|  | %rel2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 1, i32 1) | 
|  | %rel3 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 2, i32 2) | 
|  | %rel4 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 3, i32 3) | 
|  | %rel5 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 4, i32 4) | 
|  | call void @consume5(ptr addrspace(1) %rel1, ptr addrspace(1) %rel2, ptr addrspace(1) %rel3, ptr addrspace(1) %rel4, ptr addrspace(1) %rel5) | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; same as above, but for alloca | 
|  | define ptr addrspace(1) @test_alloca(ptr addrspace(1) %ptr) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_alloca: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    pushq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    pushq %rax | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -24 | 
|  | ; CHECK-NEXT:    .cfi_offset %r14, -16 | 
|  | ; CHECK-NEXT:    movq %rdi, %rbx | 
|  | ; CHECK-NEXT:    movq %rdi, (%rsp) | 
|  | ; CHECK-NEXT:    callq return_i1@PLT | 
|  | ; CHECK-NEXT:  .Ltmp2: | 
|  | ; CHECK-NEXT:    movq (%rsp), %r14 | 
|  | ; CHECK-NEXT:    movq %rbx, %rdi | 
|  | ; CHECK-NEXT:    callq consume@PLT | 
|  | ; CHECK-NEXT:    movq %r14, %rax | 
|  | ; CHECK-NEXT:    addq $8, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    popq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | entry: | 
|  | %alloca = alloca ptr addrspace(1), align 8 | 
|  | store ptr addrspace(1) %ptr, ptr %alloca | 
|  | %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)] | 
|  | %rel1 = load ptr addrspace(1), ptr %alloca | 
|  | %rel2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 1, i32 1) | 
|  | call void @consume(ptr addrspace(1) %rel2) | 
|  | ret ptr addrspace(1) %rel1 | 
|  | } | 
|  |  | 
|  | ; test base != derived | 
|  | define void @test_base_derived(ptr addrspace(1) %base, ptr addrspace(1) %derived) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_base_derived: | 
|  | ; CHECK:       # %bb.0: | 
|  | ; CHECK-NEXT:    pushq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    pushq %rax | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -24 | 
|  | ; CHECK-NEXT:    .cfi_offset %r14, -16 | 
|  | ; CHECK-NEXT:    movq %rsi, %rbx | 
|  | ; CHECK-NEXT:    movq %rdi, %r14 | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp3: | 
|  | ; CHECK-NEXT:    movq %rbx, %rdi | 
|  | ; CHECK-NEXT:    callq consume@PLT | 
|  | ; CHECK-NEXT:    addq $8, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    popq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | %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)] | 
|  | %reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 0, i32 1) | 
|  | call void @consume(ptr addrspace(1) %reloc) | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; deopt GC pointer not present in GC args goes on reg. | 
|  | define void @test_deopt_gcpointer(ptr addrspace(1) %a, ptr addrspace(1) %b) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_deopt_gcpointer: | 
|  | ; CHECK:       # %bb.0: | 
|  | ; CHECK-NEXT:    pushq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    pushq %rax | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -24 | 
|  | ; CHECK-NEXT:    .cfi_offset %r14, -16 | 
|  | ; CHECK-NEXT:    movq %rsi, %rbx | 
|  | ; CHECK-NEXT:    movq %rdi, %r14 | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp4: | 
|  | ; CHECK-NEXT:    movq %rbx, %rdi | 
|  | ; CHECK-NEXT:    callq consume@PLT | 
|  | ; CHECK-NEXT:    addq $8, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    popq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | %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)] | 
|  | %rel = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 0, i32 0) | 
|  | call void @consume(ptr addrspace(1) %rel) | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ;; Two gc.relocates of the same input, should require only a single spill/fill | 
|  | define void @test_gcrelocate_uniqueing(ptr addrspace(1) %ptr) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_gcrelocate_uniqueing: | 
|  | ; CHECK:       # %bb.0: | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -16 | 
|  | ; CHECK-NEXT:    movq %rdi, %rbx | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp5: | 
|  | ; CHECK-NEXT:    movq %rbx, %rdi | 
|  | ; CHECK-NEXT:    movq %rbx, %rsi | 
|  | ; CHECK-NEXT:    callq consume2@PLT | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | %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)] | 
|  | %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0) | 
|  | %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 1, i32 1) | 
|  | call void @consume2(ptr addrspace(1) %a, ptr addrspace(1) %b) | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; Two gc.relocates of a bitcasted pointer should only require a single spill/fill | 
|  | define void @test_gcptr_uniqueing(ptr addrspace(1) %ptr) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_gcptr_uniqueing: | 
|  | ; CHECK:       # %bb.0: | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -16 | 
|  | ; CHECK-NEXT:    movq %rdi, %rbx | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp6: | 
|  | ; CHECK-NEXT:    movq %rbx, %rdi | 
|  | ; CHECK-NEXT:    movq %rbx, %rsi | 
|  | ; CHECK-NEXT:    callq use1@PLT | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | %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)] | 
|  | %a = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0) | 
|  | %b = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 1, i32 1) | 
|  | call void @use1(ptr addrspace(1) %a, ptr addrspace(1) %b) | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; | 
|  | ; Cross-basicblock relocates are handled with spilling for now. | 
|  | define i1 @test_cross_bb(ptr addrspace(1) %a, i1 %external_cond) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_cross_bb: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    pushq %rbp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    pushq %rax | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -24 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbp, -16 | 
|  | ; CHECK-NEXT:    movl %esi, %ebp | 
|  | ; CHECK-NEXT:    movq %rdi, %rbx | 
|  | ; CHECK-NEXT:    callq return_i1@PLT | 
|  | ; CHECK-NEXT:  .Ltmp7: | 
|  | ; CHECK-NEXT:    testb $1, %bpl | 
|  | ; CHECK-NEXT:    je .LBB7_2 | 
|  | ; CHECK-NEXT:  # %bb.1: # %left | 
|  | ; CHECK-NEXT:    movq %rbx, %rdi | 
|  | ; CHECK-NEXT:    movl %eax, %ebx | 
|  | ; CHECK-NEXT:    callq consume@PLT | 
|  | ; CHECK-NEXT:    movl %ebx, %eax | 
|  | ; CHECK-NEXT:    jmp .LBB7_3 | 
|  | ; CHECK-NEXT:  .LBB7_2: # %right | 
|  | ; CHECK-NEXT:    movb $1, %al | 
|  | ; CHECK-NEXT:  .LBB7_3: # %right | 
|  | ; CHECK-NEXT:    addq $8, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    popq %rbp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | entry: | 
|  | %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)] | 
|  | br i1 %external_cond, label %left, label %right | 
|  |  | 
|  | left: | 
|  | %call1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 0, i32 0) | 
|  | %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token) | 
|  | call void @consume(ptr addrspace(1) %call1) | 
|  | ret i1 %call2 | 
|  |  | 
|  | right: | 
|  | ret i1 true | 
|  | } | 
|  |  | 
|  | ; No need to check post-regalloc output as it is the same | 
|  | define i1 @duplicate_reloc() gc "statepoint-example" { | 
|  | ; CHECK-LABEL: duplicate_reloc: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    pushq %rax | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp8: | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp9: | 
|  | ; CHECK-NEXT:    movb $1, %al | 
|  | ; CHECK-NEXT:    popq %rcx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | entry: | 
|  | %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)] | 
|  | %base = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 0, i32 0) | 
|  | %derived = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 0, i32 1) | 
|  | %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)] | 
|  | %base_reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token2,  i32 0, i32 0) | 
|  | %derived_reloc = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token2,  i32 0, i32 1) | 
|  | %cmp1 = icmp eq ptr addrspace(1) %base_reloc, null | 
|  | %cmp2 = icmp eq ptr addrspace(1) %derived_reloc, null | 
|  | %cmp = and i1 %cmp1, %cmp2 | 
|  | ret i1 %cmp | 
|  | } | 
|  |  | 
|  | ; Vectors cannot go in VRegs | 
|  | ; No need to check post-regalloc output as it is lowered using old scheme | 
|  | define <2 x ptr addrspace(1)> @test_vector(<2 x ptr addrspace(1)> %obj) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_vector: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    subq $24, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32 | 
|  | ; CHECK-NEXT:    movaps %xmm0, (%rsp) | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp10: | 
|  | ; CHECK-NEXT:    movaps (%rsp), %xmm0 | 
|  | ; CHECK-NEXT:    addq $24, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | entry: | 
|  | %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)] | 
|  | %obj.relocated = call coldcc <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token %safepoint_token, i32 0, i32 0) ; (%obj, %obj) | 
|  | ret <2 x ptr addrspace(1)> %obj.relocated | 
|  | } | 
|  |  | 
|  |  | 
|  | ; test limit on amount of vregs | 
|  | define 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" { | 
|  | ; CHECK-LABEL: test_limit: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    pushq %r15 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    pushq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    pushq %r12 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32 | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 40 | 
|  | ; CHECK-NEXT:    pushq %rax | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 48 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -40 | 
|  | ; CHECK-NEXT:    .cfi_offset %r12, -32 | 
|  | ; CHECK-NEXT:    .cfi_offset %r14, -24 | 
|  | ; CHECK-NEXT:    .cfi_offset %r15, -16 | 
|  | ; CHECK-NEXT:    movq %r8, %rbx | 
|  | ; CHECK-NEXT:    movq %rcx, %r14 | 
|  | ; CHECK-NEXT:    movq %rdx, %r15 | 
|  | ; CHECK-NEXT:    movq %rsi, %r12 | 
|  | ; CHECK-NEXT:    movq %rdi, (%rsp) | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp11: | 
|  | ; CHECK-NEXT:    movq (%rsp), %rdi | 
|  | ; CHECK-NEXT:    movq %r12, %rsi | 
|  | ; CHECK-NEXT:    movq %r15, %rdx | 
|  | ; CHECK-NEXT:    movq %r14, %rcx | 
|  | ; CHECK-NEXT:    movq %rbx, %r8 | 
|  | ; CHECK-NEXT:    callq consume5@PLT | 
|  | ; CHECK-NEXT:    addq $8, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 40 | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32 | 
|  | ; CHECK-NEXT:    popq %r12 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    popq %r14 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    popq %r15 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | entry: | 
|  | %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)] | 
|  | %rel1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 0, i32 0) | 
|  | %rel2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 1, i32 1) | 
|  | %rel3 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 2, i32 2) | 
|  | %rel4 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 3, i32 3) | 
|  | %rel5 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token,  i32 4, i32 4) | 
|  | call void @consume5(ptr addrspace(1) %rel1, ptr addrspace(1) %rel2, ptr addrspace(1) %rel3, ptr addrspace(1) %rel4, ptr addrspace(1) %rel5) | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; test ISEL for constant base pointer - must properly tie operands | 
|  | define void @test_const_base(ptr addrspace(1) %a) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_const_base: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -16 | 
|  | ; CHECK-NEXT:    movq %rdi, %rbx | 
|  | ; CHECK-NEXT:    callq func@PLT | 
|  | ; CHECK-NEXT:  .Ltmp12: | 
|  | ; CHECK-NEXT:    movq %rbx, %rdi | 
|  | ; CHECK-NEXT:    callq consume@PLT | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | entry: | 
|  | %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)] | 
|  | %rel = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token1,  i32 0, i32 1) | 
|  | call void @consume(ptr addrspace(1) %rel) | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; test multiple statepoints/relocates within single block. | 
|  | ; relocates must be properly scheduled w.r.t. statepoints | 
|  | define void @test_sched(float %0, i32 %1, ptr addrspace(1) %2) gc "statepoint-example" { | 
|  | ; CHECK-LABEL: test_sched: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    pushq %rbp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    pushq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    subq $24, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 48 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbx, -24 | 
|  | ; CHECK-NEXT:    .cfi_offset %rbp, -16 | 
|  | ; CHECK-NEXT:    movq %rsi, %rbx | 
|  | ; CHECK-NEXT:    movl %edi, %ebp | 
|  | ; CHECK-NEXT:    movss %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill | 
|  | ; CHECK-NEXT:    callq consume3@PLT | 
|  | ; CHECK-NEXT:  .Ltmp13: | 
|  | ; CHECK-NEXT:    xorps %xmm0, %xmm0 | 
|  | ; CHECK-NEXT:    cvtsi2sd %ebp, %xmm0 | 
|  | ; CHECK-NEXT:    movsd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill | 
|  | ; CHECK-NEXT:    nopl 8(%rax,%rax) | 
|  | ; CHECK-NEXT:  .Ltmp14: | 
|  | ; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload | 
|  | ; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero | 
|  | ; CHECK-NEXT:    movss %xmm0, (%rsp) | 
|  | ; CHECK-NEXT:    movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 8-byte Reload | 
|  | ; CHECK-NEXT:    # xmm0 = mem[0],zero | 
|  | ; CHECK-NEXT:    movsd %xmm0, {{[0-9]+}}(%rsp) | 
|  | ; CHECK-NEXT:    nopl 8(%rax,%rax) | 
|  | ; CHECK-NEXT:  .Ltmp15: | 
|  | ; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload | 
|  | ; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero | 
|  | ; CHECK-NEXT:    movss %xmm0, (%rsp) | 
|  | ; CHECK-NEXT:    movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 8-byte Reload | 
|  | ; CHECK-NEXT:    # xmm1 = mem[0],zero | 
|  | ; CHECK-NEXT:    movsd %xmm1, {{[0-9]+}}(%rsp) | 
|  | ; CHECK-NEXT:    nopl 8(%rax,%rax) | 
|  | ; CHECK-NEXT:  .Ltmp16: | 
|  | ; CHECK-NEXT:    xorl %eax, %eax | 
|  | ; CHECK-NEXT:    xorpd %xmm0, %xmm0 | 
|  | ; CHECK-NEXT:    movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 8-byte Reload | 
|  | ; CHECK-NEXT:    # xmm1 = mem[0],zero | 
|  | ; CHECK-NEXT:    ucomisd %xmm0, %xmm1 | 
|  | ; CHECK-NEXT:    movabsq $9223372036854775807, %rdi # imm = 0x7FFFFFFFFFFFFFFF | 
|  | ; CHECK-NEXT:    cmovbeq %rax, %rdi | 
|  | ; CHECK-NEXT:    movsd %xmm1, {{[0-9]+}}(%rsp) | 
|  | ; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload | 
|  | ; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero | 
|  | ; CHECK-NEXT:    movss %xmm0, (%rsp) | 
|  | ; CHECK-NEXT:    nopl 8(%rax,%rax) | 
|  | ; CHECK-NEXT:  .Ltmp17: | 
|  | ; CHECK-NEXT:    addq $24, %rsp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24 | 
|  | ; CHECK-NEXT:    popq %rbx | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 16 | 
|  | ; CHECK-NEXT:    popq %rbp | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8 | 
|  | ; CHECK-NEXT:    retq | 
|  | entry: | 
|  | %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) ] | 
|  | %reloc1 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token0, i32 0, i32 0) ; (%2, %2) | 
|  | %tmp1 = sitofp i32 %1 to double | 
|  | %to_max.i29 = fcmp ogt double %tmp1, 0.000000e+00 | 
|  | %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) ] | 
|  | %reloc2 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token1, i32 0, i32 0) ; (%reloc1, %reloc1) | 
|  | %reloc3 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token1, i32 0, i32 0) ; (%reloc1, %reloc1) | 
|  | %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) ] | 
|  | %reloc4 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token2, i32 0, i32 0) ; (%reloc3, %reloc2) | 
|  | %reloc5 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token2, i32 1, i32 1) ; (%reloc3, %reloc3) | 
|  | %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) ] | 
|  | %reloc6 = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token3, i32 1, i32 0) ; (%reloc5, %reloc4) | 
|  | %tmp5 = select i1 %to_max.i29, i64 9223372036854775807, i64 0 | 
|  | %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"() ] | 
|  | ret void | 
|  | } | 
|  |  | 
|  | declare token @llvm.experimental.gc.statepoint.p0(i64 immarg, i32 immarg, ptr, i32 immarg, i32 immarg, ...) | 
|  | declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32) | 
|  | declare <2 x ptr addrspace(1)> @llvm.experimental.gc.relocate.v2p1(token, i32, i32) | 
|  | declare i1 @llvm.experimental.gc.result.i1(token) |