Add sub/mul overflow intrinsics. This currently doesn't have a
[oota-llvm.git] / lib / CodeGen / SelectionDAG / SelectionDAGBuild.cpp
index 75910ef00d0e911d1883ecf722b8b1588d05fbba..5d81d224c88506d898e8ed901e9b9f9daf5faa4f 100644 (file)
@@ -2158,8 +2158,9 @@ void SelectionDAGLowering::visitSelect(User &I) {
                               SDValue(TrueVal.getNode(), TrueVal.getResNo() + i),
                               SDValue(FalseVal.getNode(), FalseVal.getResNo() + i));
 
-    setValue(&I, DAG.getMergeValues(DAG.getVTList(&ValueVTs[0], NumValues),
-                                    &Values[0], NumValues));
+    setValue(&I, DAG.getNode(ISD::MERGE_VALUES,
+                             DAG.getVTList(&ValueVTs[0], NumValues),
+                             &Values[0], NumValues));
   }
 }
 
@@ -2304,18 +2305,17 @@ static bool SequentialMask(SDValue Mask, unsigned SIndx) {
 }
 
 void SelectionDAGLowering::visitShuffleVector(User &I) {
-  SDValue Srcs[2];
-  Srcs[0] = getValue(I.getOperand(0));
-  Srcs[1] = getValue(I.getOperand(1));
+  SDValue Src1 = getValue(I.getOperand(0));
+  SDValue Src2 = getValue(I.getOperand(1));
   SDValue Mask = getValue(I.getOperand(2));
 
   MVT VT = TLI.getValueType(I.getType());
-  MVT SrcVT = Srcs[0].getValueType();
+  MVT SrcVT = Src1.getValueType();
   int MaskNumElts = Mask.getNumOperands();
   int SrcNumElts = SrcVT.getVectorNumElements();
 
   if (SrcNumElts == MaskNumElts) {
-    setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, VT, Srcs[0], Srcs[1], Mask));
+    setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, VT, Src1, Src2, Mask));
     return;
   }
 
@@ -2325,10 +2325,10 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
   if (SrcNumElts < MaskNumElts && MaskNumElts % SrcNumElts == 0) {
     // Mask is longer than the source vectors and is a multiple of the source
     // vectors.  We can use concatenate vector to make the mask and vectors
-    // length match.
+    // lengths match.
     if (SrcNumElts*2 == MaskNumElts && SequentialMask(Mask, 0)) {
       // The shuffle is concatenating two vectors together.
-      setValue(&I, DAG.getNode(ISD::CONCAT_VECTORS, VT, Srcs[0], Srcs[1]));
+      setValue(&I, DAG.getNode(ISD::CONCAT_VECTORS, VT, Src1, Src2));
       return;
     }
 
@@ -2336,16 +2336,20 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
     unsigned NumConcat = MaskNumElts / SrcNumElts;
     SDValue UndefVal = DAG.getNode(ISD::UNDEF, SrcVT);
 
-    SmallVector<SDValue, 8> MOps1, MOps2;
-    MOps1.push_back(Srcs[0]);
-    MOps2.push_back(Srcs[1]);
+    SDValue* MOps1 = new SDValue[NumConcat];
+    SDValue* MOps2 = new SDValue[NumConcat];
+    MOps1[0] = Src1;
+    MOps2[0] = Src2;
     for (unsigned i = 1; i != NumConcat; ++i) {
-      MOps1.push_back(UndefVal);
-      MOps2.push_back(UndefVal);
+      MOps1[i] = UndefVal;
+      MOps2[i] = UndefVal;
     }
-    Srcs[0] = DAG.getNode(ISD::CONCAT_VECTORS, VT, &MOps1[0], MOps1.size());
-    Srcs[1] = DAG.getNode(ISD::CONCAT_VECTORS, VT, &MOps2[0], MOps2.size());
-    
+    Src1 = DAG.getNode(ISD::CONCAT_VECTORS, VT, MOps1, NumConcat);
+    Src2 = DAG.getNode(ISD::CONCAT_VECTORS, VT, MOps2, NumConcat);
+
+    delete [] MOps1;
+    delete [] MOps2;
+
     // Readjust mask for new input vector length.
     SmallVector<SDValue, 8> MappedOps;
     for (int i = 0; i != MaskNumElts; ++i) {
@@ -2363,7 +2367,7 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
     Mask = DAG.getNode(ISD::BUILD_VECTOR, Mask.getValueType(),
                        &MappedOps[0], MappedOps.size());
 
-    setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, VT, Srcs[0], Srcs[1], Mask));
+    setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, VT, Src1, Src2, Mask));
     return;
   }
 
