Remove integer promotion support for FP_EXTEND
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeDAG.cpp
index f9d1ddc615779a44c627e7cbf0a821b47adabee0..5866e1a9f97f233f0cb80b22991aef1eb6c4a7f5 100644 (file)
@@ -2008,7 +2008,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
     Tmp3 = Node->getOperand(3);              // RHS
     Tmp4 = Node->getOperand(1);              // CC
 
-    LegalizeSetCC(Node->getValueType(0), Tmp2, Tmp3, Tmp4);
+    LegalizeSetCC(TLI.getSetCCResultType(Tmp2), Tmp2, Tmp3, Tmp4);
     LastCALLSEQ_END = DAG.getEntryNode();
 
     // If we didn't get both a LHS and RHS back from LegalizeSetCC,
@@ -2910,7 +2910,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
     Tmp4 = LegalizeOp(Node->getOperand(3));   // False
     SDValue CC = Node->getOperand(4);
     
-    LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, CC);
+    LegalizeSetCC(TLI.getSetCCResultType(Tmp1), Tmp1, Tmp2, CC);
     
     // If we didn't get both a LHS and RHS back from LegalizeSetCC,
     // the LHS is a legal SETCC itself.  In this case, we need to compare
@@ -3099,7 +3099,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
     }
 
     Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
-    
+
     switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
     default: assert(0 && "BinOp legalize operation not supported");
     case TargetLowering::Legal: break;
@@ -3816,7 +3816,49 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
       }
     }
     break;
-      
+  case ISD::CONVERT_RNDSAT: {
+    ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(Node)->getCvtCode();
+    switch (CvtCode) {
+    default: assert(0 && "Unknown cvt code!");
+    case ISD::CVT_SF:
+    case ISD::CVT_UF:
+      break;
+    case ISD::CVT_FF:
+    case ISD::CVT_FS:
+    case ISD::CVT_FU:
+    case ISD::CVT_SS:
+    case ISD::CVT_SU:
+    case ISD::CVT_US:
+    case ISD::CVT_UU: {
+      SDValue DTyOp = Node->getOperand(1);
+      SDValue STyOp = Node->getOperand(2);
+      SDValue RndOp = Node->getOperand(3);
+      SDValue SatOp = Node->getOperand(4);
+      switch (getTypeAction(Node->getOperand(0).getValueType())) {
+      case Expand: assert(0 && "Shouldn't need to expand other operators here!");
+      case Legal:
+        Tmp1 = LegalizeOp(Node->getOperand(0));
+        Result = DAG.UpdateNodeOperands(Result, Tmp1, DTyOp, STyOp,
+                                        RndOp, SatOp);
+        if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) ==
+            TargetLowering::Custom) {
+          Tmp1 = TLI.LowerOperation(Result, DAG);
+          if (Tmp1.getNode()) Result = Tmp1;
+        }
+        break;
+      case Promote:
+        Result = PromoteOp(Node->getOperand(0));
+        // For FP, make Op1 a i32
+        
+        Result = DAG.getConvertRndSat(Result.getValueType(), Result,
+                                      DTyOp, STyOp, RndOp, SatOp, CvtCode);
+        break;
+      }
+      break;
+    }
+    } // end switch CvtCode
+    break;
+  }
     // Conversion operators.  The source and destination have different types.
   case ISD::SINT_TO_FP:
   case ISD::UINT_TO_FP: {
@@ -4234,6 +4276,19 @@ SDValue SelectionDAGLegalize::PromoteOp(SDValue Op) {
       break;
     }
     break;
+  case ISD::CONVERT_RNDSAT: {
+    ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(Node)->getCvtCode();
+    assert ((CvtCode == ISD::CVT_SS || CvtCode == ISD::CVT_SU ||
+             CvtCode == ISD::CVT_US || CvtCode == ISD::CVT_UU ||
+             CvtCode == ISD::CVT_SF || CvtCode == ISD::CVT_UF) &&
+            "can only promote integers");
+    Result = DAG.getConvertRndSat(NVT, Node->getOperand(0),
+                                  Node->getOperand(1), Node->getOperand(2),
+                                  Node->getOperand(3), Node->getOperand(4),
+                                  CvtCode);
+    break;
+
+  }
   case ISD::BIT_CONVERT:
     Result = EmitStackConvert(Node->getOperand(0), Node->getValueType(0),
                               Node->getValueType(0));
@@ -7210,16 +7265,34 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo,
       Lo = Node->getOperand(0);
       Hi = Node->getOperand(1);
     } else {
-      SmallVector<SDValue, 8> LoOps(Node->op_begin(), 
-                                      Node->op_begin()+NewNumSubvectors);
+      SmallVector<SDValue, 8> LoOps(Node->op_begin(),
+                                    Node->op_begin()+NewNumSubvectors);
       Lo = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Lo, &LoOps[0], LoOps.size());
 
