forked from OSchip/llvm-project
[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:
parent
3689747619
commit
0e0a8a3fee
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue