Basic non-power-of-2 vector support
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeDAG.cpp
index 6e58631f0c1416e324f6cff582427ae2233b20e3..9c0c845932f7ac8edc3d58274b2b3aad21443614 100644 (file)
@@ -23,7 +23,6 @@
 #include "llvm/CallingConv.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
-#include "llvm/Support/Alignment.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/MathExtras.h"
@@ -1143,12 +1142,20 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     // The only option for this is to custom lower it.
     Tmp3 = TLI.LowerOperation(Result.getValue(0), DAG);
     assert(Tmp3.Val && "Target didn't custom lower this node!");
-    assert(Tmp3.Val->getNumValues() == Result.Val->getNumValues() &&
+
+    // The number of incoming and outgoing values should match; unless the final
+    // outgoing value is a flag.
+    assert((Tmp3.Val->getNumValues() == Result.Val->getNumValues() ||
+            (Tmp3.Val->getNumValues() == Result.Val->getNumValues() + 1 &&
+             Tmp3.Val->getValueType(Tmp3.Val->getNumValues() - 1) ==
+               MVT::Flag)) &&
            "Lowering call/formal_arguments produced unexpected # results!");
     
     // Since CALL/FORMAL_ARGUMENTS nodes produce multiple values, make sure to
     // remember that we legalized all of them, so it doesn't get relegalized.
     for (unsigned i = 0, e = Tmp3.Val->getNumValues(); i != e; ++i) {
+      if (Tmp3.Val->getValueType(i) == MVT::Flag)
+        continue;
       Tmp1 = LegalizeOp(Tmp3.getValue(i));
       if (Op.ResNo == i)
         Tmp2 = Tmp1;
@@ -1473,6 +1480,12 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and"
              " not tell us which reg is the stack pointer!");
       SDOperand Chain = Tmp1.getOperand(0);
+
+      // Chain the dynamic stack allocation so that it doesn't modify the stack
+      // pointer when other instructions are using the stack.
+      Chain = DAG.getCALLSEQ_START(Chain,
+                                   DAG.getConstant(0, TLI.getPointerTy()));
+
       SDOperand Size  = Tmp2.getOperand(1);
       SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, VT);
       Chain = SP.getValue(1);
@@ -1483,7 +1496,14 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
         SP = DAG.getNode(ISD::AND, VT, SP,
                          DAG.getConstant(-(uint64_t)Align, VT));
       Tmp1 = DAG.getNode(ISD::SUB, VT, SP, Size);       // Value
-      Tmp2 = DAG.getCopyToReg(Chain, SPReg, Tmp1);      // Output chain
+      Chain = DAG.getCopyToReg(Chain, SPReg, Tmp1);     // Output chain
+
+      Tmp2 =
+        DAG.getCALLSEQ_END(Chain,
+                           DAG.getConstant(0, TLI.getPointerTy()),
+                           DAG.getConstant(0, TLI.getPointerTy()),
+                           SDOperand());
+
       Tmp1 = LegalizeOp(Tmp1);
       Tmp2 = LegalizeOp(Tmp2);
       break;
@@ -1599,21 +1619,17 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       case 8: LD = DAG.getLoad(MVT::i64, Chain, Addr, NULL, 0); break;
       }
 
+      Addr = LD;
       if (TLI.getTargetMachine().getRelocationModel() == Reloc::PIC_) {
         // For PIC, the sequence is:
         // BRIND(load(Jumptable + index) + RelocBase)
-        // RelocBase is the JumpTable on PPC and X86, GOT on Alpha
-        SDOperand Reloc;
-        if (TLI.usesGlobalOffsetTable())
-          Reloc = DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, PTy);
-        else
-          Reloc = Table;
-        Addr = (PTy != MVT::i32) ? DAG.getNode(ISD::SIGN_EXTEND, PTy, LD) : LD;
-        Addr = DAG.getNode(ISD::ADD, PTy, Addr, Reloc);
-        Result = DAG.getNode(ISD::BRIND, MVT::Other, LD.getValue(1), Addr);
-      } else {
-        Result = DAG.getNode(ISD::BRIND, MVT::Other, LD.getValue(1), LD);
+        // RelocBase can be JumpTable, GOT or some sort of global base.
+        if (PTy != MVT::i32)
+          Addr = DAG.getNode(ISD::SIGN_EXTEND, PTy, Addr);
+        Addr = DAG.getNode(ISD::ADD, PTy, Addr,
+                           TLI.getPICJumpTableRelocBase(Table, DAG));
       }
+      Result = DAG.getNode(ISD::BRIND, MVT::Other, LD.getValue(1), Addr);
     }
     }
     break;
@@ -2142,7 +2158,8 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
             break;
           } else {
             SplitVectorOp(Node->getOperand(1), Lo, Hi);
-            IncrementSize = NumElems/2 * MVT::getSizeInBits(EVT)/8;
+            IncrementSize = MVT::getVectorNumElements(Lo.Val->getValueType(0)) * 
+                            MVT::getSizeInBits(EVT)/8;
           }
         } else {
           ExpandOp(Node->getOperand(1), Lo, Hi);
@@ -6210,10 +6227,15 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
   SDNode *Node = Op.Val;
   unsigned NumElements = MVT::getVectorNumElements(Op.getValueType());
   assert(NumElements > 1 && "Cannot split a single element vector!");
-  unsigned NewNumElts = NumElements/2;
+
   MVT::ValueType NewEltVT = MVT::getVectorElementType(Op.getValueType());
-  MVT::ValueType NewVT = MVT::getVectorType(NewEltVT, NewNumElts);
-  
+
+  unsigned NewNumElts_Lo = 1 << Log2_32(NumElements-1);
+  unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo;
+
+  MVT::ValueType NewVT_Lo = MVT::getVectorType(NewEltVT, NewNumElts_Lo);
+  MVT::ValueType NewVT_Hi = MVT::getVectorType(NewEltVT, NewNumElts_Hi);
+
   // See if we already split it.
   std::map<SDOperand, std::pair<SDOperand, SDOperand> >::iterator I
     = SplitNodes.find(Op);
@@ -6237,25 +6259,27 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
     SplitVectorOp(Node->getOperand(0), Lo, Hi);
     unsigned Index = cast<ConstantSDNode>(Node->getOperand(2))->getValue();
     SDOperand ScalarOp = Node->getOperand(1);
-    if (Index < NewNumElts)
-      Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT, Lo, ScalarOp,
+    if (Index < NewNumElts_Lo)
+      Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT_Lo, Lo, ScalarOp,
                        DAG.getConstant(Index, TLI.getPointerTy()));
     else
-      Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT, Hi, ScalarOp,
-                       DAG.getConstant(Index - NewNumElts, TLI.getPointerTy()));
+      Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT_Hi, Hi, ScalarOp,
+                       DAG.getConstant(Index - NewNumElts_Lo,
+                                       TLI.getPointerTy()));
     break;
   }
   case ISD::BUILD_VECTOR: {
     SmallVector<SDOperand, 8> LoOps(Node->op_begin(), 
-                                    Node->op_begin()+NewNumElts);
-    Lo = DAG.getNode(ISD::BUILD_VECTOR, NewVT, &LoOps[0], LoOps.size());
+                                    Node->op_begin()+NewNumElts_Lo);
+    Lo = DAG.getNode(ISD::BUILD_VECTOR, NewVT_Lo, &LoOps[0], LoOps.size());
 
-    SmallVector<SDOperand, 8> HiOps(Node->op_begin()+NewNumElts, 
+    SmallVector<SDOperand, 8> HiOps(Node->op_begin()+NewNumElts_Lo
                                     Node->op_end());
-    Hi = DAG.getNode(ISD::BUILD_VECTOR, NewVT, &HiOps[0], HiOps.size());
+    Hi = DAG.getNode(ISD::BUILD_VECTOR, NewVT_Hi, &HiOps[0], HiOps.size());
     break;
   }
   case ISD::CONCAT_VECTORS: {
+    // FIXME: Handle non-power-of-two vectors?
     unsigned NewNumSubvectors = Node->getNumOperands() / 2;
     if (NewNumSubvectors == 1) {
       Lo = Node->getOperand(0);
@@ -6263,11 +6287,11 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
     } else {
       SmallVector<SDOperand, 8> LoOps(Node->op_begin(), 
                                       Node->op_begin()+NewNumSubvectors);
-      Lo = DAG.getNode(ISD::CONCAT_VECTORS, NewVT, &LoOps[0], LoOps.size());
+      Lo = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Lo, &LoOps[0], LoOps.size());
 
       SmallVector<SDOperand, 8> HiOps(Node->op_begin()+NewNumSubvectors, 
                                       Node->op_end());
-      Hi = DAG.getNode(ISD::CONCAT_VECTORS, NewVT, &HiOps[0], HiOps.size());
+      Hi = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Hi, &HiOps[0], HiOps.size());
     }
     break;
   }
@@ -6282,12 +6306,12 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
       // Handle a vector merge.
       SDOperand CL, CH;
       SplitVectorOp(Cond, CL, CH);
-      Lo = DAG.getNode(Node->getOpcode(), NewVT, CL, LL, RL);
-      Hi = DAG.getNode(Node->getOpcode(), NewVT, CH, LH, RH);
+      Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, CL, LL, RL);
+      Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, CH, LH, RH);
     } else {
       // Handle a simple select with vector operands.
-      Lo = DAG.getNode(Node->getOpcode(), NewVT, Cond, LL, RL);
-      Hi = DAG.getNode(Node->getOpcode(), NewVT, Cond, LH, RH);
+      Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, Cond, LL, RL);
+      Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, Cond, LH, RH);
     }
     break;
   }
@@ -6308,16 +6332,16 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
     SplitVectorOp(Node->getOperand(0), LL, LH);
     SplitVectorOp(Node->getOperand(1), RL, RH);
     
-    Lo = DAG.getNode(Node->getOpcode(), NewVT, LL, RL);
-    Hi = DAG.getNode(Node->getOpcode(), NewVT, LH, RH);
+    Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, LL, RL);
+    Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, LH, RH);
     break;
   }
   case ISD::FPOWI: {
     SDOperand L, H;
     SplitVectorOp(Node->getOperand(0), L, H);
 
-    Lo = DAG.getNode(Node->getOpcode(), NewVT, L, Node->getOperand(1));
-    Hi = DAG.getNode(Node->getOpcode(), NewVT, H, Node->getOperand(1));
+    Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, L, Node->getOperand(1));
+    Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, H, Node->getOperand(1));
     break;
   }
   case ISD::CTTZ:
@@ -6331,8 +6355,8 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
     SDOperand L, H;
     SplitVectorOp(Node->getOperand(0), L, H);
 
-    Lo = DAG.getNode(Node->getOpcode(), NewVT, L);
-    Hi = DAG.getNode(Node->getOpcode(), NewVT, H);
+    Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, L);
+    Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, H);
     break;
   }
   case ISD::LOAD: {
@@ -6344,13 +6368,13 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
     unsigned Alignment = LD->getAlignment();
     bool isVolatile = LD->isVolatile();
 
-    Lo = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
-    unsigned IncrementSize = NewNumElts * MVT::getSizeInBits(NewEltVT)/8;
+    Lo = DAG.getLoad(NewVT_Lo, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
+    unsigned IncrementSize = NewNumElts_Lo * MVT::getSizeInBits(NewEltVT)/8;
     Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
                       getIntPtrConstant(IncrementSize));
     SVOffset += IncrementSize;
     Alignment = MinAlign(Alignment, IncrementSize);
-    Hi = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
+    Hi = DAG.getLoad(NewVT_Hi, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
     
     // Build a factor node to remember that this load is independent of the
     // other one.
@@ -6378,8 +6402,8 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
     }
     // Split the vector and convert each of the pieces now.
     SplitVectorOp(InOp, Lo, Hi);
-    Lo = DAG.getNode(ISD::BIT_CONVERT, NewVT, Lo);
-    Hi = DAG.getNode(ISD::BIT_CONVERT, NewVT, Hi);
+    Lo = DAG.getNode(ISD::BIT_CONVERT, NewVT_Lo, Lo);
+    Hi = DAG.getNode(ISD::BIT_CONVERT, NewVT_Hi, Hi);
     break;
   }
   }