Check in code to scalarize arbitrarily wide packed types for some simple
authorNate Begeman <natebegeman@mac.com>
Tue, 22 Nov 2005 18:16:00 +0000 (18:16 +0000)
committerNate Begeman <natebegeman@mac.com>
Tue, 22 Nov 2005 18:16:00 +0000 (18:16 +0000)
vector operations (load, add, sub, mul).

This allows us to codegen:
void %foo(<4 x float> * %a) {
entry:
  %tmp1 = load <4 x float> * %a;
  %tmp2 = add <4 x float> %tmp1, %tmp1
  store <4 x float> %tmp2, <4 x float> *%a
  ret void
}

on ppc as:
_foo:
        lfs f0, 12(r3)
        lfs f1, 8(r3)
        lfs f2, 4(r3)
        lfs f3, 0(r3)
        fadds f0, f0, f0
        fadds f1, f1, f1
        fadds f2, f2, f2
        fadds f3, f3, f3
        stfs f0, 12(r3)
        stfs f1, 8(r3)
        stfs f2, 4(r3)
        stfs f3, 0(r3)
        blr

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

include/llvm/CodeGen/SelectionDAGNodes.h
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

index b98a3f022bfd52a877628b84ce0b7638cb9fdccd..6e6b88223d2b92fa32323d296c22aa5d6f1d5c42 100644 (file)
@@ -123,7 +123,9 @@ namespace ISD {
     // Simple abstract vector operators.  Unlike the integer and floating point
     // binary operators, these nodes also take two additional operands:
     // a constant element count, and a value type node indicating the type of
-    // the elements.  The order is count, type, op0, op1.
+    // the elements.  The order is op0, op1, count, type.  All vector opcodes,
+    // including VLOAD, must currently have count and type as their 3rd and 4th
+    // arguments.
     VADD, VSUB, VMUL,
 
     // MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing
index 35f401e202ada850aa29d5b943e165b80067d29f..19ccfbbf47f2363d91fb323776a4e23d408582d0 100644 (file)
@@ -1121,6 +1121,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
 
     case Expand:
       SDOperand Lo, Hi;
+      unsigned IncrementSize;
       ExpandOp(Node->getOperand(1), Lo, Hi);
 
       if (!TLI.isLittleEndian())
@@ -1128,7 +1129,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
 
       Lo = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, Lo, Tmp2,
                        Node->getOperand(3));