-      SmallVector<SDValue, 8> HiOps(Node->op_begin()+NewNumSubvectors, 
+      SmallVector<SDValue, 8> HiOps(Node->op_begin()+NewNumSubvectors,
                                       Node->op_end());
       Hi = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Hi, &HiOps[0], HiOps.size());
     }
     break;
   }
+  case ISD::EXTRACT_SUBVECTOR: {
+    SDValue Vec = Op.getOperand(0);
+    SDValue Idx = Op.getOperand(1);
+    MVT     IdxVT = Idx.getValueType();
+
+    Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Lo, Vec, Idx);
+    ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx);
+    if (CIdx) {
+      Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Hi, Vec, 
+                       DAG.getConstant(CIdx->getZExtValue() + NewNumElts_Lo,
+                                       IdxVT));
+    } else {
+      Idx = DAG.getNode(ISD::ADD, IdxVT, Idx,
+                        DAG.getConstant(NewNumElts_Lo, IdxVT));
+      Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, NewVT_Hi, Vec, Idx);
+    }
+    break;
+  }
   case ISD::SELECT: {
     SDValue Cond = Node->getOperand(0);
 
@@ -7326,6 +7399,24 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo,
     Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, H);
     break;
   }
+  case ISD::CONVERT_RNDSAT: {
+    ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(Node)->getCvtCode();
+    SDValue L, H;
+    SplitVectorOp(Node->getOperand(0), L, H);
+    SDValue DTyOpL =  DAG.getValueType(NewVT_Lo);
+    SDValue DTyOpH =  DAG.getValueType(NewVT_Hi);
+    SDValue STyOpL =  DAG.getValueType(L.getValueType());
+    SDValue STyOpH =  DAG.getValueType(H.getValueType());
+
+    SDValue RndOp = Node->getOperand(3);
+    SDValue SatOp = Node->getOperand(4);
+
+    Lo = DAG.getConvertRndSat(NewVT_Lo, L, DTyOpL, STyOpL,
+                              RndOp, SatOp, CvtCode);
+    Hi = DAG.getConvertRndSat(NewVT_Hi, H, DTyOpH, STyOpH,
+                              RndOp, SatOp, CvtCode);
+    break;
+  }
   case ISD::LOAD: {
     LoadSDNode *LD = cast<LoadSDNode>(Node);
     SDValue Ch = LD->getChain();
@@ -7464,6 +7555,16 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) {
                          NewVT, 
                          ScalarizeVectorOp(Node->getOperand(0)));
     break;
+  case ISD::CONVERT_RNDSAT: {
+    SDValue Op0 = ScalarizeVectorOp(Node->getOperand(0));
+    Result = DAG.getConvertRndSat(NewVT, Op0,
+                                  DAG.getValueType(NewVT),
+                                  DAG.getValueType(Op0.getValueType()),
+                                  Node->getOperand(3),
+                                  Node->getOperand(4),
+                                  cast<CvtRndSatSDNode>(Node)->getCvtCode());
+    break;
+  }
   case ISD::FPOWI:
   case ISD::FP_ROUND:
     Result = DAG.getNode(Node->getOpcode(),
@@ -7516,8 +7617,8 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) {
     break;
   }
   case ISD::EXTRACT_SUBVECTOR:
