[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelLowering.cpp X86ISelLowering.h

Chris Lattner sabre at nondot.org
Sun Feb 25 00:59:39 PST 2007



Changes in directory llvm/lib/Target/X86:

X86ISelLowering.cpp updated: 1.329 -> 1.330
X86ISelLowering.h updated: 1.86 -> 1.87
---
Log message:

factor a bunch of code out of LowerCCCCallTo into a new LowerCallResult
function.  This function now uses GetRetValueLocs to determine *where*
the result values are located and concerns itself with *how* to pull the
values out.


---
Diffs of the changes:  (+97 -100)

 X86ISelLowering.cpp |  194 +++++++++++++++++++++++++---------------------------
 X86ISelLowering.h   |    3 
 2 files changed, 97 insertions(+), 100 deletions(-)


Index: llvm/lib/Target/X86/X86ISelLowering.cpp
diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.329 llvm/lib/Target/X86/X86ISelLowering.cpp:1.330
--- llvm/lib/Target/X86/X86ISelLowering.cpp:1.329	Sun Feb 25 02:29:00 2007
+++ llvm/lib/Target/X86/X86ISelLowering.cpp	Sun Feb 25 02:59:22 2007
@@ -446,24 +446,96 @@
   // Otherwise, NumVTs is 1.
   MVT::ValueType ArgVT = VTs[0];
   
-  if (MVT::isVector(ArgVT))        // Integer or FP vector result -> XMM0.
-    ResultRegs[0] = X86::XMM0;
-  else if (MVT::isFloatingPoint(ArgVT) && Subtarget->is64Bit())
-    // FP values in X86-64 go in XMM0.
-    ResultRegs[0] = X86::XMM0;
-  else if (MVT::isFloatingPoint(ArgVT))
-    // FP values in X86-32 go in ST0.
-    ResultRegs[0] = X86::ST0;
-  else {
-    assert(MVT::isInteger(ArgVT) && "Unknown return value type!");
+  unsigned Reg;
+  switch (ArgVT) {
+  case MVT::i8:  Reg = X86::AL; break;
+  case MVT::i16: Reg = X86::AX; break;
+  case MVT::i32: Reg = X86::EAX; break;
+  case MVT::i64: Reg = X86::RAX; break;
+  case MVT::f32:
+  case MVT::f64:
+    if (Subtarget->is64Bit())
+      Reg = X86::XMM0;         // FP values in X86-64 go in XMM0.
+    else
+      Reg = X86::ST0;          // FP values in X86-32 go in ST0.
+    break;
+  default:
+    assert(MVT::isVector(ArgVT) && "Unknown return value type!");
+    Reg = X86::XMM0; // Int/FP vector result -> XMM0.
+    break;
+  }
+  ResultRegs[0] = Reg;
+}
+
+/// LowerCallResult - Lower the result values of an ISD::CALL into the
+/// appropriate copies out of appropriate physical registers.  This assumes that
+/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
+/// being lowered.  The returns a SDNode with the same number of values as the
+/// ISD::CALL.
+SDNode *X86TargetLowering::
+LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall, 
+                unsigned CallingConv, SelectionDAG &DAG) {
+  SmallVector<SDOperand, 8> ResultVals;
+
+  // We support returning up to two registers.
+  MVT::ValueType VTs[2];
+  unsigned DestRegs[2];
+  unsigned NumRegs = TheCall->getNumValues() - 1;
+  assert(NumRegs <= 2 && "Can only return up to two regs!");
+  
+  for (unsigned i = 0; i != NumRegs; ++i)
+    VTs[i] = TheCall->getValueType(i);
+  
+  // Determine which register each value should be copied into.
+  GetRetValueLocs(VTs, NumRegs, DestRegs, Subtarget, CallingConv);
+  
+  // Copy all of the result registers out of their specified physreg.
+  if (NumRegs != 1 || DestRegs[0] != X86::ST0) {
+    for (unsigned i = 0; i != NumRegs; ++i) {
+      Chain = DAG.getCopyFromReg(Chain, DestRegs[i], VTs[i],
+                                 InFlag).getValue(1);
+      InFlag = Chain.getValue(2);
+      ResultVals.push_back(Chain.getValue(0));
+    }
+  } else {
+    // Copies from the FP stack are special, as ST0 isn't a valid register
+    // before the fp stackifier runs.
     
-    // Integer result -> EAX / RAX.
-    // The C calling convention guarantees the return value has been
-    // promoted to at least MVT::i32. The X86-64 ABI doesn't require the
-    // value to be promoted MVT::i64. So we don't have to extend it to
-    // 64-bit.
-    ResultRegs[0] = (ArgVT == MVT::i64) ? X86::RAX : X86::EAX;
+    // Copy ST0 into an RFP register with FP_GET_RESULT.
+    SDVTList Tys = DAG.getVTList(MVT::f64, MVT::Other, MVT::Flag);
+    SDOperand GROps[] = { Chain, InFlag };
+    SDOperand RetVal = DAG.getNode(X86ISD::FP_GET_RESULT, Tys, GROps, 2);
+    Chain  = RetVal.getValue(1);
+    InFlag = RetVal.getValue(2);
+    
+    // If we are using ScalarSSE, store ST(0) to the stack and reload it into
+    // an XMM register.
+    if (X86ScalarSSE) {
+      // FIXME: Currently the FST is flagged to the FP_GET_RESULT. This
+      // shouldn't be necessary except that RFP cannot be live across
+      // multiple blocks. When stackifier is fixed, they can be uncoupled.
+      MachineFunction &MF = DAG.getMachineFunction();
+      int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
+      SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
+      SDOperand Ops[] = {
+        Chain, RetVal, StackSlot, DAG.getValueType(VTs[0]), InFlag
+      };
+      Chain = DAG.getNode(X86ISD::FST, MVT::Other, Ops, 5);
+      RetVal = DAG.getLoad(VTs[0], Chain, StackSlot, NULL, 0);
+      Chain = RetVal.getValue(1);
+    }
+    
+    if (VTs[0] == MVT::f32 && !X86ScalarSSE)
+      // FIXME: we would really like to remember that this FP_ROUND
+      // operation is okay to eliminate if we allow excess FP precision.
+      RetVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, RetVal);
+    ResultVals.push_back(RetVal);
   }
