From 4d186a129b13aab048e427c7f0cb64903e6e2d83 Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Tue, 17 Nov 2015 16:04:21 +0000 Subject: [PATCH] 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 --- lib/CodeGen/SelectionDAG/StatepointLowering.cpp | 18 +++++++++++------- test/CodeGen/X86/statepoint-call-lowering.ll | 20 +++++++++++++++++++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index 05024063392..a74d15371ca 100644 --- a/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -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. - - if (HasDef && (CallEnd->getOpcode() == ISD::CopyFromReg || - CallEnd->getOpcode() == ISD::LOAD)) - CallEnd = CallEnd->getOperand(0).getNode(); + // 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) { + 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!"); diff --git a/test/CodeGen/X86/statepoint-call-lowering.ll b/test/CodeGen/X86/statepoint-call-lowering.ll index 46d3cafa35b..14e7da721ca 100644 --- a/test/CodeGen/X86/statepoint-call-lowering.ll +++ b/test/CodeGen/X86/statepoint-call-lowering.ll @@ -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) -- 2.11.0