@@ -2371,13 +2375,13 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
     // Resulting vector is shorter than the incoming vector.
     if (SrcNumElts == MaskNumElts && SequentialMask(Mask,0)) {
       // Shuffle extracts 1st vector.
-      setValue(&I, Srcs[0]);
+      setValue(&I, Src1);
       return;
     }
 
     if (SrcNumElts == MaskNumElts && SequentialMask(Mask,MaskNumElts)) {
       // Shuffle extracts 2nd vector.
-      setValue(&I, Srcs[1]);
+      setValue(&I, Src2);
       return;
     }
 
@@ -2406,7 +2410,7 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
 
     // Check if the access is smaller than the vector size and can we find
     // a reasonable extract index.
-    int RangeUse[2];  // 0 = Unused, 1 = Extract, 2 = Can not Extract.
+    int RangeUse[2] = { 2, 2 };  // 0 = Unused, 1 = Extract, 2 = Can not Extract.
     int StartIdx[2];  // StartIdx to extract from
     for (int Input=0; Input < 2; ++Input) {
       if (MinRange[Input] == SrcNumElts+1 && MaxRange[Input] == -1) {
@@ -2414,19 +2418,17 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
         StartIdx[Input] = 0;
       } else if (MaxRange[Input] - MinRange[Input] < MaskNumElts) {
         // Fits within range but we should see if we can find a good
-        // start index that a multiple of the mask length.
+        // start index that is a multiple of the mask length.
         if (MaxRange[Input] < MaskNumElts) {
           RangeUse[Input] = 1; // Extract from beginning of the vector
           StartIdx[Input] = 0;
         } else {
           StartIdx[Input] = (MinRange[Input]/MaskNumElts)*MaskNumElts;
-          if (MaxRange[Input] - StartIdx[Input] < MaskNumElts) 
+          if (MaxRange[Input] - StartIdx[Input] < MaskNumElts &&
+              StartIdx[Input] + MaskNumElts < SrcNumElts) 
             RangeUse[Input] = 1; // Extract from a multiple of the mask length.
-          else
-            RangeUse[Input] = 2; // Can not extract
         }
-      } else
-        RangeUse[Input] = 2;  // Access doesn't fit within range
+      }
     }
 
     if (RangeUse[0] == 0 && RangeUse[0] == 0) {
@@ -2436,11 +2438,12 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
     else if (RangeUse[0] < 2 && RangeUse[1] < 2) {
       // Extract appropriate subvector and generate a vector shuffle
       for (int Input=0; Input < 2; ++Input) {
+        SDValue& Src = Input == 0 ? Src1 : Src2;
         if (RangeUse[Input] == 0) {
-          Srcs[Input] = DAG.getNode(ISD::UNDEF, VT);
+          Src = DAG.getNode(ISD::UNDEF, VT);
         } else {
-          Srcs[Input] = DAG.getNode(ISD::EXTRACT_SUBVECTOR, VT, Srcs[Input],
-                                    DAG.getIntPtrConstant(StartIdx[Input]));
+          Src = DAG.getNode(ISD::EXTRACT_SUBVECTOR, VT, Src,
+                            DAG.getIntPtrConstant(StartIdx[Input]));
         }
       }
       // Calculate new mask.
@@ -2461,7 +2464,7 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
       }
       Mask = DAG.getNode(ISD::BUILD_VECTOR, Mask.getValueType(),
                          &MappedOps[0], MappedOps.size());
-      setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, VT, Srcs[0], Srcs[1], Mask));
+      setValue(&I, DAG.getNode(ISD::VECTOR_SHUFFLE, VT, Src1, Src2, Mask));
       return;
     }
   }
