Significantly improve handling of vectors that are live across basic blocks,
[oota-llvm.git] / lib / CodeGen / SelectionDAG / SelectionDAGISel.cpp
index d404d15ff7b2e5da59f714e7f34003d0ad943905..0b32352c689ae3da9cee0445fa238cb47fd11da2 100644 (file)
@@ -264,8 +264,16 @@ FunctionLoweringInfo::FunctionLoweringInfo(TargetLowering &tli,
     for (BasicBlock::iterator I = BB->begin();
          (PN = dyn_cast<PHINode>(I)); ++I)
       if (!PN->use_empty()) {
-        unsigned NumElements =
-          TLI.getNumElements(TLI.getValueType(PN->getType()));
+        MVT::ValueType VT = TLI.getValueType(PN->getType());
+        unsigned NumElements;
+        if (VT != MVT::Vector)
+          NumElements = TLI.getNumElements(VT);
+        else {
+          MVT::ValueType VT1,VT2;
+          NumElements = 
+            TLI.getPackedTypeBreakdown(cast<PackedType>(PN->getType()),
+                                       VT1, VT2);
+        }
         unsigned PHIReg = ValueMap[PN];
         assert(PHIReg &&"PHI node does not have an assigned virtual register!");
         for (unsigned i = 0; i != NumElements; ++i)
@@ -507,8 +515,8 @@ public:
   void visitSetLT(User &I) { visitSetCC(I, ISD::SETLT, ISD::SETULT); }
   void visitSetGT(User &I) { visitSetCC(I, ISD::SETGT, ISD::SETUGT); }
 
-  void visitExtractElement(ExtractElementInst &I);
-  void visitInsertElement(InsertElementInst &I);
+  void visitExtractElement(User &I);
+  void visitInsertElement(User &I);
 
   void visitGetElementPtr(User &I);
   void visitCast(User &I);
@@ -586,18 +594,8 @@ SDOperand SelectionDAGLowering::getValue(const Value *V) {
       // the packed constant.
       std::vector<SDOperand> Ops;
       if (ConstantPacked *CP = dyn_cast<ConstantPacked>(C)) {
-        if (MVT::isFloatingPoint(PVT)) {
-          for (unsigned i = 0; i != NumElements; ++i) {
-            const ConstantFP *El = cast<ConstantFP>(CP->getOperand(i));
-            Ops.push_back(DAG.getConstantFP(El->getValue(), PVT));
-          }
-        } else {
-          for (unsigned i = 0; i != NumElements; ++i) {
-            const ConstantIntegral *El = 
-            cast<ConstantIntegral>(CP->getOperand(i));
-            Ops.push_back(DAG.getConstant(El->getRawValue(), PVT));
-          }
-        }
+        for (unsigned i = 0; i != NumElements; ++i)
+          Ops.push_back(getValue(CP->getOperand(i)));
       } else {
         assert(isa<ConstantAggregateZero>(C) && "Unknown packed constant!");
         SDOperand Op;
@@ -632,32 +630,61 @@ SDOperand SelectionDAGLowering::getValue(const Value *V) {
   unsigned InReg = VMI->second;
   
   // If this type is not legal, make it so now.
-  if (VT == MVT::Vector) {
-    // FIXME: We only handle legal vectors right now.  We need a VBUILD_VECTOR
-    const PackedType *PTy = cast<PackedType>(VTy);
-    unsigned NumElements = PTy->getNumElements();
-    MVT::ValueType PVT = TLI.getValueType(PTy->getElementType());
-    MVT::ValueType TVT = MVT::getVectorType(PVT, NumElements);
-    assert(TLI.isTypeLegal(TVT) &&
-           "FIXME: Cannot handle illegal vector types here yet!");
-    VT = TVT;
-  }
-  
-  MVT::ValueType DestVT = TLI.getTypeToTransformTo(VT);
-  
-  N = DAG.getCopyFromReg(DAG.getEntryNode(), InReg, DestVT);
-  if (DestVT < VT) {
-    // Source must be expanded.  This input value is actually coming from the
-    // register pair VMI->second and VMI->second+1.
-    N = DAG.getNode(ISD::BUILD_PAIR, VT, N,
-                    DAG.getCopyFromReg(DAG.getEntryNode(), InReg+1, DestVT));
-  } else {
-    if (DestVT > VT) { // Promotion case
+  if (VT != MVT::Vector) {
+    MVT::ValueType DestVT = TLI.getTypeToTransformTo(VT);
+  
+    N = DAG.getCopyFromReg(DAG.getEntryNode(), InReg, DestVT);
+    if (DestVT < VT) {
+      // Source must be expanded.  This input value is actually coming from the
+      // register pair VMI->second and VMI->second+1.
+      N = DAG.getNode(ISD::BUILD_PAIR, VT, N,
+                      DAG.getCopyFromReg(DAG.getEntryNode(), InReg+1, DestVT));
+    } else if (DestVT > VT) { // Promotion case
       if (MVT::isFloatingPoint(VT))
         N = DAG.getNode(ISD::FP_ROUND, VT, N);
       else
         N = DAG.getNode(ISD::TRUNCATE, VT, N);
     }
+  } else {
+    // Otherwise, if this is a vector, make it available as a generic vector
+    // here.
+    MVT::ValueType PTyElementVT, PTyLegalElementVT;
+    unsigned NE = TLI.getPackedTypeBreakdown(cast<PackedType>(VTy),PTyElementVT,
+                                             PTyLegalElementVT);
+
+    // Build a VBUILD_VECTOR with the input registers.
+    std::vector<SDOperand> Ops;
+    if (PTyElementVT == PTyLegalElementVT) {
+      // If the value types are legal, just VBUILD the CopyFromReg nodes.
+      for (unsigned i = 0; i != NE; ++i)
+        Ops.push_back(DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, 
+                                         PTyElementVT));
+    } else if (PTyElementVT < PTyLegalElementVT) {
+      // If the register was promoted, use TRUNCATE of FP_ROUND as appropriate.
+      for (unsigned i = 0; i != NE; ++i) {
+        SDOperand Op = DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, 
+                                          PTyElementVT);
+        if (MVT::isFloatingPoint(PTyElementVT))
+          Op = DAG.getNode(ISD::FP_ROUND, PTyElementVT, Op);
+        else
+          Op = DAG.getNode(ISD::TRUNCATE, PTyElementVT, Op);
+        Ops.push_back(Op);
+      }
+    } else {
+      // If the register was expanded, use BUILD_PAIR.
+      assert((NE & 1) == 0 && "Must expand into a multiple of 2 elements!");
+      for (unsigned i = 0; i != NE/2; ++i) {
+        SDOperand Op0 = DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, 
+                                           PTyElementVT);
+        SDOperand Op1 = DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, 
+                                           PTyElementVT);
+        Ops.push_back(DAG.getNode(ISD::BUILD_PAIR, VT, Op0, Op1));
+      }
+    }
+    
+    Ops.push_back(DAG.getConstant(NE, MVT::i32));
+    Ops.push_back(DAG.getValueType(PTyLegalElementVT));
+    N = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, Ops);
   }
   
   return N;
@@ -1020,7 +1047,7 @@ void SelectionDAGLowering::visitCast(User &I) {
   }
 }
 
-void SelectionDAGLowering::visitInsertElement(InsertElementInst &I) {
+void SelectionDAGLowering::visitInsertElement(User &I) {
   SDOperand InVec = getValue(I.getOperand(0));
   SDOperand InVal = getValue(I.getOperand(1));
   SDOperand InIdx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(),
@@ -1032,7 +1059,7 @@ void SelectionDAGLowering::visitInsertElement(InsertElementInst &I) {
                            InVec, InVal, InIdx, Num, Typ));
 }
 
-void SelectionDAGLowering::visitExtractElement(ExtractElementInst &I) {
+void SelectionDAGLowering::visitExtractElement(User &I) {
   SDOperand InVec = getValue(I.getOperand(0));
   SDOperand InIdx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(),
                                 getValue(I.getOperand(1)));
@@ -1390,7 +1417,7 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
   case Intrinsic::dbg_declare: {
     MachineDebugInfo *DebugInfo = DAG.getMachineDebugInfo();
     DbgDeclareInst &DI = cast<DbgDeclareInst>(I);
-    if (DebugInfo && DebugInfo->Verify(DI.getVariable())) {
+    if (DebugInfo && DI.getVariable() && DebugInfo->Verify(DI.getVariable())) {
       std::vector<SDOperand> Ops;
 
       SDOperand AddressOp  = getValue(DI.getAddress());
@@ -2599,31 +2626,47 @@ CopyValueToVirtualRegister(SelectionDAGLowering &SDL, Value *V, unsigned Reg) {
   if (SrcVT == DestVT) {
     return DAG.getCopyToReg(SDL.getRoot(), Reg, Op);
   } else if (SrcVT == MVT::Vector) {
-    // FIXME: THIS DOES NOT SUPPORT PROMOTED/EXPANDED ELEMENTS!
-
-    // Figure out the right, legal destination reg to copy into.
-    const PackedType *PTy = cast<PackedType>(V->getType());
-    unsigned NumElts = PTy->getNumElements();
-    MVT::ValueType EltTy = TLI.getValueType(PTy->getElementType());
+    // Handle copies from generic vectors to registers.
+    MVT::ValueType PTyElementVT, PTyLegalElementVT;
+    unsigned NE = TLI.getPackedTypeBreakdown(cast<PackedType>(V->getType()),
+                                             PTyElementVT, PTyLegalElementVT);
     
-    unsigned NumVectorRegs = 1;
-
-    // Divide the input until we get to a supported size.  This will always
-    // end with a scalar if the target doesn't support vectors.
-    while (NumElts > 1 && !TLI.isTypeLegal(getVectorType(EltTy, NumElts))) {
-      NumElts >>= 1;
-      NumVectorRegs <<= 1;
+    // Insert a VBIT_CONVERT of the input vector to a "N x PTyElementVT" 
+    // MVT::Vector type.
+    Op = DAG.getNode(ISD::VBIT_CONVERT, MVT::Vector, Op,
+                     DAG.getConstant(NE, MVT::i32), 
+                     DAG.getValueType(PTyElementVT));
+
+    // Loop over all of the elements of the resultant vector,
+    // VEXTRACT_VECTOR_ELT'ing them, converting them to PTyLegalElementVT, then
+    // copying them into output registers.
+    std::vector<SDOperand> OutChains;
+    SDOperand Root = SDL.getRoot();
+    for (unsigned i = 0; i != NE; ++i) {
+      SDOperand Elt = DAG.getNode(ISD::VEXTRACT_VECTOR_ELT, PTyElementVT,
+                                  Op, DAG.getConstant(i, MVT::i32));
+      if (PTyElementVT == PTyLegalElementVT) {
+        // Elements are legal.
+        OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Elt));
+      } else if (PTyLegalElementVT > PTyElementVT) {
+        // Elements are promoted.
+        if (MVT::isFloatingPoint(PTyLegalElementVT))
+          Elt = DAG.getNode(ISD::FP_EXTEND, PTyLegalElementVT, Elt);
+        else
+          Elt = DAG.getNode(ISD::ANY_EXTEND, PTyLegalElementVT, Elt);
+        OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Elt));
+      } else {
+        // Elements are expanded.
+        // The src value is expanded into multiple registers.
+        SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, PTyLegalElementVT,
+                                   Elt, DAG.getConstant(0, MVT::i32));
+        SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, PTyLegalElementVT,
+                                   Elt, DAG.getConstant(1, MVT::i32));
+        OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Lo));
+        OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Hi));
+      }
     }
-    
-    MVT::ValueType VT;
-    if (NumElts == 1)
-      VT = EltTy;
-    else
-      VT = getVectorType(EltTy, NumElts);
-    
-    // FIXME: THIS ASSUMES THAT THE INPUT VECTOR WILL BE LEGAL!
-    Op = DAG.getNode(ISD::BIT_CONVERT, VT, Op);
-    return DAG.getCopyToReg(SDL.getRoot(), Reg, Op);
+    return DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains);
   } else if (SrcVT < DestVT) {
     // The src value is promoted to the register.
     if (MVT::isFloatingPoint(SrcVT))