mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
Allow explicit spill slots to be specified for a gc.statepoint
This patch adds support for explicitly provided spill slots in the GC arguments of a gc.statepoint. This is somewhat analogous to gcroot, but leverages the STATEPOINT MI node and StackMap infrastructure. The motivation for this is: 1) The stack spilling code for gc.statepoints hasn't advanced as fast as I'd like. One major option is to give up on doing spilling in the backend and do it at the IR level instead. We'd give up the ability to have gc values in registers, but that's a minor cost in practice. We are not neccessarily moving in that direction, but having the ability to prototype such a thing cheaply is interesting. 2) I want to port the gcroot lowering to use the statepoint infastructure. Given the metadata printers for gcroot expect a fixed set of stack roots, it's easiest to just reuse the explicit stack slots and pass them directly to the underlying statepoint. I'm holding off on the documentation for the new feature until I'm reasonable sure this is going to stick around. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233356 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b827c4b923
commit
28ffcd3f1e
@ -397,10 +397,11 @@ static void lowerIncomingStatepointValue(SDValue Incoming,
|
||||
Builder.DAG.getTargetConstant(StackMaps::ConstantOp, MVT::i64));
|
||||
Ops.push_back(Builder.DAG.getTargetConstant(C->getSExtValue(), MVT::i64));
|
||||
} else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Incoming)) {
|
||||
// This handles allocas as arguments to the statepoint
|
||||
const TargetLowering &TLI = Builder.DAG.getTargetLoweringInfo();
|
||||
Ops.push_back(
|
||||
Builder.DAG.getTargetFrameIndex(FI->getIndex(), TLI.getPointerTy()));
|
||||
// This handles allocas as arguments to the statepoint (this is only
|
||||
// really meaningful for a deopt value. For GC, we'd be trying to
|
||||
// relocate the address of the alloca itself?)
|
||||
Ops.push_back(Builder.DAG.getTargetFrameIndex(FI->getIndex(),
|
||||
Incoming.getValueType()));
|
||||
} else {
|
||||
// Otherwise, locate a spill slot and explicitly spill it so it
|
||||
// can be found by the runtime later. We currently do not support
|
||||
@ -523,6 +524,21 @@ static void lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
|
||||
SDValue Incoming = Builder.getValue(V);
|
||||
lowerIncomingStatepointValue(Incoming, Ops, Builder);
|
||||
}
|
||||
|
||||
// If there are any explicit spill slots passed to the statepoint, record
|
||||
// them, but otherwise do not do anything special. These are user provided
|
||||
// allocas and give control over placement to the consumer. In this case,
|
||||
// it is the contents of the slot which may get updated, not the pointer to
|
||||
// the alloca
|
||||
for (Value *V : StatepointSite.gc_args()) {
|
||||
SDValue Incoming = Builder.getValue(V);
|
||||
if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Incoming)) {
|
||||
// This handles allocas as arguments to the statepoint
|
||||
Ops.push_back(Builder.DAG.getTargetFrameIndex(FI->getIndex(),
|
||||
Incoming.getValueType()));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitStatepoint(const CallInst &CI) {
|
||||
|
121
test/CodeGen/X86/statepoint-allocas.ll
Normal file
121
test/CodeGen/X86/statepoint-allocas.ll
Normal file
@ -0,0 +1,121 @@
|
||||
; RUN: llc < %s | FileCheck %s
|
||||
; Check that we can lower a use of an alloca both as a deopt value (where the
|
||||
; exact meaning is up to the consumer of the stackmap) and as an explicit spill
|
||||
; slot used for GC.
|
||||
|
||||
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-linux-gnu"
|
||||
|
||||
declare zeroext i1 @return_i1()
|
||||
|
||||
; Can we handle an explicit relocation slot (in the form of an alloca) given
|
||||
; to the statepoint?
|
||||
define i32 addrspace(1)* @test(i32 addrspace(1)* %ptr) gc "statepoint-example" {
|
||||
; CHECK-LABEL: test
|
||||
; CHECK: pushq %rax
|
||||
; CHECK: movq %rdi, (%rsp)
|
||||
; CHECK: callq return_i1
|
||||
; CHECK: movq (%rsp), %rax
|
||||
; CHECK: popq %rdx
|
||||
; CHECK: retq
|
||||
entry:
|
||||
%alloca = alloca i32 addrspace(1)*, align 8
|
||||
store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca
|
||||
call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)** %alloca)
|
||||
%rel = load i32 addrspace(1)*, i32 addrspace(1)** %alloca
|
||||
ret i32 addrspace(1)* %rel
|
||||
}
|
||||
|
||||
; Can we handle an alloca as a deopt value?
|
||||
define i32 addrspace(1)* @test2(i32 addrspace(1)* %ptr) gc "statepoint-example" {
|
||||
; CHECK-LABEL: test2
|
||||
; CHECK: pushq %rax
|
||||
; CHECK: movq %rdi, (%rsp)
|
||||
; CHECK: callq return_i1
|
||||
; CHECK: xorl %eax, %eax
|
||||
; CHECK: popq %rdx
|
||||
; CHECK: retq
|
||||
entry:
|
||||
%alloca = alloca i32 addrspace(1)*, align 8
|
||||
store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca
|
||||
call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 1, i32 addrspace(1)** %alloca)
|
||||
ret i32 addrspace(1)* null
|
||||
}
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
|
||||
|
||||
|
||||
; CHECK-LABEL: .section .llvm_stackmaps
|
||||
; CHECK-NEXT: __LLVM_StackMaps:
|
||||
; Header
|
||||
; CHECK-NEXT: .byte 1
|
||||
; CHECK-NEXT: .byte 0
|
||||
; CHECK-NEXT: .short 0
|
||||
; Num Functions
|
||||
; CHECK-NEXT: .long 2
|
||||
; Num LargeConstants
|
||||
; CHECK-NEXT: .long 0
|
||||
; Num Callsites
|
||||
; CHECK-NEXT: .long 2
|
||||
|
||||
; Functions and stack size
|
||||
; CHECK-NEXT: .quad test
|
||||
; CHECK-NEXT: .quad 8
|
||||
; CHECK-NEXT: .quad test2
|
||||
; CHECK-NEXT: .quad 8
|
||||
|
||||
; Large Constants
|
||||
; Statepoint ID only
|
||||
; CHECK: .quad 2882400000
|
||||
|
||||
; Callsites
|
||||
; The GC one
|
||||
; CHECK: .long .Ltmp1-test
|
||||
; CHECK: .short 0
|
||||
; CHECK: .short 3
|
||||
; SmallConstant (0)
|
||||
; CHECK: .byte 4
|
||||
; CHECK: .byte 8
|
||||
; CHECK: .short 0
|
||||
; CHECK: .long 0
|
||||
; SmallConstant (0)
|
||||
; CHECK: .byte 4
|
||||
; CHECK: .byte 8
|
||||
; CHECK: .short 0
|
||||
; CHECK: .long 0
|
||||
; Direct Spill Slot [RSP+0]
|
||||
; CHECK: .byte 2
|
||||
; CHECK: .byte 8
|
||||
; CHECK: .short 7
|
||||
; CHECK: .long 0
|
||||
; No Padding or LiveOuts
|
||||
; CHECK: .short 0
|
||||
; CHECK: .short 0
|
||||
; CHECK: .align 8
|
||||
|
||||
; The Deopt one
|
||||
; CHECK: .long .Ltmp3-test2
|
||||
; CHECK: .short 0
|
||||
; CHECK: .short 3
|
||||
; SmallConstant (0)
|
||||
; CHECK: .byte 4
|
||||
; CHECK: .byte 8
|
||||
; CHECK: .short 0
|
||||
; CHECK: .long 0
|
||||
; SmallConstant (1)
|
||||
; CHECK: .byte 4
|
||||
; CHECK: .byte 8
|
||||
; CHECK: .short 0
|
||||
; CHECK: .long 1
|
||||
; Direct Spill Slot [RSP+0]
|
||||
; CHECK: .byte 2
|
||||
; CHECK: .byte 8
|
||||
; CHECK: .short 7
|
||||
; CHECK: .long 0
|
||||
|
||||
; No Padding or LiveOuts
|
||||
; CHECK: .short 0
|
||||
; CHECK: .short 0
|
||||
; CHECK: .align 8
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user