[llvm-commits] [llvm] r37843 - /llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Dan Gohman djg at cray.com
Thu Jul 5 07:49:23 PDT 2007


Hi Evan,

I'm currently testing the attached patch, which seems to fix the
problems for PPC. It extends getCopyToParts and getCopyFromParts
to have an extra parameter to indicate when endian-swapping is
needed. I don't have access to a PPC test environment; I've included
a few trivial regression tests in this patch; I'll do some more
soon.

Copying to virtual registers is always done in little-endian order,
while copying to physical registers, arguments, or return values,
is done in target-endian order. I wonder if it would make sense to
change to using target-endian order for virtual registers as well?

Dan

On Tue, Jul 03, 2007 at 06:35:58PM -0700, Evan Cheng wrote:
> Hi Dan,
> 
> This patch is breaking llvm-gcc bootstrapping on PPC.
> 
> I am not sure what exactly wrong is it. But the old code has a check  
> for endianness while your new code doesn't. Can you check again if  
> you are taking endianness into consideration?
> 
> Thanks,
> 
> Evan
> 
> On Jul 2, 2007, at 9:18 AM, Dan Gohman wrote:
> 
> >Author: djg
> >Date: Mon Jul  2 11:18:06 2007
> >New Revision: 37843
> >
> >URL: http://llvm.org/viewvc/llvm-project?rev=37843&view=rev
> >Log:
> >Replace ExpandScalarFormalArgs and ExpandScalarCallArgs with the newly
> >refactored getCopyFromParts and getCopyToParts, which are more  
> >general.
> >This effectively adds support for lowering illegal by-val vector call
> >arguments.
> >
> >Modified:
> >    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
> >
> >Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
> >URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ 
> >SelectionDAG/SelectionDAGISel.cpp? 
> >rev=37843&r1=37842&r2=37843&view=diff
> >====================================================================== 
> >========
> >--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp  
> >(original)
> >+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Mon  
> >Jul  2 11:18:06 2007
> >@@ -2861,7 +2861,7 @@
> >   if (!MVT::isVector(ValueVT) || NumParts == 1) {
> >     // If the value was expanded, copy from the parts.
> >     if (NumParts > 1) {
> >-      for (unsigned i = 0; i < NumParts; ++i)
> >+      for (unsigned i = 0; i != NumParts; ++i)
> >         Parts[i] = DAG.getNode(ISD::EXTRACT_ELEMENT, PartVT, Val,
> >                                DAG.getConstant(i, MVT::i32));
> >       return;
> >@@ -2950,7 +2950,7 @@
> >   // Copy the legal parts from the registers.
> >   unsigned NumParts = Regs.size();
> >   SmallVector<SDOperand, 8> Parts(NumParts);
> >-  for (unsigned i = 0; i < NumParts; ++i) {
> >+  for (unsigned i = 0; i != NumParts; ++i) {
> >     SDOperand Part = Flag ?
> >                      DAG.getCopyFromReg(Chain, Regs[i], RegVT,  
> >*Flag) :
> >                      DAG.getCopyFromReg(Chain, Regs[i], RegVT);
> >@@ -2981,7 +2981,7 @@
> >   getCopyToParts(DAG, Val, &Parts[0], NumParts, RegVT);
> >
> >   // Copy the parts into the registers.
> >-  for (unsigned i = 0; i < NumParts; ++i) {
> >+  for (unsigned i = 0; i != NumParts; ++i) {
> >     SDOperand Part = Flag ?
> >                      DAG.getCopyToReg(Chain, R[i], Parts[i], *Flag) :
> >                      DAG.getCopyToReg(Chain, R[i], Parts[i]);
> >@@ -3746,32 +3746,6 @@
> >                           DAG.getSrcValue(I.getOperand(2))));
> > }
> >
> >-/// ExpandScalarFormalArgs - Recursively expand the  
> >formal_argument node, either
> >-/// bit_convert it or join a pair of them with a BUILD_PAIR when  
> >appropriate.
> >-static SDOperand ExpandScalarFormalArgs(MVT::ValueType VT, SDNode  
> >*Arg,
> >-                                        unsigned &i, SelectionDAG  
> >&DAG,
> >-                                        TargetLowering &TLI) {
> >-  if (TLI.getTypeAction(VT) != TargetLowering::Expand)
> >-    return SDOperand(Arg, i++);
> >-
> >-  MVT::ValueType EVT = TLI.getTypeToTransformTo(VT);
> >-  unsigned NumVals = MVT::getSizeInBits(VT) / MVT::getSizeInBits 
> >(EVT);
> >-  if (NumVals == 1) {
> >-    return DAG.getNode(ISD::BIT_CONVERT, VT,
> >-                       ExpandScalarFormalArgs(EVT, Arg, i, DAG,  
> >TLI));
> >-  } else if (NumVals == 2) {
> >-    SDOperand Lo = ExpandScalarFormalArgs(EVT, Arg, i, DAG, TLI);
> >-    SDOperand Hi = ExpandScalarFormalArgs(EVT, Arg, i, DAG, TLI);
> >-    if (!TLI.isLittleEndian())
> >-      std::swap(Lo, Hi);
> >-    return DAG.getNode(ISD::BUILD_PAIR, VT, Lo, Hi);
> >-  } else {
> >-    // Value scalarized into many values.  Unimp for now.
> >-    assert(0 && "Cannot expand i64 -> i16 yet!");
> >-  }
> >-  return SDOperand();
> >-}
> >-
> > /// TargetLowering::LowerArguments - This is the default  
> >LowerArguments
> > /// implementation, which just inserts a FORMAL_ARGUMENTS node.   
> >FIXME: When all
> > /// targets are migrated to using FORMAL_ARGUMENTS, this hook  
> >should be
> >@@ -3842,8 +3816,8 @@
> >   SDNode *Result = DAG.getNode(ISD::FORMAL_ARGUMENTS,
> >                                DAG.getNodeValueTypes(RetVals),  
> >RetVals.size(),
> >                                &Ops[0], Ops.size()).Val;
> >-
> >-  DAG.setRoot(SDOperand(Result, Result->getNumValues()-1));
> >+  unsigned NumArgRegs = Result->getNumValues() - 1;
> >+  DAG.setRoot(SDOperand(Result, NumArgRegs));
> >
> >   // Set up the return result vector.
> >   Ops.clear();
> >@@ -3875,79 +3849,22 @@
> >       Ops.push_back(Op);
> >       break;
> >     }
> >-    case Expand:
> >-      if (!MVT::isVector(VT)) {
> >-        // If this is a large integer or a floating point node  
> >that needs to be
> >-        // expanded, it needs to be reassembled from small  
> >integers.  Figure out
> >-        // what the source elt type is and how many small integers  
> >it is.
> >-        Ops.push_back(ExpandScalarFormalArgs(VT, Result, i, DAG,  
> >*this));
> >-      } else {
> >-        // Otherwise, this is a vector type.  We only support  
> >legal vectors
> >-        // right now.
> >-        const VectorType *PTy = cast<VectorType>(I->getType());
> >-        unsigned NumElems = PTy->getNumElements();
> >-        const Type *EltTy = PTy->getElementType();
> >-
> >-        // Figure out if there is a Packed type corresponding to  
> >this Vector
> >-        // type.  If so, convert to the vector type.
> >-        MVT::ValueType TVT =
> >-          MVT::getVectorType(getValueType(EltTy), NumElems);
> >-        if (TVT != MVT::Other && isTypeLegal(TVT)) {
> >-          SDOperand N = SDOperand(Result, i++);
> >-          // Handle copies from vectors to registers.
> >-          N = DAG.getNode(ISD::BIT_CONVERT, TVT, N);
> >-          Ops.push_back(N);
> >-        } else {
> >-          assert(0 && "Don't support illegal by-val vector  
> >arguments yet!");
> >-          abort();
> >-        }
> >-      }
> >+    case Expand: {
> >+      MVT::ValueType PartVT = getRegisterType(VT);
> >+      unsigned NumParts = getNumRegisters(VT);
> >+      SmallVector<SDOperand, 4> Parts(NumParts);
> >+      for (unsigned j = 0; j != NumParts; ++j)
> >+        Parts[j] = SDOperand(Result, i++);
> >+      Ops.push_back(getCopyFromParts(DAG, &Parts[0], NumParts,  
> >PartVT, VT));
> >       break;
> >     }
> >+    }
> >   }
> >+  assert(i == NumArgRegs && "Argument register count mismatch!");
> >   return Ops;
> > }
> >
> >
> >-/// ExpandScalarCallArgs - Recursively expand call argument node by
> >-/// bit_converting it or extract a pair of elements from the  
> >larger  node.
> >-static void ExpandScalarCallArgs(MVT::ValueType VT, SDOperand Arg,
> >-                                 unsigned Flags,
> >-                                 SmallVector<SDOperand, 32> &Ops,
> >-                                 SelectionDAG &DAG,
> >-                                 TargetLowering &TLI,
> >-                                 bool isFirst = true) {
> >-
> >-  if (TLI.getTypeAction(VT) != TargetLowering::Expand) {
> >-    // if it isn't first piece, alignment must be 1
> >-    if (!isFirst)
> >-      Flags = (Flags & (~ISD::ParamFlags::OrigAlignment)) |
> >-        (1 << ISD::ParamFlags::OrigAlignmentOffs);
> >-    Ops.push_back(Arg);
> >-    Ops.push_back(DAG.getConstant(Flags, MVT::i32));
> >-    return;
> >-  }
> >-
> >-  MVT::ValueType EVT = TLI.getTypeToTransformTo(VT);
> >-  unsigned NumVals = MVT::getSizeInBits(VT) / MVT::getSizeInBits 
> >(EVT);
> >-  if (NumVals == 1) {
> >-    Arg = DAG.getNode(ISD::BIT_CONVERT, EVT, Arg);
> >-    ExpandScalarCallArgs(EVT, Arg, Flags, Ops, DAG, TLI, isFirst);
> >-  } else if (NumVals == 2) {
> >-    SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, EVT, Arg,
> >-                               DAG.getConstant(0, TLI.getPointerTy 
> >()));
> >-    SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, EVT, Arg,
> >-                               DAG.getConstant(1, TLI.getPointerTy 
> >()));
> >-    if (!TLI.isLittleEndian())
> >-      std::swap(Lo, Hi);
> >-    ExpandScalarCallArgs(EVT, Lo, Flags, Ops, DAG, TLI, isFirst);
> >-    ExpandScalarCallArgs(EVT, Hi, Flags, Ops, DAG, TLI, false);
> >-  } else {
> >-    // Value scalarized into many values.  Unimp for now.
> >-    assert(0 && "Cannot expand i64 -> i16 yet!");
> >-  }
> >-}
> >-
> > /// TargetLowering::LowerCallTo - This is the default LowerCallTo
> > /// implementation, which just inserts an ISD::CALL node, which is  
> >later custom
> > /// lowered by the target to something concrete.  FIXME: When all  
> >targets are
> >@@ -4014,35 +3931,24 @@
> >       Ops.push_back(Op);
> >       Ops.push_back(DAG.getConstant(Flags, MVT::i32));
> >       break;
> >-    case Expand:
> >-      if (!MVT::isVector(VT)) {
> >-        // If this is a large integer, it needs to be broken down  
> >into small
> >-        // integers.  Figure out what the source elt type is and  
> >how many small
> >-        // integers it is.
> >-        ExpandScalarCallArgs(VT, Op, Flags, Ops, DAG, *this);
> >-      } else {
> >-        // Otherwise, this is a vector type.  We only support  
> >legal vectors
> >-        // right now.
> >-        const VectorType *PTy = cast<VectorType>(Args[i].Ty);
> >-        unsigned NumElems = PTy->getNumElements();
> >-        const Type *EltTy = PTy->getElementType();
> >-
> >-        // Figure out if there is a Packed type corresponding to  
> >this Vector
> >-        // type.  If so, convert to the vector type.
> >-        MVT::ValueType TVT =
> >-          MVT::getVectorType(getValueType(EltTy), NumElems);
> >-        if (TVT != MVT::Other && isTypeLegal(TVT)) {
> >-          // Insert a BIT_CONVERT of the original type to the  
> >vector type.
> >-          Op = DAG.getNode(ISD::BIT_CONVERT, TVT, Op);
> >-          Ops.push_back(Op);
> >-          Ops.push_back(DAG.getConstant(Flags, MVT::i32));
> >-        } else {
> >-          assert(0 && "Don't support illegal by-val vector call  
> >args yet!");
> >-          abort();
> >-        }
> >+    case Expand: {
> >+      MVT::ValueType PartVT = getRegisterType(VT);
> >+      unsigned NumParts = getNumRegisters(VT);
> >+      SmallVector<SDOperand, 4> Parts(NumParts);
> >+      getCopyToParts(DAG, Op, &Parts[0], NumParts, PartVT);
> >+      for (unsigned i = 0; i != NumParts; ++i) {
> >+        // if it isn't first piece, alignment must be 1
> >+        unsigned MyFlags = Flags;
> >+        if (i != 0)
> >+          MyFlags = (MyFlags & (~ISD::ParamFlags::OrigAlignment)) |
> >+            (1 << ISD::ParamFlags::OrigAlignmentOffs);
> >+
> >+        Ops.push_back(Parts[i]);
> >+        Ops.push_back(DAG.getConstant(MyFlags, MVT::i32));
> >       }
> >       break;
> >     }
> >+    }
> >   }
> >
> >   // Figure out the result value types.
> >@@ -4360,7 +4266,7 @@
> >
> >   // Copy the value by legal parts into sequential virtual registers.
> >   getCopyToParts(DAG, Op, &Regs[0], NumRegs, RegisterVT);
> >-  for (unsigned i = 0; i < NumRegs; ++i)
> >+  for (unsigned i = 0; i != NumRegs; ++i)
> >     Chains[i] = DAG.getCopyToReg(getRoot(), Reg + i, Regs[i]);
> >   return DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0],  
> >NumRegs);
> > }
> >
> >
> >_______________________________________________
> >llvm-commits mailing list
> >llvm-commits at cs.uiuc.edu
> >http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 
-------------- next part --------------
Index: test/CodeGen/PowerPC/big-endian-actual-args.ll
===================================================================
--- test/CodeGen/PowerPC/big-endian-actual-args.ll	(revision 0)
+++ test/CodeGen/PowerPC/big-endian-actual-args.ll	(revision 0)
@@ -0,0 +1,7 @@
+; RUN: llvm-as < %s | llc -march=ppc32 | grep {addc 4, 4, 6}
+; RUN: llvm-as < %s | llc -march=ppc32 | grep {adde 3, 3, 5}
+
+define i64 @foo(i64 %x, i64 %y) {
+  %z = add i64 %x, %y
+  ret i64 %z
+}
Index: test/CodeGen/PowerPC/big-endian-formal-args.ll
===================================================================
--- test/CodeGen/PowerPC/big-endian-formal-args.ll	(revision 0)
+++ test/CodeGen/PowerPC/big-endian-formal-args.ll	(revision 0)
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | llc -march=ppc32 | grep {li 6, 3}
+; RUN: llvm-as < %s | llc -march=ppc32 | grep {li 4, 2}
+; RUN: llvm-as < %s | llc -march=ppc32 | grep {li 3, 0}
+; RUN: llvm-as < %s | llc -march=ppc32 | grep {mr 5, 3}
+
+declare void @bar(i64 %x, i64 %y)
+
+define void @foo() {
+  call void @bar(i64 2, i64 3)
+  ret void
+}
Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	(revision 37907)
+++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	(working copy)
@@ -613,6 +613,195 @@
 };
 } // end namespace llvm
 
