Add support for multiple return values for the PPC target by
authorDan Gohman <gohman@apple.com>
Wed, 19 Mar 2008 21:39:28 +0000 (21:39 +0000)
committerDan Gohman <gohman@apple.com>
Wed, 19 Mar 2008 21:39:28 +0000 (21:39 +0000)
converting call result lowering to use the CallingConvLowering
infastructure.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48552 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/PowerPC/PPCISelLowering.h
test/CodeGen/PowerPC/multiple-return-values.ll [new file with mode: 0644]

index 88d4b5f63d7d866e2183f77a70b0c3c9a4cbedf6..d8f7400c2ae21acfc7d462c159783c5f83fff53e 100644 (file)
@@ -1747,7 +1747,8 @@ CreateCopyOfByValArgument(SDOperand Src, SDOperand Dst, SDOperand Chain,
 }
 
 SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG,
-                                       const PPCSubtarget &Subtarget) {
+                                       const PPCSubtarget &Subtarget,
+                                       TargetMachine &TM) {
   SDOperand Chain  = Op.getOperand(0);
   bool isVarArg    = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
   SDOperand Callee = Op.getOperand(4);
@@ -2184,155 +2185,30 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG,
   if (Op.Val->getValueType(0) != MVT::Other)
     InFlag = Chain.getValue(1);
 
-  SDOperand ResultVals[9];
-  unsigned NumResults = 0;
-  NodeTys.clear();
+  SmallVector<SDOperand, 16> ResultVals;
+  SmallVector<CCValAssign, 16> RVLocs;
+  unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
+  CCState CCInfo(CC, isVarArg, TM, RVLocs);
+  CCInfo.AnalyzeCallResult(Op.Val, RetCC_PPC);
   
-  // If the call has results, copy the values out of the ret val registers.
-  switch (Op.Val->getValueType(0)) {
-  default: assert(0 && "Unexpected ret value!");
-  case MVT::Other: break;
-  case MVT::i32:
-    // There are 8 result regs for Complex double, and 4 for Complex long long.
-    if (Op.Val->getNumValues()>=8 && Op.Val->getValueType(7) == MVT::i32) {
-      Chain = DAG.getCopyFromReg(Chain, PPC::R3, MVT::i32, InFlag).getValue(1);
-      ResultVals[0] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R4, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[1] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R5, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[2] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R6, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[3] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R7, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[4] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R8, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[5] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R9, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[6] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R10, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[7] = Chain.getValue(0);
-      NumResults = 8;
-      NodeTys.push_back(MVT::i32);
-      NodeTys.push_back(MVT::i32);
-      NodeTys.push_back(MVT::i32);
-      NodeTys.push_back(MVT::i32);
-      NodeTys.push_back(MVT::i32);
-      NodeTys.push_back(MVT::i32);
-      NodeTys.push_back(MVT::i32);
-    } else if (Op.Val->getNumValues()>=4 && 
-               Op.Val->getValueType(3) == MVT::i32) {
-      Chain = DAG.getCopyFromReg(Chain, PPC::R3, MVT::i32, InFlag).getValue(1);
-      ResultVals[0] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R4, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[1] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R5, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[2] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R6, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[3] = Chain.getValue(0);
-      NumResults = 4;
-      NodeTys.push_back(MVT::i32);
-      NodeTys.push_back(MVT::i32);
-      NodeTys.push_back(MVT::i32);
-    } else if (Op.Val->getValueType(1) == MVT::i32) {
-      Chain = DAG.getCopyFromReg(Chain, PPC::R3, MVT::i32, InFlag).getValue(1);
-      ResultVals[0] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::R4, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[1] = Chain.getValue(0);
-      NumResults = 2;
-      NodeTys.push_back(MVT::i32);
-    } else {
-      Chain = DAG.getCopyFromReg(Chain, PPC::R3, MVT::i32, InFlag).getValue(1);
-      ResultVals[0] = Chain.getValue(0);
-      NumResults = 1;
-    }
-    NodeTys.push_back(MVT::i32);
-    break;
-  case MVT::i64:
-    if (Op.Val->getNumValues()>=4 && 
-        Op.Val->getValueType(3) == MVT::i64) {
-      Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
-      ResultVals[0] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::X4, MVT::i64,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[1] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::X5, MVT::i64,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[2] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::X6, MVT::i64,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[3] = Chain.getValue(0);
-      NumResults = 4;
-      NodeTys.push_back(MVT::i64);
-      NodeTys.push_back(MVT::i64);
-      NodeTys.push_back(MVT::i64);
-    } else if (Op.Val->getValueType(1) == MVT::i64) {
-      Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
-      ResultVals[0] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::X4, MVT::i64,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[1] = Chain.getValue(0);
-      NumResults = 2;
-      NodeTys.push_back(MVT::i64);
-    } else {
-      Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
-      ResultVals[0] = Chain.getValue(0);
-      NumResults = 1;
-    }
-    NodeTys.push_back(MVT::i64);
-    break;
-  case MVT::f64:
-    if (Op.Val->getValueType(1) == MVT::f64) {
-      Chain = DAG.getCopyFromReg(Chain, PPC::F1, MVT::f64, InFlag).getValue(1);
-      ResultVals[0] = Chain.getValue(0);
-      Chain = DAG.getCopyFromReg(Chain, PPC::F2, MVT::f64,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals[1] = Chain.getValue(0);
-      NumResults = 2;
-      NodeTys.push_back(MVT::f64);
-      NodeTys.push_back(MVT::f64);
-      break;
-    } 
-    // else fall through
-  case MVT::f32:
-    Chain = DAG.getCopyFromReg(Chain, PPC::F1, Op.Val->getValueType(0),
-                               InFlag).getValue(1);
-    ResultVals[0] = Chain.getValue(0);
-    NumResults = 1;
-    NodeTys.push_back(Op.Val->getValueType(0));
-    break;
-  case MVT::v4f32:
-  case MVT::v4i32:
-  case MVT::v8i16:
-  case MVT::v16i8:
-    Chain = DAG.getCopyFromReg(Chain, PPC::V2, Op.Val->getValueType(0),
-                                   InFlag).getValue(1);
-    ResultVals[0] = Chain.getValue(0);
-    NumResults = 1;
-    NodeTys.push_back(Op.Val->getValueType(0));
-    break;
+  // Copy all of the result registers out of their specified physreg.
+  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
+    CCValAssign &VA = RVLocs[i];
+    MVT::ValueType VT = VA.getValVT();
+    assert(VA.isRegLoc() && "Can only return in registers!");
+    Chain = DAG.getCopyFromReg(Chain, VA.getLocReg(), VT, InFlag).getValue(1);
+    ResultVals.push_back(Chain.getValue(0));
+    InFlag = Chain.getValue(2);
   }
-  
-  NodeTys.push_back(MVT::Other);
-  
+
   // If the function returns void, just return the chain.
-  if (NumResults == 0)
+  if (RVLocs.empty())
     return Chain;
   
   // Otherwise, merge everything together with a MERGE_VALUES node.
-  ResultVals[NumResults++] = Chain;
-  SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys,
-                              ResultVals, NumResults);
+  ResultVals.push_back(Chain);
+  SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(),
+                              &ResultVals[0], ResultVals.size());
   return Res.getValue(Op.ResNo);
 }
 
