- Re-apply 52748 and friends with fix. GetConstantStringInfo() returns an empty string for ConstantAggregateZero case which surprises selectiondag.
- Correctly handle memcpy from constant string which is zero-initialized.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52891 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index f1c2ecf..023be5c 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/Constants.h"
+#include "llvm/Analysis/ValueTracking.h"
 #include "llvm/GlobalAlias.h"
 #include "llvm/GlobalVariable.h"
 #include "llvm/Intrinsics.h"
@@ -747,18 +748,14 @@
 }
 
 SDOperand SelectionDAG::getConstant(uint64_t Val, MVT VT, bool isT) {
-  MVT EltVT =
-    VT.isVector() ? VT.getVectorElementType() : VT;
-
+  MVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT;
   return getConstant(APInt(EltVT.getSizeInBits(), Val), VT, isT);
 }
 
 SDOperand SelectionDAG::getConstant(const APInt &Val, MVT VT, bool isT) {
   assert(VT.isInteger() && "Cannot create FP integer constant!");
 
-  MVT EltVT =
-    VT.isVector() ? VT.getVectorElementType() : VT;
-  
+  MVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT;
   assert(Val.getBitWidth() == EltVT.getSizeInBits() &&
          "APInt size does not match type size!");
 
@@ -2554,6 +2551,16 @@
 static SDOperand getMemsetStringVal(MVT VT, SelectionDAG &DAG,
                                     const TargetLowering &TLI,
                                     std::string &Str, unsigned Offset) {
+  // Handle vector with all elements zero.
+  if (Str.empty()) {
+    if (VT.isInteger())
+      return DAG.getConstant(0, VT);
+    unsigned NumElts = VT.getVectorNumElements();
+    MVT EltVT = (VT.getVectorElementType() == MVT::f32) ? MVT::i32 : MVT::i64;
+    return DAG.getNode(ISD::BIT_CONVERT, VT,
+                       DAG.getConstant(0, MVT::getVectorVT(EltVT, NumElts)));
+  }
+
   assert(!VT.isVector() && "Can't handle vector type here!");
   unsigned NumBits = VT.getSizeInBits();
   unsigned MSB = NumBits / 8;
@@ -2577,8 +2584,7 @@
 
 /// isMemSrcFromString - Returns true if memcpy source is a string constant.
 ///
-static bool isMemSrcFromString(SDOperand Src, std::string &Str,
-                               uint64_t &SrcOff) {
+static bool isMemSrcFromString(SDOperand Src, std::string &Str) {
   unsigned SrcDelta = 0;
   GlobalAddressSDNode *G = NULL;
   if (Src.getOpcode() == ISD::GlobalAddress)
@@ -2593,13 +2599,8 @@
     return false;
 
   GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getGlobal());
-  if (GV && GV->isConstant()) {
-    Str = GV->getStringValue(false);
-    if (!Str.empty()) {
-      SrcOff += SrcDelta;
-      return true;
-    }
-  }
+  if (GV && GetConstantStringInfo(GV, Str, SrcDelta, false))
+    return true;
 
   return false;
 }
@@ -2611,14 +2612,12 @@
 bool MeetsMaxMemopRequirement(std::vector<MVT> &MemOps,
                               SDOperand Dst, SDOperand Src,
                               unsigned Limit, uint64_t Size, unsigned &Align,
+                              std::string &Str, bool &isSrcStr,
                               SelectionDAG &DAG,
                               const TargetLowering &TLI) {
-  bool AllowUnalign = TLI.allowsUnalignedMemoryAccesses();
-
-  std::string Str;
-  uint64_t SrcOff = 0;
-  bool isSrcStr = isMemSrcFromString(Src, Str, SrcOff);
+  isSrcStr = isMemSrcFromString(Src, Str);
   bool isSrcConst = isa<ConstantSDNode>(Src);
+  bool AllowUnalign = TLI.allowsUnalignedMemoryAccesses();
   MVT VT= TLI.getOptimalMemOpType(Size, Align, isSrcConst, isSrcStr);
   if (VT != MVT::iAny) {
     unsigned NewAlign = (unsigned)
@@ -2707,26 +2706,28 @@
   if (!AlwaysInline)
     Limit = TLI.getMaxStoresPerMemcpy();
   unsigned DstAlign = Align;  // Destination alignment can change.
+  std::string Str;
+  bool CopyFromStr;
   if (!MeetsMaxMemopRequirement(MemOps, Dst, Src, Limit, Size, DstAlign,
-                                DAG, TLI))
+                                Str, CopyFromStr, DAG, TLI))
     return SDOperand();
 
-  std::string Str;
-  uint64_t SrcOff = 0, DstOff = 0;
-  bool CopyFromStr = isMemSrcFromString(Src, Str, SrcOff);
 
+  bool isZeroStr = CopyFromStr && Str.empty();
   SmallVector<SDOperand, 8> OutChains;
   unsigned NumMemOps = MemOps.size();
+  uint64_t SrcOff = 0, DstOff = 0;
   for (unsigned i = 0; i < NumMemOps; i++) {
     MVT VT = MemOps[i];
     unsigned VTSize = VT.getSizeInBits() / 8;
     SDOperand Value, Store;
 
-    if (CopyFromStr && !VT.isVector()) {
+    if (CopyFromStr && (isZeroStr || !VT.isVector())) {
       // It's unlikely a store of a vector immediate can be done in a single
       // instruction. It would require a load from a constantpool first.
-      // FIXME: Handle cases where store of vector immediate is done in a
-      // single instruction.
+      // We also handle store a vector with all zero's.
+      // FIXME: Handle other cases where store of vector immediate is done in
+      // a single instruction.
       Value = getMemsetStringVal(VT, DAG, TLI, Str, SrcOff);
       Store = DAG.getStore(Chain, Value,
                            getMemBasePlusOffset(Dst, DstOff, DAG),
@@ -2763,8 +2764,10 @@
   if (!AlwaysInline)
     Limit = TLI.getMaxStoresPerMemmove();
   unsigned DstAlign = Align;  // Destination alignment can change.
+  std::string Str;
+  bool CopyFromStr;
   if (!MeetsMaxMemopRequirement(MemOps, Dst, Src, Limit, Size, DstAlign,
-                                DAG, TLI))
+                                Str, CopyFromStr, DAG, TLI))
     return SDOperand();
 
   uint64_t SrcOff = 0, DstOff = 0;
@@ -2814,8 +2817,10 @@
   // Expand memset to a series of load/store ops if the size operand
   // falls below a certain threshold.
   std::vector<MVT> MemOps;
+  std::string Str;
+  bool CopyFromStr;
   if (!MeetsMaxMemopRequirement(MemOps, Dst, Src, TLI.getMaxStoresPerMemset(),
-                                Size, Align, DAG, TLI))
+                                Size, Align, Str, CopyFromStr, DAG, TLI))
     return SDOperand();
 
   SmallVector<SDOperand, 8> OutChains;