+  
+  // Merge everything together with a MERGE_VALUES node.
+  ResultVals.push_back(Chain);
+  return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(),
+                     &ResultVals[0], ResultVals.size()).Val;
 }
 
 
@@ -696,7 +768,6 @@
   bool isVarArg       = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
   bool isTailCall     = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
   SDOperand Callee    = Op.getOperand(4);
-  MVT::ValueType RetVT= Op.Val->getValueType(0);
   unsigned NumOps     = (Op.getNumOperands() - 5) / 2;
 
   static const unsigned XMMArgRegs[] = {
@@ -905,88 +976,12 @@
   Ops.push_back(DAG.getConstant(NumBytesForCalleeToPush, getPointerTy()));
   Ops.push_back(InFlag);
   Chain = DAG.getNode(ISD::CALLSEQ_END, NodeTys, &Ops[0], Ops.size());
-  if (RetVT != MVT::Other)
-    InFlag = Chain.getValue(1);
-
-  SmallVector<SDOperand, 8> ResultVals;
-  switch (RetVT) {
-  default: assert(0 && "Unknown value type to return!");
-  case MVT::Other:
-    NodeTys = DAG.getVTList(MVT::Other);
-    break;
-  case MVT::i8:
-    Chain = DAG.getCopyFromReg(Chain, X86::AL, MVT::i8, InFlag).getValue(1);
-    ResultVals.push_back(Chain.getValue(0));
-    NodeTys = DAG.getVTList(MVT::i8, MVT::Other);
-    break;
-  case MVT::i16:
-    Chain = DAG.getCopyFromReg(Chain, X86::AX, MVT::i16, InFlag).getValue(1);
-    ResultVals.push_back(Chain.getValue(0));
-    NodeTys = DAG.getVTList(MVT::i16, MVT::Other);
-    break;
-  case MVT::i32:
-    if (Op.Val->getValueType(1) == MVT::i32) {
-      Chain = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag).getValue(1);
-      ResultVals.push_back(Chain.getValue(0));
-      Chain = DAG.getCopyFromReg(Chain, X86::EDX, MVT::i32,
-                                 Chain.getValue(2)).getValue(1);
-      ResultVals.push_back(Chain.getValue(0));
-      NodeTys = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other);
-    } else {
-      Chain = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag).getValue(1);
-      ResultVals.push_back(Chain.getValue(0));
-      NodeTys = DAG.getVTList(MVT::i32, MVT::Other);
-    }
-    break;
-  case MVT::v16i8:
-  case MVT::v8i16:
-  case MVT::v4i32:
-  case MVT::v2i64:
-  case MVT::v4f32:
-  case MVT::v2f64:
-    assert(!isStdCall && "Unknown value type to return!");
-    Chain = DAG.getCopyFromReg(Chain, X86::XMM0, RetVT, InFlag).getValue(1);
-    ResultVals.push_back(Chain.getValue(0));
-    NodeTys = DAG.getVTList(RetVT, MVT::Other);
-    break;
-  case MVT::f32:
-  case MVT::f64: {
-    SDVTList Tys = DAG.getVTList(MVT::f64, MVT::Other, MVT::Flag);
-    SDOperand GROps[] = { Chain, InFlag };
-    SDOperand RetVal = DAG.getNode(X86ISD::FP_GET_RESULT, Tys, GROps, 2);
-    Chain  = RetVal.getValue(1);
-    InFlag = RetVal.getValue(2);
-    if (X86ScalarSSE) {
-      // FIXME: Currently the FST is flagged to the FP_GET_RESULT. This
-      // shouldn't be necessary except that RFP cannot be live across
-      // multiple blocks. When stackifier is fixed, they can be uncoupled.
-      MachineFunction &MF = DAG.getMachineFunction();
-      int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
-      SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
-      Tys = DAG.getVTList(MVT::Other);
-      SDOperand Ops[] = {
-        Chain, RetVal, StackSlot, DAG.getValueType(RetVT), InFlag
-      };
-      Chain = DAG.getNode(X86ISD::FST, Tys, Ops, 5);
-      RetVal = DAG.getLoad(RetVT, Chain, StackSlot, NULL, 0);
-      Chain = RetVal.getValue(1);
-    }
-
-    if (RetVT == MVT::f32 && !X86ScalarSSE)
-      // FIXME: we would really like to remember that this FP_ROUND
-      // operation is okay to eliminate if we allow excess FP precision.
-      RetVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, RetVal);
-    ResultVals.push_back(RetVal);
-    NodeTys = DAG.getVTList(RetVT, MVT::Other);
-    break;
-  }
-  }
+  InFlag = Chain.getValue(1);
 