+
+/// getCopyFromParts - Create a value that contains the
+/// specified legal parts combined into the value they represent.
+static SDOperand getCopyFromParts(SelectionDAG &DAG,
+                                  const SDOperand *Parts,
+                                  unsigned NumParts,
+                                  MVT::ValueType PartVT,
+                                  MVT::ValueType ValueVT,
+                                  bool EndianOrder,
+                                  ISD::NodeType AssertOp = ISD::DELETED_NODE) {
+  if (!MVT::isVector(ValueVT) || NumParts == 1) {
+    SDOperand Val = Parts[0];
+
+    // If the value was expanded, copy from the top part.
+    if (NumParts > 1) {
+      assert(NumParts == 2 &&
+             "Cannot expand to more than 2 elts yet!");
+      SDOperand Hi = Parts[1];
+      if (EndianOrder && !DAG.getTargetLoweringInfo().isLittleEndian())
+        std::swap(Val, Hi);
+      return DAG.getNode(ISD::BUILD_PAIR, ValueVT, Val, Hi);
+    }
+
+    // Otherwise, if the value was promoted or extended, truncate it to the
+    // appropriate type.
+    if (PartVT == ValueVT)
+      return Val;
+  
+    if (MVT::isVector(PartVT)) {
+      assert(MVT::isVector(ValueVT) && "Unknown vector conversion!");
+      return DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
+    }
+  
+    if (MVT::isInteger(PartVT) &&
+        MVT::isInteger(ValueVT)) {
+      if (ValueVT < PartVT) {
+        // For a truncate, see if we have any information to
+        // indicate whether the truncated bits will always be
+        // zero or sign-extension.
+        if (AssertOp != ISD::DELETED_NODE)
+          Val = DAG.getNode(AssertOp, PartVT, Val,
+                            DAG.getValueType(ValueVT));
+        return DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
+      } else {
+        return DAG.getNode(ISD::ANY_EXTEND, ValueVT, Val);
+      }
+    }
+  
+    if (MVT::isFloatingPoint(PartVT) &&
+        MVT::isFloatingPoint(ValueVT))
+      return DAG.getNode(ISD::FP_ROUND, ValueVT, Val);
+
+    if (MVT::getSizeInBits(PartVT) == 
+        MVT::getSizeInBits(ValueVT))
+      return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
+
+    assert(0 && "Unknown mismatch!");
+  }
+
+  // Handle a multi-element vector.
+  MVT::ValueType IntermediateVT, RegisterVT;
+  unsigned NumIntermediates;
+  unsigned NumRegs =
+    DAG.getTargetLoweringInfo()
+      .getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
+                              RegisterVT);
+
+  assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
+  assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
+  assert(RegisterVT == Parts[0].getValueType() &&
+         "Part type doesn't match part!");
+
+  // Assemble the parts into intermediate operands.
+  SmallVector<SDOperand, 8> Ops(NumIntermediates);
+  if (NumIntermediates == NumParts) {
+    // If the register was not expanded, truncate or copy the value,
+    // as appropriate.
+    for (unsigned i = 0; i != NumParts; ++i)
+      Ops[i] = getCopyFromParts(DAG, &Parts[i], 1,
+                                PartVT, IntermediateVT, EndianOrder);
+  } else if (NumParts > 0) {
+    // If the intermediate type was expanded, build the intermediate operands
+    // from the parts.
+    assert(NumIntermediates % NumParts == 0 &&
+           "Must expand into a divisible number of parts!");
+    unsigned Factor = NumIntermediates / NumParts;
+    for (unsigned i = 0; i != NumIntermediates; ++i)
+      Ops[i] = getCopyFromParts(DAG, &Parts[i * Factor], Factor,
+                                PartVT, IntermediateVT, EndianOrder);
+  }
+  
+  // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate
+  // operands.
+  return DAG.getNode(MVT::isVector(IntermediateVT) ?
+                       ISD::CONCAT_VECTORS :
+                       ISD::BUILD_VECTOR,
+                     ValueVT, &Ops[0], NumParts);
+}
+
+/// getCopyToParts - Create a series of nodes that contain the
+/// specified value split into legal parts.
+static void getCopyToParts(SelectionDAG &DAG,
+                           SDOperand Val,
+                           SDOperand *Parts,
+                           unsigned NumParts,
+                           MVT::ValueType PartVT,
+                           bool EndianOrder) {
+  MVT::ValueType ValueVT = Val.getValueType();
+
+  if (!MVT::isVector(ValueVT) || NumParts == 1) {
+    // If the value was expanded, copy from the parts.
+    if (NumParts > 1) {
+      for (unsigned i = 0; i != NumParts; ++i)
+        Parts[i] = DAG.getNode(ISD::EXTRACT_ELEMENT, PartVT, Val,
+                               DAG.getConstant(i, MVT::i32));
+      if (EndianOrder && !DAG.getTargetLoweringInfo().isLittleEndian())
+        std::reverse(Parts, Parts + NumParts);
+      return;
+    }
+
+    // If there is a single part and the types differ, this must be
+    // a promotion.
+    if (PartVT != ValueVT) {
+      if (MVT::isVector(PartVT)) {
+        assert(MVT::isVector(ValueVT) &&
+               "Not a vector-vector cast?");
+        Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
+      } else if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) {
+        if (PartVT < ValueVT)
+          Val = DAG.getNode(ISD::TRUNCATE, PartVT, Val);
+        else
+          Val = DAG.getNode(ISD::ANY_EXTEND, PartVT, Val);
+      } else if (MVT::isFloatingPoint(PartVT) &&
+                 MVT::isFloatingPoint(ValueVT)) {
+        Val = DAG.getNode(ISD::FP_EXTEND, PartVT, Val);
+      } else if (MVT::getSizeInBits(PartVT) == 
+                 MVT::getSizeInBits(ValueVT)) {
+        Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
+      } else {
+        assert(0 && "Unknown mismatch!");
+      }
+    }
+    Parts[0] = Val;
+    return;
+  }
+
+  // Handle a multi-element vector.
+  MVT::ValueType IntermediateVT, RegisterVT;
+  unsigned NumIntermediates;
+  unsigned NumRegs =
+    DAG.getTargetLoweringInfo()
+      .getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
+                              RegisterVT);
+  unsigned NumElements = MVT::getVectorNumElements(ValueVT);
+
+  assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
+  assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
+
+  // Split the vector into intermediate operands.
+  SmallVector<SDOperand, 8> Ops(NumIntermediates);
+  for (unsigned i = 0; i != NumIntermediates; ++i)
+    if (MVT::isVector(IntermediateVT))
+      Ops[i] = DAG.getNode(ISD::EXTRACT_SUBVECTOR,
+                           IntermediateVT, Val,
+                           DAG.getConstant(i * (NumElements / NumIntermediates),
+                                           MVT::i32));
+    else
+      Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT,
+                           IntermediateVT, Val, 
+                           DAG.getConstant(i, MVT::i32));
+
+  // Split the intermediate operands into legal parts.
+  if (NumParts == NumIntermediates) {
+    // If the register was not expanded, promote or copy the value,
+    // as appropriate.
+    for (unsigned i = 0; i != NumParts; ++i)
+      getCopyToParts(DAG, Ops[i], &Parts[i], 1, PartVT, EndianOrder);
+  } else if (NumParts > 0) {
+    // If the intermediate type was expanded, split each the value into
+    // legal parts.
+    assert(NumParts % NumIntermediates == 0 &&
+           "Must expand into a divisible number of parts!");
+    unsigned Factor = NumParts / NumIntermediates;
+    for (unsigned i = 0; i != NumIntermediates; ++i)
+      getCopyToParts(DAG, Ops[i], &Parts[i * Factor], Factor, PartVT, EndianOrder);
+  }
+}
+
+
 SDOperand SelectionDAGLowering::getValue(const Value *V) {
   SDOperand &N = NodeMap[V];
   if (N.Val) return N;
@@ -713,8 +902,8 @@
     SDOperand RetOp = getValue(I.getOperand(i));
     
     // If this is an integer return value, we need to promote it ourselves to
-    // the full width of a register, since LegalizeOp will use ANY_EXTEND rather
-    // than sign/zero.
+    // the full width of a register, since getCopyToParts and Legalize will use
+    // ANY_EXTEND rather than sign/zero.
     // FIXME: C calling convention requires the return type to be promoted to
     // at least 32-bit. But this is not necessary for non-C calling conventions.
     if (MVT::isInteger(RetOp.getValueType()) && 
@@ -732,9 +921,19 @@
       if (Attrs && Attrs->paramHasAttr(0, ParamAttr::ZExt))
         ExtendKind = ISD::ZERO_EXTEND;
       RetOp = DAG.getNode(ExtendKind, TmpVT, RetOp);
+      NewValues.push_back(RetOp);
+      NewValues.push_back(DAG.getConstant(false, MVT::i32));
+    } else {
+      MVT::ValueType VT = RetOp.getValueType();
+      unsigned NumParts = TLI.getNumRegisters(VT);
+      MVT::ValueType PartVT = TLI.getRegisterType(VT);
+      SmallVector<SDOperand, 4> Parts(NumParts);
+      getCopyToParts(DAG, RetOp, &Parts[0], NumParts, PartVT, true);
+      for (unsigned i = 0; i < NumParts; ++i) {
+        NewValues.push_back(Parts[i]);
+        NewValues.push_back(DAG.getConstant(false, MVT::i32));
+      }
     }
-    NewValues.push_back(RetOp);
-    NewValues.push_back(DAG.getConstant(false, MVT::i32));
   }
   DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other,
                           &NewValues[0], NewValues.size()));
