Expand small memmovs using inline code. Set the X86 threshold for expanding
[oota-llvm.git] / lib / CodeGen / SelectionDAG / DAGCombiner.cpp
index 4eccb815e3b9825231e44e1595e108aea7a8c64c..31cbdb9c787f46b304b02fcb5326ff05a667911f 100644 (file)
@@ -29,6 +29,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
 #include <algorithm>
+#include <set>
 using namespace llvm;
 
 STATISTIC(NodesCombined   , "Number of dag nodes combined");
@@ -177,6 +178,7 @@ namespace {
     SDOperand visitSIGN_EXTEND_INREG(SDNode *N);
     SDOperand visitTRUNCATE(SDNode *N);
     SDOperand visitBIT_CONVERT(SDNode *N);
+    SDOperand visitBUILD_PAIR(SDNode *N);
     SDOperand visitFADD(SDNode *N);
     SDOperand visitFSUB(SDNode *N);
     SDOperand visitFMUL(SDNode *N);
@@ -217,6 +219,7 @@ namespace {
                             ISD::CondCode Cond, bool foldBooleans = true);
     SDOperand SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, 
                                          unsigned HiOp);
+    SDOperand CombineConsecutiveLoads(SDNode *N, MVT::ValueType VT);
     SDOperand ConstantFoldBIT_CONVERTofBUILD_VECTOR(SDNode *, MVT::ValueType);
     SDOperand BuildSDIV(SDNode *N);
     SDOperand BuildUDIV(SDNode *N);
@@ -710,6 +713,7 @@ SDOperand DAGCombiner::visit(SDNode *N) {
   case ISD::SIGN_EXTEND_INREG:  return visitSIGN_EXTEND_INREG(N);
   case ISD::TRUNCATE:           return visitTRUNCATE(N);
   case ISD::BIT_CONVERT:        return visitBIT_CONVERT(N);
+  case ISD::BUILD_PAIR:         return visitBUILD_PAIR(N);
   case ISD::FADD:               return visitFADD(N);
   case ISD::FSUB:               return visitFSUB(N);
   case ISD::FMUL:               return visitFMUL(N);
@@ -2773,20 +2777,18 @@ SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
   if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND)
     return DAG.getNode(ISD::SIGN_EXTEND, VT, N0.getOperand(0));
   
-  // fold (sext (truncate (load x))) -> (sext (smaller load x))
-  // fold (sext (truncate (srl (load x), c))) -> (sext (smaller load (x+c/n)))
   if (N0.getOpcode() == ISD::TRUNCATE) {
+    // fold (sext (truncate (load x))) -> (sext (smaller load x))
+    // fold (sext (truncate (srl (load x), c))) -> (sext (smaller load (x+c/n)))
     SDOperand NarrowLoad = ReduceLoadWidth(N0.Val);
     if (NarrowLoad.Val) {
       if (NarrowLoad.Val != N0.Val)
         CombineTo(N0.Val, NarrowLoad);
       return DAG.getNode(ISD::SIGN_EXTEND, VT, NarrowLoad);
     }
-  }
 
-  // See if the value being truncated is already sign extended.  If so, just
-  // eliminate the trunc/sext pair.
-  if (N0.getOpcode() == ISD::TRUNCATE) {
+    // See if the value being truncated is already sign extended.  If so, just
+    // eliminate the trunc/sext pair.
     SDOperand Op = N0.getOperand(0);
     unsigned OpBits   = MVT::getSizeInBits(Op.getValueType());
     unsigned MidBits  = MVT::getSizeInBits(N0.getValueType());
@@ -2887,6 +2889,11 @@ SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
     if (SCC.Val) return SCC;
   }
   
+  // fold (sext x) -> (zext x) if the sign bit is known zero.
+  if ((!AfterLegalize || TLI.isOperationLegal(ISD::ZERO_EXTEND, VT)) &&
+      DAG.SignBitIsZero(N0))
+    return DAG.getNode(ISD::ZERO_EXTEND, VT, N0);
+  
   return SDOperand();
 }
 
@@ -3351,6 +3358,40 @@ SDOperand DAGCombiner::visitTRUNCATE(SDNode *N) {
   return ReduceLoadWidth(N);
 }
 
