[llvm] r253339 - Lower statepoints with multi-def targets.

Pat Gavlin via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 17 08:04:22 PST 2015


Author: pgavlin
Date: Tue Nov 17 10:04:21 2015
New Revision: 253339

URL: http://llvm.org/viewvc/llvm-project?rev=253339&view=rev
Log:
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.

Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
    llvm/trunk/test/CodeGen/X86/statepoint-call-lowering.ll

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp?rev=253339&r1=253338&r2=253339&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp Tue Nov 17 10:04:21 2015
@@ -333,13 +333,17 @@ lowerCallFromStatepoint(ImmutableStatepo
   //   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!");
 

Modified: llvm/trunk/test/CodeGen/X86/statepoint-call-lowering.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/statepoint-call-lowering.ll?rev=253339&r1=253338&r2=253339&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/statepoint-call-lowering.ll (original)
+++ llvm/trunk/test/CodeGen/X86/statepoint-call-lowering.ll Tue Nov 17 10:04:21 2015
@@ -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.resul
 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)




More information about the llvm-commits mailing list