@@ -2779,197 +2978,14 @@
 }
 
 
-/// getCopyFromParts - Create a value that contains the
-/// specified legal parts combined into the value they represent.
-static SDOperand getCopyFromParts(SelectionDAG &DAG,
-                                  const SDOperand *Parts,
-                                  unsigned NumParts,
-                                  MVT::ValueType PartVT,
-                                  MVT::ValueType ValueVT,
-                                  ISD::NodeType AssertOp = ISD::DELETED_NODE) {
-  if (!MVT::isVector(ValueVT) || NumParts == 1) {
-    SDOperand Val = Parts[0];
-
-    // If the value was expanded, copy from the top part.
-    if (NumParts > 1) {
-      assert(NumParts == 2 &&
-             "Cannot expand to more than 2 elts yet!");
-      SDOperand Hi = Parts[1];
-      return DAG.getNode(ISD::BUILD_PAIR, ValueVT, Val, Hi);
-    }
-
-    // Otherwise, if the value was promoted or extended, truncate it to the
-    // appropriate type.
-    if (PartVT == ValueVT)
-      return Val;
-  
-    if (MVT::isVector(PartVT)) {
-      assert(MVT::isVector(ValueVT) && "Unknown vector conversion!");
-      return DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
-    }
-  
-    if (MVT::isInteger(PartVT) &&
-        MVT::isInteger(ValueVT)) {
-      if (ValueVT < PartVT) {
-        // For a truncate, see if we have any information to
-        // indicate whether the truncated bits will always be
-        // zero or sign-extension.
-        if (AssertOp != ISD::DELETED_NODE)
-          Val = DAG.getNode(AssertOp, PartVT, Val,
-                            DAG.getValueType(ValueVT));
-        return DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
-      } else {
-        return DAG.getNode(ISD::ANY_EXTEND, ValueVT, Val);
-      }
-    }
-  
-    if (MVT::isFloatingPoint(PartVT) &&
-        MVT::isFloatingPoint(ValueVT))
-      return DAG.getNode(ISD::FP_ROUND, ValueVT, Val);
-
-    if (MVT::getSizeInBits(PartVT) == 
-        MVT::getSizeInBits(ValueVT))
-      return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
-
-    assert(0 && "Unknown mismatch!");
-  }
-
-  // Handle a multi-element vector.
-  MVT::ValueType IntermediateVT, RegisterVT;
-  unsigned NumIntermediates;
-  unsigned NumRegs =
-    DAG.getTargetLoweringInfo()
-      .getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
-                              RegisterVT);
-
-  assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
-  assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
-  assert(RegisterVT == Parts[0].getValueType() &&
-         "Part type doesn't match part!");
-
-  // Assemble the parts into intermediate operands.
-  SmallVector<SDOperand, 8> Ops(NumIntermediates);
-  if (NumIntermediates == NumParts) {
-    // If the register was not expanded, truncate or copy the value,
-    // as appropriate.
-    for (unsigned i = 0; i != NumParts; ++i)
-      Ops[i] = getCopyFromParts(DAG, &Parts[i], 1, PartVT, IntermediateVT);
-  } else if (NumParts > 0) {
-    // If the intermediate type was expanded, build the intermediate operands
-    // from the parts.
-    assert(NumIntermediates % NumParts == 0 &&
-           "Must expand into a divisible number of parts!");
-    unsigned Factor = NumIntermediates / NumParts;
-    for (unsigned i = 0; i != NumIntermediates; ++i)
-      Ops[i] = getCopyFromParts(DAG, &Parts[i * Factor], Factor,
-                                PartVT, IntermediateVT);
-  }
-  
-  // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate
-  // operands.
-  return DAG.getNode(MVT::isVector(IntermediateVT) ?
-                       ISD::CONCAT_VECTORS :
-                       ISD::BUILD_VECTOR,
-                     ValueVT, &Ops[0], NumParts);
-}
-
-/// getCopyToParts - Create a series of nodes that contain the
-/// specified value split into legal parts.
-static void getCopyToParts(SelectionDAG &DAG,
-                           SDOperand Val,
-                           SDOperand *Parts,
-                           unsigned NumParts,
-                           MVT::ValueType PartVT) {
-  MVT::ValueType ValueVT = Val.getValueType();
-
-  if (!MVT::isVector(ValueVT) || NumParts == 1) {
-    // If the value was expanded, copy from the parts.
-    if (NumParts > 1) {
-      for (unsigned i = 0; i != NumParts; ++i)
-        Parts[i] = DAG.getNode(ISD::EXTRACT_ELEMENT, PartVT, Val,
-                               DAG.getConstant(i, MVT::i32));
-      return;
-    }
-
-    // If there is a single part and the types differ, this must be
-    // a promotion.
-    if (PartVT != ValueVT) {
-      if (MVT::isVector(PartVT)) {
-        assert(MVT::isVector(ValueVT) &&
-               "Not a vector-vector cast?");
-        Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
-      } else if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) {
-        if (PartVT < ValueVT)
-          Val = DAG.getNode(ISD::TRUNCATE, PartVT, Val);
-        else
-          Val = DAG.getNode(ISD::ANY_EXTEND, PartVT, Val);
-      } else if (MVT::isFloatingPoint(PartVT) &&
-                 MVT::isFloatingPoint(ValueVT)) {
-        Val = DAG.getNode(ISD::FP_EXTEND, PartVT, Val);
-      } else if (MVT::getSizeInBits(PartVT) == 
-                 MVT::getSizeInBits(ValueVT)) {
-        Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
-      } else {
-        assert(0 && "Unknown mismatch!");
-      }
-    }
-    Parts[0] = Val;
-    return;
-  }
-
-  // Handle a multi-element vector.
-  MVT::ValueType IntermediateVT, RegisterVT;
-  unsigned NumIntermediates;
-  unsigned NumRegs =
-    DAG.getTargetLoweringInfo()
-      .getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
-                              RegisterVT);
-  unsigned NumElements = MVT::getVectorNumElements(ValueVT);
-
-  assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
-  assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
-
-  // Split the vector into intermediate operands.
-  SmallVector<SDOperand, 8> Ops(NumIntermediates);
-  for (unsigned i = 0; i != NumIntermediates; ++i)
-    if (MVT::isVector(IntermediateVT))
-      Ops[i] = DAG.getNode(ISD::EXTRACT_SUBVECTOR,
-                           IntermediateVT, Val,
-                           DAG.getConstant(i * (NumElements / NumIntermediates),
-                                           MVT::i32));
-    else
-      Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT,
-                           IntermediateVT, Val, 
-                           DAG.getConstant(i, MVT::i32));
-
-  // Split the intermediate operands into legal parts.
-  if (NumParts == NumIntermediates) {
-    // If the register was not expanded, promote or copy the value,
-    // as appropriate.
-    for (unsigned i = 0; i != NumParts; ++i)
-      getCopyToParts(DAG, Ops[i], &Parts[i], 1, PartVT);
-  } else if (NumParts > 0) {
-    // If the intermediate type was expanded, split each the value into
-    // legal parts.
-    assert(NumParts % NumIntermediates == 0 &&
-           "Must expand into a divisible number of parts!");
-    unsigned Factor = NumParts / NumIntermediates;
-    for (unsigned i = 0; i != NumIntermediates; ++i)
-      getCopyToParts(DAG, Ops[i], &Parts[i * Factor], Factor, PartVT);
-  }
-}
-
-
 /// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from
 /// this value and returns the result as a ValueVT value.  This uses 
 /// Chain/Flag as the input and updates them for the output Chain/Flag.
 /// If the Flag pointer is NULL, no flag is used.
 SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
                                         SDOperand &Chain, SDOperand *Flag)const{
-  // Get the list of registers, in the appropriate order.
+  // Get the list of registers.
   std::vector<unsigned> R(Regs);
-  if (!DAG.getTargetLoweringInfo().isLittleEndian())
-    std::reverse(R.begin(), R.end());
 
   // Copy the legal parts from the registers.
   unsigned NumParts = Regs.size();
@@ -2985,7 +3001,7 @@
   }
   
   // Assemble the legal parts into the final value.