+static SDNode *getBuildPairElt(SDNode *N, unsigned i) {
+  SDOperand Elt = N->getOperand(i);
+  if (Elt.getOpcode() != ISD::MERGE_VALUES)
+    return Elt.Val;
+  return Elt.getOperand(Elt.ResNo).Val;
+}
+
+/// CombineConsecutiveLoads - build_pair (load, load) -> load
+/// if load locations are consecutive. 
+SDOperand DAGCombiner::CombineConsecutiveLoads(SDNode *N, MVT::ValueType VT) {
+  assert(N->getOpcode() == ISD::BUILD_PAIR);
+
+  SDNode *LD1 = getBuildPairElt(N, 0);
+  if (!ISD::isNON_EXTLoad(LD1) || !LD1->hasOneUse())
+    return SDOperand();
+  MVT::ValueType LD1VT = LD1->getValueType(0);
+  SDNode *LD2 = getBuildPairElt(N, 1);
+  const MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
+  if (ISD::isNON_EXTLoad(LD2) &&
+      LD2->hasOneUse() &&
+      TLI.isConsecutiveLoad(LD2, LD1, MVT::getSizeInBits(LD1VT)/8, 1, MFI)) {
+    LoadSDNode *LD = cast<LoadSDNode>(LD1);
+    unsigned Align = LD->getAlignment();
+    unsigned NewAlign = TLI.getTargetMachine().getTargetData()->
+      getABITypeAlignment(MVT::getTypeForValueType(VT));
+    if ((!AfterLegalize || TLI.isTypeLegal(VT)) &&
+        TLI.isOperationLegal(ISD::LOAD, VT) && NewAlign <= Align)
+      return DAG.getLoad(VT, LD->getChain(), LD->getBasePtr(),
+                         LD->getSrcValue(), LD->getSrcValueOffset(),
+                         LD->isVolatile(), Align);
+  }
+  return SDOperand();
+}
+
 SDOperand DAGCombiner::visitBIT_CONVERT(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
   MVT::ValueType VT = N->getValueType(0);
@@ -3458,10 +3499,22 @@ SDOperand DAGCombiner::visitBIT_CONVERT(SDNode *N) {
 
     return DAG.getNode(ISD::OR, VT, X, Cst);
   }
+
+  // bitconvert(build_pair(ld, ld)) -> ld iff load locations are consecutive. 
+  if (N0.getOpcode() == ISD::BUILD_PAIR) {
+    SDOperand CombineLD = CombineConsecutiveLoads(N0.Val, VT);
+    if (CombineLD.Val)
+      return CombineLD;
+  }
   
   return SDOperand();
 }
 
+SDOperand DAGCombiner::visitBUILD_PAIR(SDNode *N) {
+  MVT::ValueType VT = N->getValueType(0);
+  return CombineConsecutiveLoads(N, VT);
+}
+
 /// ConstantFoldBIT_CONVERTofBUILD_VECTOR - We know that BV is a build_vector
 /// node with Constant, ConstantFP or Undef operands.  DstEltVT indicates the 
 /// destination element value type.