@@ -3537,7 +3413,8 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
                                  VarArgsStackOffset, VarArgsNumGPR,
                                  VarArgsNumFPR, PPCSubTarget);
 
-  case ISD::CALL:               return LowerCALL(Op, DAG, PPCSubTarget);
+  case ISD::CALL:               return LowerCALL(Op, DAG, PPCSubTarget,
+                                                 getTargetMachine());
   case ISD::RET:                return LowerRET(Op, DAG, getTargetMachine());
   case ISD::STACKRESTORE:       return LowerSTACKRESTORE(Op, DAG, PPCSubTarget);
   case ISD::DYNAMIC_STACKALLOC:
index 5229693e17b4cfefd37e35702e4daa2aad0c8ef3..61a2f255417d82f70c40259fb708db624e7f2bc1 100644 (file)
@@ -317,7 +317,7 @@ namespace llvm {
                                     unsigned &VarArgsNumFPR,
                                     const PPCSubtarget &Subtarget);
     SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG,
-                        const PPCSubtarget &Subtarget);
+                        const PPCSubtarget &Subtarget, TargetMachine &TM);
     SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG, TargetMachine &TM);
     SDOperand LowerSTACKRESTORE(SDOperand Op, SelectionDAG &DAG,
                                 const PPCSubtarget &Subtarget);
diff --git a/test/CodeGen/PowerPC/multiple-return-values.ll b/test/CodeGen/PowerPC/multiple-return-values.ll
new file mode 100644 (file)
index 0000000..b72b148
--- /dev/null
@@ -0,0 +1,17 @@
+; RUN: llvm-as < %s | llc -march=ppc32
+; RUN: llvm-as < %s | llc -march=ppc64
+
+define {i64, float} @bar(i64 %a, float %b) {
+        %y = add i64 %a, 7
+        %z = add float %b, 7.0
+       ret i64 %y, float %z
+}
+
+define i64 @foo() {
+       %M = call {i64, float} @bar(i64 21, float 21.0)
+        %N = getresult {i64, float} %M, 0
+        %O = getresult {i64, float} %M, 1
+        %P = fptosi float %O to i64
+        %Q = add i64 %P, %N
+       ret i64 %Q
+}