-  return getCopyFromParts(DAG, &Parts[0], NumParts, RegVT, ValueVT);
+  return getCopyFromParts(DAG, &Parts[0], NumParts, RegVT, ValueVT, true);
 }
 
 /// getCopyToRegs - Emit a series of CopyToReg nodes that copies the
@@ -2994,15 +3010,13 @@
 /// If the Flag pointer is NULL, no flag is used.
 void RegsForValue::getCopyToRegs(SDOperand Val, SelectionDAG &DAG,
                                  SDOperand &Chain, SDOperand *Flag) const {
-  // Get the list of registers, in the appropriate order.
+  // Get the list of registers.
   std::vector<unsigned> R(Regs);
-  if (!DAG.getTargetLoweringInfo().isLittleEndian())
-    std::reverse(R.begin(), R.end());
 
   // Get the list of the values's legal parts.
   unsigned NumParts = Regs.size();
   SmallVector<SDOperand, 8> Parts(NumParts);
-  getCopyToParts(DAG, Val, &Parts[0], NumParts, RegVT);
+  getCopyToParts(DAG, Val, &Parts[0], NumParts, RegVT, true);
 
   // Copy the parts into the registers.
   for (unsigned i = 0; i != NumParts; ++i) {
@@ -3879,7 +3893,7 @@
       SmallVector<SDOperand, 4> Parts(NumParts);
       for (unsigned j = 0; j != NumParts; ++j)
         Parts[j] = SDOperand(Result, i++);
-      Ops.push_back(getCopyFromParts(DAG, &Parts[0], NumParts, PartVT, VT));
+      Ops.push_back(getCopyFromParts(DAG, &Parts[0], NumParts, PartVT, VT, true));
       break;
     }
     }
