Add r149110 back with a fix for when the vector and the int have the same
width.

llvm-svn: 149151
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index fe28926..121e334 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -52,6 +52,44 @@
   if (C->isAllOnesValue() && !DestTy->isX86_MMXTy())
     return Constant::getAllOnesValue(DestTy);
 
+  // Handle a vector->integer cast.
+  if (IntegerType *IT = dyn_cast<IntegerType>(DestTy)) {
+    // FIXME: Remove ConstantVector support.
+    if ((!isa<ConstantDataVector>(C) && !isa<ConstantVector>(C)) ||
+        // TODO: Handle big endian someday.
+        !TD.isLittleEndian())
+      return ConstantExpr::getBitCast(C, DestTy);
+
+    unsigned NumSrcElts = C->getType()->getVectorNumElements();
+    
+    // If the vector is a vector of floating point, convert it to vector of int
+    // to simplify things.
+    if (C->getType()->getVectorElementType()->isFloatingPointTy()) {
+      unsigned FPWidth =
+        C->getType()->getVectorElementType()->getPrimitiveSizeInBits();
+      Type *SrcIVTy =
+        VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumSrcElts);
+      // Ask VMCore to do the conversion now that #elts line up.
+      C = ConstantExpr::getBitCast(C, SrcIVTy);
+    }
+    
+    // Now that we know that the input value is a vector of integers, just shift
+    // and insert them into our result.
+    unsigned BitShift =
+      TD.getTypeAllocSizeInBits(C->getType()->getVectorElementType());
+    APInt Result(IT->getBitWidth(), 0);
+    for (unsigned i = 0; i != NumSrcElts; ++i) {
+      // FIXME: Rework when we have ConstantDataVector.
+      ConstantInt *Elt=dyn_cast_or_null<ConstantInt>(C->getAggregateElement(i));
+      if (Elt == 0)  // Elt must be a constant expr or something.
+        return ConstantExpr::getBitCast(C, DestTy);
+      
+      Result |= Elt->getValue().zextOrSelf(IT->getBitWidth()) << i*BitShift;
+    }
+   
+    return ConstantInt::get(IT, Result);
+  }
+  
   // The code below only handles casts to vectors currently.
   VectorType *DestVTy = dyn_cast<VectorType>(DestTy);
   if (DestVTy == 0)
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index b5411be..c580dd3 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -1123,6 +1123,18 @@
   return *this;
 }
 
+APInt APInt::zextOrSelf(unsigned width) const {
+  if (BitWidth < width)
+    return zext(width);
+  return *this;
+}
+
+APInt APInt::sextOrSelf(unsigned width) const {
+  if (BitWidth < width)
+    return sext(width);
+  return *this;
+}
+
 /// Arithmetic right-shift this APInt by shiftAmt.
 /// @brief Arithmetic right-shift function.
 APInt APInt::ashr(const APInt &shiftAmt) const {