-      unsigned IncrementSize = MVT::getSizeInBits(Hi.getValueType())/8;
+      // If this is a vector type, then we have to calculate the increment as
+      // the product of the element size in bytes, and the number of elements
+      // in the high half of the vector.
+      if (MVT::Vector == Hi.getValueType()) {
+        unsigned NumElems = cast<ConstantSDNode>(Hi.getOperand(2))->getValue();
+        MVT::ValueType EVT = cast<VTSDNode>(Hi.getOperand(3))->getVT();
+        IncrementSize = NumElems * MVT::getSizeInBits(EVT)/8;
+      } else {
+        IncrementSize = MVT::getSizeInBits(Hi.getValueType())/8;
+      }
       Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
                          getIntPtrConstant(IncrementSize));
       assert(isTypeLegal(Tmp2.getValueType()) &&
@@ -3001,8 +3011,9 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
   MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
   SDNode *Node = Op.Val;
   assert(getTypeAction(VT) == Expand && "Not an expanded type!");
-  assert(MVT::isInteger(VT) && "Cannot expand FP values!");
-  assert(MVT::isInteger(NVT) && NVT < VT &&
+  assert((MVT::isInteger(VT) || VT == MVT::Vector) && 
+         "Cannot expand FP values!");
+  assert(((MVT::isInteger(NVT) && NVT < VT) || VT == MVT::Vector) &&
          "Cannot expand to FP value or to larger int value!");
 
   // See if we already expanded it.
@@ -3107,6 +3118,71 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
       std::swap(Lo, Hi);
     break;
   }
+  case ISD::VLOAD: {
+    SDOperand Ch = LegalizeOp(Node->getOperand(0));   // Legalize the chain.
+    SDOperand Ptr = LegalizeOp(Node->getOperand(1));  // Legalize the pointer.
+    unsigned NumElements =cast<ConstantSDNode>(Node->getOperand(2))->getValue();
+    MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
+    
+    // If we only have two elements, turn into a pair of scalar loads.
+    // FIXME: handle case where a vector of two elements is fine, such as
+    //   2 x double on SSE2.
+    if (NumElements == 2) {
+      Lo = DAG.getLoad(EVT, Ch, Ptr, Node->getOperand(4));
+      // Increment the pointer to the other half.
+      unsigned IncrementSize = MVT::getSizeInBits(EVT)/8;
+      Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                        getIntPtrConstant(IncrementSize));
+      //Is this safe?  declaring that the two parts of the split load
+      //are from the same instruction?
+      Hi = DAG.getLoad(EVT, Ch, Ptr, Node->getOperand(4));
+    } else {
+      NumElements /= 2; // Split the vector in half
+      Lo = DAG.getVecLoad(NumElements, EVT, Ch, Ptr, Node->getOperand(4));
+      unsigned IncrementSize = NumElements * MVT::getSizeInBits(EVT)/8;
+      Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                        getIntPtrConstant(IncrementSize));
+      //Is this safe?  declaring that the two parts of the split load
+      //are from the same instruction?
+      Hi = DAG.getVecLoad(NumElements, EVT, Ch, Ptr, Node->getOperand(4));
+    }
+    
+    // Build a factor node to remember that this load is independent of the
+    // other one.
+    SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+                               Hi.getValue(1));
+    
+    // Remember that we legalized the chain.
+    AddLegalizedOperand(Op.getValue(1), TF);
+    if (!TLI.isLittleEndian())
+      std::swap(Lo, Hi);
+    break;
+  }
+  case ISD::VADD:
+  case ISD::VSUB:
+  case ISD::VMUL: {
+    unsigned NumElements =cast<ConstantSDNode>(Node->getOperand(2))->getValue();
+    MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
+    SDOperand LL, LH, RL, RH;
+    
+    ExpandOp(Node->getOperand(0), LL, LH);
+    ExpandOp(Node->getOperand(1), RL, RH);
+
+    // If we only have two elements, turn into a pair of scalar loads.
+    // FIXME: handle case where a vector of two elements is fine, such as
+    //   2 x double on SSE2.
+    if (NumElements == 2) {
+      unsigned Opc = getScalarizedOpcode(Node->getOpcode(), EVT);
+      Lo = DAG.getNode(Opc, EVT, LL, RL);
+      Hi = DAG.getNode(Opc, EVT, LH, RH);
+    } else {
+      Lo = DAG.getNode(Node->getOpcode(), MVT::Vector, LL, RL, LL.getOperand(2),
+                       LL.getOperand(3));
+      Hi = DAG.getNode(Node->getOpcode(), MVT::Vector, LH, RH, LH.getOperand(2),
+                       LH.getOperand(3));
+    }
+    break;
+  }
   case ISD::TAILCALL:
   case ISD::CALL: {
     SDOperand Chain  = LegalizeOp(Node->getOperand(0));  // Legalize the chain.
index 685bdabd49fc4d45553a7f08b0112285cdaba822..7676ead3551f83a90a87615596317e48b910f929 100644 (file)
@@ -1106,7 +1106,7 @@ SDOperand SelectionDAG::getVecLoad(unsigned Count, MVT::ValueType EVT,
   Ops.push_back(SV);
   std::vector<MVT::ValueType> VTs;
   VTs.reserve(2);
-  VTs.push_back(EVT); VTs.push_back(MVT::Other);  // Add token chain.
+  VTs.push_back(MVT::Vector); VTs.push_back(MVT::Other);  // Add token chain.
   return getNode(ISD::VLOAD, VTs, Ops);
 }
 
index 079b16b1f82e12af43b513f6cfc6d7b76b8f396b..881168137420b8302d366865727bb9726c176bd0 100644 (file)
@@ -528,7 +528,7 @@ void SelectionDAGLowering::visitBinary(User &I, unsigned IntOp, unsigned FPOp,
     } else {
       SDOperand Num = DAG.getConstant(NumElements, MVT::i32);
       SDOperand Typ = DAG.getValueType(PVT);
-      setValue(&I, DAG.getNode(VecOp, Op1.getValueType(), Num, Typ, Op1, Op2));
+      setValue(&I, DAG.getNode(VecOp, MVT::Vector, Op1, Op2, Num, Typ));
     }
   }
 }