@@ -3951,7 +3965,7 @@
       MVT::ValueType PartVT = getRegisterType(VT);
       unsigned NumParts = getNumRegisters(VT);
       SmallVector<SDOperand, 4> Parts(NumParts);
-      getCopyToParts(DAG, Op, &Parts[0], NumParts, PartVT);
+      getCopyToParts(DAG, Op, &Parts[0], NumParts, PartVT, true);
       for (unsigned i = 0; i != NumParts; ++i) {
         // if it isn't first piece, alignment must be 1
         unsigned MyFlags = Flags;
@@ -3991,7 +4005,7 @@
     SmallVector<SDOperand, 4> Results(NumRegs);
     for (unsigned i = 0; i != NumRegs; ++i)
       Results[i] = Res.getValue(i);
-    Res = getCopyFromParts(DAG, &Results[0], NumRegs, RegisterVT, VT, AssertOp);
+    Res = getCopyFromParts(DAG, &Results[0], NumRegs, RegisterVT, VT, false, AssertOp);
   }
 
   return std::make_pair(Res, Chain);
@@ -4281,7 +4295,7 @@
   SmallVector<SDOperand, 8> Chains(NumRegs);
 
   // Copy the value by legal parts into sequential virtual registers.
-  getCopyToParts(DAG, Op, &Regs[0], NumRegs, RegisterVT);
+  getCopyToParts(DAG, Op, &Regs[0], NumRegs, RegisterVT, false);
   for (unsigned i = 0; i != NumRegs; ++i)
     Chains[i] = DAG.getCopyToReg(getRoot(), Reg + i, Regs[i]);
   return DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0], NumRegs);


More information about the llvm-commits mailing list