-  // Merge everything together with a MERGE_VALUES node.
-  ResultVals.push_back(Chain);
-  SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys,
-                              &ResultVals[0], ResultVals.size());
-  return Res.getValue(Op.ResNo);
+  // Handle result values, copying them out of physregs into vregs that we
+  // return.
+  return SDOperand(LowerCallResult(Chain, InFlag, Op.Val, CallingConv::C, DAG),
+                   Op.ResNo);
 }
 
 
@@ -3946,9 +3941,8 @@
     default:
       assert(0 && "Unsupported calling convention");
     case CallingConv::Fast:
-      if (EnableFastCC) {
+      if (EnableFastCC)
         return LowerFastCCCallTo(Op, DAG);
-      }
       // Falls through
     case CallingConv::C:
       return LowerCCCCallTo(Op, DAG);


Index: llvm/lib/Target/X86/X86ISelLowering.h
diff -u llvm/lib/Target/X86/X86ISelLowering.h:1.86 llvm/lib/Target/X86/X86ISelLowering.h:1.87
--- llvm/lib/Target/X86/X86ISelLowering.h:1.86	Sun Feb 25 02:15:11 2007
+++ llvm/lib/Target/X86/X86ISelLowering.h	Sun Feb 25 02:59:22 2007
@@ -360,6 +360,9 @@
     /// X86ScalarSSE - Select between SSE2 or x87 floating point ops.
     bool X86ScalarSSE;
 
+    SDNode *LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode*TheCall,
+                            unsigned CallingConv, SelectionDAG &DAG);
+        
     // C and StdCall Calling Convention implementation.
     SDOperand LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
                                 bool isStdCall = false);






More information about the llvm-commits mailing list