mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-15 07:59:50 +00:00
Lower statepoints with multi-def targets.
Statepoint lowering currently expects that the target method of a statepoint only defines a single value. This precludes using statepoints with ABIs that return values in multiple registers (e.g. the SysV AMD64 ABI). This change adds support for lowering statepoints with mutli-def targets. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253339 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7673d242f7
commit
4d186a129b
@ -333,13 +333,17 @@ lowerCallFromStatepoint(ImmutableStatepoint ISP, const BasicBlock *EHPadBB,
|
||||
// ch, glue = callseq_end ch, glue
|
||||
// get_return_value ch, glue
|
||||
//
|
||||
// get_return_value can either be a CopyFromReg to grab the return value from
|
||||
// %RAX, or it can be a LOAD to load a value returned by reference via a stack
|
||||
// slot.
|
||||
// get_return_value can either be a sequence of CopyFromReg instructions
|
||||
// to grab the return value from the return register(s), or it can be a LOAD
|
||||
// to load a value returned by reference via a stack slot.
|
||||
|
||||
if (HasDef && (CallEnd->getOpcode() == ISD::CopyFromReg ||
|
||||
CallEnd->getOpcode() == ISD::LOAD))
|
||||
CallEnd = CallEnd->getOperand(0).getNode();
|
||||
if (HasDef) {
|
||||
if (CallEnd->getOpcode() == ISD::LOAD)
|
||||
CallEnd = CallEnd->getOperand(0).getNode();
|
||||
else
|
||||
while (CallEnd->getOpcode() == ISD::CopyFromReg)
|
||||
CallEnd = CallEnd->getOperand(0).getNode();
|
||||
}
|
||||
|
||||
assert(CallEnd->getOpcode() == ISD::CALLSEQ_END && "expected!");
|
||||
|
||||
|
@ -5,10 +5,13 @@
|
||||
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-linux-gnu"
|
||||
|
||||
%struct = type { i64, i64 }
|
||||
|
||||
declare zeroext i1 @return_i1()
|
||||
declare zeroext i32 @return_i32()
|
||||
declare i32* @return_i32ptr()
|
||||
declare float @return_float()
|
||||
declare %struct @return_struct()
|
||||
declare void @varargf(i32, ...)
|
||||
|
||||
define i1 @test_i1_return() gc "statepoint-example" {
|
||||
@ -61,12 +64,24 @@ entry:
|
||||
ret float %call1
|
||||
}
|
||||
|
||||
define %struct @test_struct_return() gc "statepoint-example" {
|
||||
; CHECK-LABEL: test_struct_return
|
||||
; CHECK: pushq %rax
|
||||
; CHECK: callq return_struct
|
||||
; CHECK: popq %rcx
|
||||
; CHECK: retq
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (i64, i32, %struct ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_structf(i64 0, i32 0, %struct ()* @return_struct, i32 0, i32 0, i32 0, i32 0)
|
||||
%call1 = call %struct @llvm.experimental.gc.result.struct(i32 %safepoint_token)
|
||||
ret %struct %call1
|
||||
}
|
||||
|
||||
define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" {
|
||||
; CHECK-LABEL: test_relocate
|
||||
; Check that an ununsed relocate has no code-generation impact
|
||||
; CHECK: pushq %rax
|
||||
; CHECK: callq return_i1
|
||||
; CHECK-NEXT: .Ltmp9:
|
||||
; CHECK-NEXT: .Ltmp11:
|
||||
; CHECK-NEXT: popq %rdx
|
||||
; CHECK-NEXT: retq
|
||||
entry:
|
||||
@ -137,6 +152,9 @@ declare i32* @llvm.experimental.gc.result.p0i32(i32)
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_f32f(i64, i32, float ()*, i32, i32, ...)
|
||||
declare float @llvm.experimental.gc.result.f32(i32)
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_structf(i64, i32, %struct ()*, i32, i32, ...)
|
||||
declare %struct @llvm.experimental.gc.result.struct(i32)
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(i64, i32, void (i32, ...)*, i32, i32, ...)
|
||||
|
||||
declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32)
|
||||
|
Loading…
Reference in New Issue
Block a user