@@ -2480,10 +2483,10 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
       assert(isa<ConstantSDNode>(Arg) && "Invalid VECTOR_SHUFFLE mask!");
       int Idx = cast<ConstantSDNode>(Arg)->getZExtValue();
       if (Idx < SrcNumElts)
-        Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, Srcs[0],
+        Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, Src1,
                                   DAG.getConstant(Idx, PtrVT)));
       else
-        Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, Srcs[1],
+        Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, Src2,
                                   DAG.getConstant(Idx - SrcNumElts, PtrVT)));
     }
   }
@@ -2526,8 +2529,9 @@ void SelectionDAGLowering::visitInsertValue(InsertValueInst &I) {
     Values[i] = IntoUndef ? DAG.getNode(ISD::UNDEF, AggValueVTs[i]) :
                 SDValue(Agg.getNode(), Agg.getResNo() + i);
 
-  setValue(&I, DAG.getMergeValues(DAG.getVTList(&AggValueVTs[0], NumAggValues),
-                                  &Values[0], NumAggValues));
+  setValue(&I, DAG.getNode(ISD::MERGE_VALUES,
+                           DAG.getVTList(&AggValueVTs[0], NumAggValues),
+                           &Values[0], NumAggValues));
 }
 
 void SelectionDAGLowering::visitExtractValue(ExtractValueInst &I) {
@@ -2554,8 +2558,9 @@ void SelectionDAGLowering::visitExtractValue(ExtractValueInst &I) {
                     Agg.getNode()->getValueType(Agg.getResNo() + i)) :
         SDValue(Agg.getNode(), Agg.getResNo() + i);
 
-  setValue(&I, DAG.getMergeValues(DAG.getVTList(&ValValueVTs[0], NumValValues),
-                                  &Values[0], NumValValues));
+  setValue(&I, DAG.getNode(ISD::MERGE_VALUES,
+                           DAG.getVTList(&ValValueVTs[0], NumValValues),
+                           &Values[0], NumValValues));
 }
 
 
@@ -2719,8 +2724,9 @@ void SelectionDAGLowering::visitLoad(LoadInst &I) {
       PendingLoads.push_back(Chain);
   }
 
-  setValue(&I, DAG.getMergeValues(DAG.getVTList(&ValueVTs[0], NumValues),
-                                  &Values[0], NumValues));
+  setValue(&I, DAG.getNode(ISD::MERGE_VALUES,
+                           DAG.getVTList(&ValueVTs[0], NumValues),
+                           &Values[0], NumValues));
 }
 
 
@@ -2962,6 +2968,23 @@ SelectionDAGLowering::implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op) {
   return 0;
 }
 
+// implVisitAluOverflow - Lower an overflow instrinsics
+const char *
+SelectionDAGLowering::implVisitAluOverflow(CallInst &I, ISD::NodeType Op) {
+    SDValue Op1 = getValue(I.getOperand(1));
+    SDValue Op2 = getValue(I.getOperand(2));
+
+    MVT ValueVTs[] = { Op1.getValueType(), MVT::i1 };
+    SDValue Ops[] = { Op1, Op2 };
+
+    SDValue Result =
+      DAG.getNode(Op,
+                  DAG.getVTList(&ValueVTs[0], 2), &Ops[0], 2);
+
+    setValue(&I, Result);
+    return 0;
+  }
+
 /// visitExp - Lower an exp intrinsic. Handles the special sequences for
 /// limited-precision mode.
 void
@@ -3662,8 +3685,7 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
   case Intrinsic::longjmp:
     return "_longjmp"+!TLI.usesUnderscoreLongJmp();
     break;
