
Snippet is a tiny live interval which has copy or fill like def and copy or spill like use at the end (any of them might abcent). Snippet has only one use/def inside interval and interval is located in one basic block. When inline spiller spills some reg around uses it also forces the spilling of connected snippets those which got by splitting the same original reg and its def is a full copy of our reg or its last use is a full copy to our reg. The definition of snippet is extended to allow not only one use/def but more. However all other uses are statepoint instructions which will fold fill into its operand. That way we do not introduce new fills/spills. Reviewed By: qcolombet, dantrushin Differential Revision: https://reviews.llvm.org/D138093
80 lines
3.2 KiB
LLVM
80 lines
3.2 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -max-registers-for-gc-values=256 -use-registers-for-deopt-values=true -code-model=large -fixup-allow-gcptr-in-csr=true < %s | FileCheck %s
|
|
|
|
; The test checks that Greedy register allocator should not split single basic block
|
|
; if it has only one non-statepoint use. Otherwise we may a redundant register usage.
|
|
|
|
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-pc-win64"
|
|
|
|
define ptr addrspace(1) @foo(ptr addrspace(1) %arg) gc "statepoint-example" {
|
|
; CHECK-LABEL: foo:
|
|
; CHECK: # %bb.0: # %entry
|
|
; CHECK-NEXT: pushq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 16
|
|
; CHECK-NEXT: pushq %r15
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 24
|
|
; CHECK-NEXT: pushq %r14
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 32
|
|
; CHECK-NEXT: pushq %r13
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 40
|
|
; CHECK-NEXT: pushq %r12
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 48
|
|
; CHECK-NEXT: pushq %rbx
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 56
|
|
; CHECK-NEXT: pushq %rax
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 64
|
|
; CHECK-NEXT: .cfi_offset %rbx, -56
|
|
; CHECK-NEXT: .cfi_offset %r12, -48
|
|
; CHECK-NEXT: .cfi_offset %r13, -40
|
|
; CHECK-NEXT: .cfi_offset %r14, -32
|
|
; CHECK-NEXT: .cfi_offset %r15, -24
|
|
; CHECK-NEXT: .cfi_offset %rbp, -16
|
|
; CHECK-NEXT: movq %rdi, (%rsp) # 8-byte Spill
|
|
; CHECK-NEXT: movabsq $nocsr, %rax
|
|
; CHECK-NEXT: callq *%rax
|
|
; CHECK-NEXT: movabsq $bar, %rax
|
|
; CHECK-NEXT: movq (%rsp), %rdi # 8-byte Reload
|
|
; CHECK-NEXT: callq *%rax # 8-byte Folded Reload
|
|
; CHECK-NEXT: .Ltmp0:
|
|
; CHECK-NEXT: movabsq $nocsr, %rax
|
|
; CHECK-NEXT: callq *%rax
|
|
; CHECK-NEXT: movq (%rsp), %rax # 8-byte Reload
|
|
; CHECK-NEXT: addq $8, %rsp
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 56
|
|
; CHECK-NEXT: popq %rbx
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 48
|
|
; CHECK-NEXT: popq %r12
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 40
|
|
; CHECK-NEXT: popq %r13
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 32
|
|
; CHECK-NEXT: popq %r14
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 24
|
|
; CHECK-NEXT: popq %r15
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 16
|
|
; CHECK-NEXT: popq %rbp
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 8
|
|
; CHECK-NEXT: retq
|
|
entry:
|
|
; force spill %arg on stack.
|
|
call void @nocsr()
|
|
br label %do_call
|
|
|
|
do_call:
|
|
; Basic block with two use intructions inside:
|
|
; copy to rdi as an argument to call and use in statepoint instruction as gc-live and deopt value.
|
|
%statepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void (ptr addrspace(1))) @bar, i32 1, i32 0, ptr addrspace(1) %arg, i32 0, i32 0) [ "deopt"(ptr addrspace(1) %arg), "gc-live"(ptr addrspace(1) %arg) ]
|
|
%arg.reloc = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %statepoint_token, i32 0, i32 0)
|
|
br label %next
|
|
|
|
next:
|
|
; force spill %arg.reloc on stack.
|
|
call void @nocsr()
|
|
ret ptr addrspace(1) %arg.reloc
|
|
}
|
|
|
|
declare void @nocsr() "no_callee_saved_registers"
|
|
declare void @bar(ptr addrspace(1))
|
|
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 immarg, i32 immarg)
|