[CodeGen] Prefer static frame index for STATEPOINT liveness args

Summary:
If a given liveness arg of STATEPOINT is at a fixed frame index
(e.g. a function argument passed on stack), prefer to use this
fixed location even the address is also in a register. If we use
the register it will generate a spill, which is not necessary
since the fixed frame index can be directly recorded in the stack
map.

Patch by Cherry Zhang <cherryyz@google.com>.

Reviewers: thanm, niravd, reames

Reviewed By: reames

Subscribers: cherryyz, reames, anna, arphaman, llvm-commits

Differential Revision: https://reviews.llvm.org/D53889

llvm-svn: 347998
This commit is contained in:
Than McIntosh 2018-11-30 16:22:41 +00:00
parent 3689747619
commit 0e0a8a3fee
2 changed files with 95 additions and 3 deletions

View File

@ -522,7 +522,16 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
// The vm state arguments are lowered in an opaque manner. We do not know
// what type of values are contained within.
for (const Value *V : SI.DeoptState) {
SDValue Incoming = Builder.getValue(V);
SDValue Incoming;
// If this is a function argument at a static frame index, generate it as
// the frame index.
if (const Argument *Arg = dyn_cast<Argument>(V)) {
int FI = Builder.FuncInfo.getArgumentFrameIndex(Arg);
if (FI != INT_MAX)
Incoming = Builder.DAG.getFrameIndex(FI, Builder.getFrameIndexTy());
}
if (!Incoming.getNode())
Incoming = Builder.getValue(V);
const bool LiveInValue = LiveInDeopt && !isGCValue(V);
lowerIncomingStatepointValue(Incoming, LiveInValue, Ops, Builder);
}

View File

@ -96,9 +96,33 @@ define i32 @test_spadj(i32 addrspace(1)* %p) gc "statepoint-example" {
ret i32 %ld
}
; Test that function arguments at fixed stack offset
; can be directly encoded in the stack map, without
; spilling.
%struct = type { i64, i64, i64 }
declare void @use(%struct*)
define void @test_fixed_arg(%struct* byval %x) gc "statepoint-example" {
; CHECK-LABEL: test_fixed_arg
; CHECK: pushq %rax
; CHECK: leaq 16(%rsp), %rdi
; Should not spill fixed stack address.
; CHECK-NOT: movq %rdi, (%rsp)
; CHECK: callq use
; CHECK: popq %rax
; CHECK: retq
entry:
br label %bb
bb: ; preds = %entry
%statepoint_token = call token (i64, i32, void (%struct*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64 0, i32 0, void (%struct*)* @use, i32 1, i32 0, %struct* %x, i32 0, i32 1, %struct* %x)
ret void
}
declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...)
declare token @llvm.experimental.gc.statepoint.p0f_isVoidi64i64i64i64i64i64i64i64f(i64, i32, void (i64, i64, i64, i64, i64, i64, i64, i64)*, i32, i32, ...)
declare token @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64, i32, void (%struct*)*, i32, i32, ...)
declare i1 @llvm.experimental.gc.result.i1(token)
declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) #3
@ -109,11 +133,11 @@ declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; CHECK-NEXT: .long 4
; CHECK-NEXT: .long 5
; Num LargeConstants
; CHECK-NEXT: .long 0
; Num Callsites
; CHECK-NEXT: .long 4
; CHECK-NEXT: .long 5
; Functions and stack size
; CHECK-NEXT: .quad test
@ -128,6 +152,9 @@ declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
; CHECK-NEXT: .quad test_spadj
; CHECK-NEXT: .quad 8
; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad test_fixed_arg
; CHECK-NEXT: .quad 8
; CHECK-NEXT: .quad 1
;
; test
@ -421,3 +448,59 @@ declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
; CHECK: .short 0
; CHECK: .short 0
; CHECK: .p2align 3
;
; test_fixed_arg
; Statepoint ID
; CHECK-NEXT: .quad 0
; Instruction Offset
; CHECK-NEXT: .long .Ltmp4-test_fixed_arg
; Reserved:
; CHECK: .short 0
; NumLocations:
; CHECK: .short 4
; StkMapRecord[0]:
; SmallConstant(0):
; CHECK: .byte 4
; CHECK-NEXT: .byte 0
; CHECK: .short 8
; CHECK: .short 0
; CHECK-NEXT: .short 0
; CHECK: .long 0
; StkMapRecord[1]:
; SmallConstant(0):
; CHECK: .byte 4
; CHECK-NEXT: .byte 0
; CHECK: .short 8
; CHECK: .short 0
; CHECK-NEXT: .short 0
; CHECK: .long 0
; StkMapRecord[2]:
; SmallConstant(1):
; CHECK: .byte 4
; CHECK-NEXT: .byte 0
; CHECK: .short 8
; CHECK: .short 0
; CHECK-NEXT: .short 0
; CHECK: .long 1
; StkMapRecord[3]:
; Direct RSP+16
; CHECK: .byte 2
; CHECK-NEXT: .byte 0
; CHECK: .short 8
; CHECK: .short 7
; CHECK-NEXT: .short 0
; CHECK: .long 16
; No padding or LiveOuts
; CHECK: .short 0
; CHECK: .short 0
; CHECK: .p2align 3