-  case Intrinsic::memcpy_i32:
-  case Intrinsic::memcpy_i64: {
+  case Intrinsic::memcpy: {
     SDValue Op1 = getValue(I.getOperand(1));
     SDValue Op2 = getValue(I.getOperand(2));
     SDValue Op3 = getValue(I.getOperand(3));
@@ -3672,8 +3694,7 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
                               I.getOperand(1), 0, I.getOperand(2), 0));
     return 0;
   }
-  case Intrinsic::memset_i32:
-  case Intrinsic::memset_i64: {
+  case Intrinsic::memset: {
     SDValue Op1 = getValue(I.getOperand(1));
     SDValue Op2 = getValue(I.getOperand(2));
     SDValue Op3 = getValue(I.getOperand(3));
@@ -3682,8 +3703,7 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
                               I.getOperand(1), 0));
     return 0;
   }
-  case Intrinsic::memmove_i32:
-  case Intrinsic::memmove_i64: {
+  case Intrinsic::memmove: {
     SDValue Op1 = getValue(I.getOperand(1));
     SDValue Op2 = getValue(I.getOperand(2));
     SDValue Op3 = getValue(I.getOperand(3));
@@ -4093,29 +4113,18 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
     return 0;
   }
 
-  case Intrinsic::sadd_with_overflow: {
-    // Convert to "ISD::SADDO" instruction.
-    SDValue Chain = getRoot();
-    SDValue Op1 = getValue(I.getOperand(1));
-    SDValue Op2 = getValue(I.getOperand(2));
-    MVT Ty = Op1.getValueType();
-
-    MVT ValueVTs[] = { Ty, MVT::i1, MVT::Other };
-    SDValue Ops[] = { Op1, Op2, Chain };
-
-    SDValue Result = DAG.getNode(ISD::SADDO, DAG.getVTList(&ValueVTs[0], 3),
-                                 &Ops[0], 3);
-
-    setValue(&I, Result);
-
-    unsigned NumArgRegs = Result.getNode()->getNumValues() - 1;
-    DAG.setRoot(SDValue(Result.getNode(), NumArgRegs));
-    return 0;
-  }
-  case Intrinsic::uadd_with_overflow: {
-    // TODO: Convert to "ISD::UADDO" instruction.
-    return 0;
-  }
+  case Intrinsic::uadd_with_overflow:
+    return implVisitAluOverflow(I, ISD::UADDO);
+  case Intrinsic::sadd_with_overflow:
+    return implVisitAluOverflow(I, ISD::SADDO);
+  case Intrinsic::usub_with_overflow:
+    return implVisitAluOverflow(I, ISD::USUBO);
+  case Intrinsic::ssub_with_overflow:
+    return implVisitAluOverflow(I, ISD::SSUBO);
+  case Intrinsic::umul_with_overflow:
+    return implVisitAluOverflow(I, ISD::UMULO);
+  case Intrinsic::smul_with_overflow:
+    return implVisitAluOverflow(I, ISD::SMULO);
 
   case Intrinsic::prefetch: {
     SDValue Ops[4];
@@ -4552,8 +4561,9 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
     Parts.clear();
   }
 
-  return DAG.getMergeValues(DAG.getVTList(&ValueVTs[0], ValueVTs.size()),
-                            &Values[0], ValueVTs.size());
+  return DAG.getNode(ISD::MERGE_VALUES,
+                     DAG.getVTList(&ValueVTs[0], ValueVTs.size()),
+                     &Values[0], ValueVTs.size());
 }
 
 /// getCopyToRegs - Emit a series of CopyToReg nodes that copies the
@@ -5688,8 +5698,9 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
                          AssertOp);
       ReturnValues.push_back(ReturnValue);
     }
-    Res = DAG.getMergeValues(DAG.getVTList(&RetTys[0], RetTys.size()),
-                             &ReturnValues[0], ReturnValues.size());
+    Res = DAG.getNode(ISD::MERGE_VALUES,
+                      DAG.getVTList(&RetTys[0], RetTys.size()),
+                      &ReturnValues[0], ReturnValues.size());
   }
 
   return std::make_pair(Res, Chain);