-    Result = Node->getOperand(0);
-    assert(Result.getValueType() == NewVT);
+    Result = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, Node->getOperand(0),
+                         Node->getOperand(1));
     break;
   case ISD::BIT_CONVERT: {
     SDValue Op0 = Op.getOperand(0);
@@ -7591,8 +7692,7 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) {
       assert(0 && "Unexpected operation in WidenVectorOp!");
       break;
   case ISD::CopyFromReg:
-    assert(0 && "CopyFromReg must be legal!");
-  case ISD::UNDEF:
+    assert(0 && "CopyFromReg doesn't need widening!");
   case ISD::Constant:
   case ISD::ConstantFP:
     // To build a vector of these elements, clients should call BuildVector
@@ -7602,6 +7702,9 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) {
     // Variable Arguments with vector types doesn't make any sense to me
     assert(0 && "Unexpected operation in WidenVectorOp!");
     break;
+  case ISD::UNDEF:
+    Result = DAG.getNode(ISD::UNDEF, WidenVT);
+    break;
   case ISD::BUILD_VECTOR: {
     // Build a vector with undefined for the new nodes
     SDValueVector NewOps(Node->op_begin(), Node->op_end());
@@ -7740,7 +7843,10 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) {
   case ISD::FNEG:
   case ISD::FSQRT:
   case ISD::FSIN:
-  case ISD::FCOS: {
+  case ISD::FCOS:
+  case ISD::CTPOP:
+  case ISD::CTTZ:
+  case ISD::CTLZ: {
     // Unary op widening
     SDValue Tmp1;    
     TargetLowering::LegalizeAction action =
@@ -7763,6 +7869,44 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) {
     }
     break;
   }
+  case ISD::CONVERT_RNDSAT: {
+    SDValue RndOp = Node->getOperand(3);
+    SDValue SatOp = Node->getOperand(4);
+
+    TargetLowering::LegalizeAction action =
+      TLI.getOperationAction(Node->getOpcode(), WidenVT);
+
+    SDValue SrcOp = Node->getOperand(0);
+
+    // Converts between two different types so we need to determine
+    // the correct widen type for the input operand.
+    MVT SVT = SrcOp.getValueType();
+    assert(SVT.isVector() && "can not widen non vector type");
+    MVT SEVT = SVT.getVectorElementType();
+    MVT SWidenVT =  MVT::getVectorVT(SEVT, NewNumElts);
+
+    SrcOp = WidenVectorOp(SrcOp, SWidenVT);
+    assert(SrcOp.getValueType() == WidenVT);
+    SDValue DTyOp = DAG.getValueType(WidenVT);
+    SDValue STyOp = DAG.getValueType(SrcOp.getValueType());
+    ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(Node)->getCvtCode();
+
+    Result = DAG.getConvertRndSat(WidenVT, SrcOp, DTyOp, STyOp,
+                                  RndOp, SatOp, CvtCode);
+    switch (action)  {
+    default: assert(0 && "action not supported");
+    case TargetLowering::Legal:
+      break;
+    case TargetLowering::Promote:
+      // We defer the promotion to when we legalize the op
+      break;
+    case TargetLowering::Expand:
+      // Expand the operation into a bunch of nasty scalar code.
+      Result = LegalizeOp(UnrollVectorOp(Result));
+      break;
+    }
+    break;
+  }
   case ISD::FPOW:
   case ISD::FPOWI: 
   case ISD::ADD:
@@ -7857,15 +8001,38 @@ SDValue SelectionDAGLegalize::WidenVectorOp(SDValue Op, MVT WidenVT) {
     break;
   }
   case ISD::EXTRACT_SUBVECTOR: {
-    SDValue Tmp1;
-
-    // The incoming vector might already be the proper type
-    if (Node->getOperand(0).getValueType() != WidenVT)
-      Tmp1 = WidenVectorOp(Node->getOperand(0), WidenVT);
-    else
-      Tmp1 = Node->getOperand(0);
-    assert(Tmp1.getValueType() == WidenVT);
-    Result = DAG.getNode(Node->getOpcode(), WidenVT, Tmp1, Node->getOperand(1));
+    SDValue Tmp1 = Node->getOperand(0);
+    SDValue Idx = Node->getOperand(1);
+    ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx);
+    if (CIdx && CIdx->getZExtValue() == 0) {
+      // Since we are access the start of the vector, the incoming
+      // vector type might be the proper.
+      MVT Tmp1VT = Tmp1.getValueType();
+      if (Tmp1VT == WidenVT)
+        return Tmp1;
+      else {
+        unsigned Tmp1VTNumElts = Tmp1VT.getVectorNumElements();
+        if (Tmp1VTNumElts < NewNumElts)
+          Result = WidenVectorOp(Tmp1, WidenVT);
+        else
+          Result = DAG.getNode(ISD::EXTRACT_SUBVECTOR, WidenVT, Tmp1, Idx);
+      }
+    } else if (NewNumElts % NumElts == 0) {
+      // Widen the extracted subvector.
+      unsigned NumConcat = NewNumElts / NumElts;
+      SDValue UndefVal = DAG.getNode(ISD::UNDEF, VT);
+      SmallVector<SDValue, 8> MOps;
+      MOps.push_back(Op);
+      for (unsigned i = 1; i != NumConcat; ++i) {
+        MOps.push_back(UndefVal);
+      }
+      Result = LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, WidenVT,
+                                      &MOps[0], MOps.size()));
+    } else {
+      assert(0 && "can not widen extract subvector");
+     // This could be implemented using insert and build vector but I would
+     // like to see when this happens.
+    }
     break;
   }
 
@@ -8094,7 +8261,7 @@ SDValue SelectionDAGLegalize::genWidenVectorLoads(SDValueVector& LdChain,
       FindWidenVecType(TLI, LdWidth, ResType, EVT, VecEVT);
       EVTWidth = EVT.getSizeInBits();
       // Readjust position and vector position based on new load type
-      Idx = Idx * (oEVTWidth/EVTWidth)+1;
+      Idx = Idx * (oEVTWidth/EVTWidth);
       VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, VecOp);
     }
       
@@ -8159,7 +8326,7 @@ void SelectionDAGLegalize::genWidenVectorStores(SDValueVector& StChain,
                                                 int         SVOffset,
                                                 unsigned    Alignment,
                                                 bool        isVolatile,
-                                                SDValue   ValOp,
+                                                SDValue     ValOp,
                                                 unsigned    StWidth) {
   // Breaks the stores into a series of power of 2 width stores.  For any
   // width, we convert the vector to the vector of element size that we
@@ -8174,7 +8341,7 @@ void SelectionDAGLegalize::genWidenVectorStores(SDValueVector& StChain,
 
   SDValue VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, ValOp);
   SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EVT, VecOp,
-                                  DAG.getIntPtrConstant(0));
+                            DAG.getIntPtrConstant(0));
   SDValue StOp = DAG.getStore(Chain, EOp, BasePtr, SV, SVOffset,
                                isVolatile, Alignment);
   StChain.push_back(StOp);
@@ -8201,12 +8368,12 @@ void SelectionDAGLegalize::genWidenVectorStores(SDValueVector& StChain,
       FindWidenVecType(TLI, StWidth, VVT, EVT, VecEVT);
       EVTWidth = EVT.getSizeInBits();
       // Readjust position and vector position based on new load type
-      Idx = Idx * (oEVTWidth/EVTWidth)+1;
+      Idx = Idx * (oEVTWidth/EVTWidth);
       VecOp = DAG.getNode(ISD::BIT_CONVERT, VecEVT, VecOp);
     }
     
     EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EVT, VecOp,
-                      DAG.getIntPtrConstant(Idx));
+                      DAG.getIntPtrConstant(Idx++));
     StChain.push_back(DAG.getStore(Chain, EOp, BasePtr, SV,
                                    SVOffset + Offset, isVolatile,
                                    MinAlign(Alignment, Offset)));