@@ -3880,7 +3933,8 @@ SDOperand DAGCombiner::visitFP_EXTEND(SDNode *N) {
   MVT::ValueType VT = N->getValueType(0);
   
   // If this is fp_round(fpextend), don't fold it, allow ourselves to be folded.
-  if (N->hasOneUse() && (N->use_begin())->getOpcode() == ISD::FP_ROUND)
+  if (N->hasOneUse() && 
+      N->use_begin()->getSDOperand().getOpcode() == ISD::FP_ROUND)
     return SDOperand();
 
   // fold (fp_extend c1fp) -> c1fp
@@ -4627,49 +4681,82 @@ SDOperand DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) {
 }
 
 SDOperand DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) {
+  // (vextract (v4f32 load $addr), c) -> (f32 load $addr+c*size)
+  // (vextract (v4f32 s2v (f32 load $addr)), c) -> (f32 load $addr+c*size)
+  // (vextract (v4f32 shuffle (load $addr), <1,u,u,u>), 0) -> (f32 load $addr)
+
+  // Perform only after legalization to ensure build_vector / vector_shuffle
+  // optimizations have already been done.
+  if (!AfterLegalize) return SDOperand();
+
   SDOperand InVec = N->getOperand(0);
   SDOperand EltNo = N->getOperand(1);
 
-  // (vextract (v4f32 s2v (f32 load $addr)), 0) -> (f32 load $addr)
-  // (vextract (v4i32 bc (v4f32 s2v (f32 load $addr))), 0) -> (i32 load $addr)
   if (isa<ConstantSDNode>(EltNo)) {
     unsigned Elt = cast<ConstantSDNode>(EltNo)->getValue();
     bool NewLoad = false;
-    if (Elt == 0) {
-      MVT::ValueType VT = InVec.getValueType();
-      MVT::ValueType EVT = MVT::getVectorElementType(VT);
-      MVT::ValueType LVT = EVT;
-      unsigned NumElts = MVT::getVectorNumElements(VT);
-      if (InVec.getOpcode() == ISD::BIT_CONVERT) {
-        MVT::ValueType BCVT = InVec.getOperand(0).getValueType();
-        if (!MVT::isVector(BCVT) ||
-            NumElts != MVT::getVectorNumElements(BCVT))
-          return SDOperand();
+    MVT::ValueType VT = InVec.getValueType();
+    MVT::ValueType EVT = MVT::getVectorElementType(VT);
+    MVT::ValueType LVT = EVT;
+    if (InVec.getOpcode() == ISD::BIT_CONVERT) {
+      MVT::ValueType BCVT = InVec.getOperand(0).getValueType();
+      if (!MVT::isVector(BCVT)
+          || (MVT::getSizeInBits(EVT) >
+              MVT::getSizeInBits(MVT::getVectorElementType(BCVT))))
+        return SDOperand();
+      InVec = InVec.getOperand(0);
+      EVT = MVT::getVectorElementType(BCVT);
+      NewLoad = true;
+    }
+
+    LoadSDNode *LN0 = NULL;
+    if (ISD::isNormalLoad(InVec.Val))
+      LN0 = cast<LoadSDNode>(InVec);
+    else if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR &&
+             InVec.getOperand(0).getValueType() == EVT &&
+             ISD::isNormalLoad(InVec.getOperand(0).Val)) {
+      LN0 = cast<LoadSDNode>(InVec.getOperand(0));
+    } else if (InVec.getOpcode() == ISD::VECTOR_SHUFFLE) {
+      // (vextract (vector_shuffle (load $addr), v2, <1, u, u, u>), 1)
+      // =>
+      // (load $addr+1*size)
+      unsigned Idx = cast<ConstantSDNode>(InVec.getOperand(2).
+                                          getOperand(Elt))->getValue();
+      unsigned NumElems = InVec.getOperand(2).getNumOperands();
+      InVec = (Idx < NumElems) ? InVec.getOperand(0) : InVec.getOperand(1);
+      if (InVec.getOpcode() == ISD::BIT_CONVERT)
         InVec = InVec.getOperand(0);
-        EVT = MVT::getVectorElementType(BCVT);
-        NewLoad = true;
+      if (ISD::isNormalLoad(InVec.Val)) {
+        LN0 = cast<LoadSDNode>(InVec);
+        Elt = (Idx < NumElems) ? Idx : Idx - NumElems;
       }
-      if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR &&
-          InVec.getOperand(0).getValueType() == EVT &&
-          ISD::isNormalLoad(InVec.getOperand(0).Val) &&
-          InVec.getOperand(0).hasOneUse()) {
-        LoadSDNode *LN0 = cast<LoadSDNode>(InVec.getOperand(0));
-        unsigned Align = LN0->getAlignment();
-        if (NewLoad) {
-          // Check the resultant load doesn't need a higher alignment than the
-          // original load.
-          unsigned NewAlign = TLI.getTargetMachine().getTargetData()->
-            getABITypeAlignment(MVT::getTypeForValueType(LVT));
-          if (!TLI.isOperationLegal(ISD::LOAD, LVT) || NewAlign > Align)
-            return SDOperand();
-          Align = NewAlign;
-        }
+    }
+    if (!LN0 || !LN0->hasOneUse())
+      return SDOperand();
 
-        return DAG.getLoad(LVT, LN0->getChain(), LN0->getBasePtr(),
-                           LN0->getSrcValue(), LN0->getSrcValueOffset(),
-                           LN0->isVolatile(), Align);
-      }
+    unsigned Align = LN0->getAlignment();
+    if (NewLoad) {
+      // Check the resultant load doesn't need a higher alignment than the
+      // original load.
+      unsigned NewAlign = TLI.getTargetMachine().getTargetData()->
+        getABITypeAlignment(MVT::getTypeForValueType(LVT));
+      if (!TLI.isOperationLegal(ISD::LOAD, LVT) || NewAlign > Align)
+        return SDOperand();
+      Align = NewAlign;
+    }
+
+    SDOperand NewPtr = LN0->getBasePtr();
+    if (Elt) {
+      unsigned PtrOff = MVT::getSizeInBits(LVT) * Elt / 8;
+      MVT::ValueType PtrType = NewPtr.getValueType();
+      if (TLI.isBigEndian())
+        PtrOff = MVT::getSizeInBits(VT) / 8 - PtrOff;
+      NewPtr = DAG.getNode(ISD::ADD, PtrType, NewPtr,
+                           DAG.getConstant(PtrOff, PtrType));
     }
+    return DAG.getLoad(LVT, LN0->getChain(), NewPtr,
+                       LN0->getSrcValue(), LN0->getSrcValueOffset(),
+                       LN0->isVolatile(), Align);
   }
   return SDOperand();
 }