fold fp_round(fp_round(x)) -> fp_round(x).
[oota-llvm.git] / lib / CodeGen / SelectionDAG / DAGCombiner.cpp
index cfa46e6b59136714ea0dfc8763ce6f82c6ef6ea4..5ebda953fbd3a18453345b6fd71518a21c088fec 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by Nate Begeman and is distributed under the
-// University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -135,6 +135,7 @@ namespace {
       SDOperand To[] = { Res0, Res1 };
       return CombineTo(N, To, 2, AddTo);
     }
+    
   private:    
     
     /// SimplifyDemandedBits - Check the specified integer node value to see if
@@ -460,10 +461,13 @@ static SDOperand GetNegatedExpression(SDOperand Op, SelectionDAG &DAG,
                        GetNegatedExpression(Op.getOperand(1), DAG, Depth+1));
     
   case ISD::FP_EXTEND:
-  case ISD::FP_ROUND:
   case ISD::FSIN:
     return DAG.getNode(Op.getOpcode(), Op.getValueType(),
                        GetNegatedExpression(Op.getOperand(0), DAG, Depth+1));
+  case ISD::FP_ROUND:
+      return DAG.getNode(ISD::FP_ROUND, Op.getValueType(),
+                         GetNegatedExpression(Op.getOperand(0), DAG, Depth+1),
+                         Op.getOperand(1));
   }
 }
 
@@ -842,8 +846,9 @@ SDOperand combineSelectAndUse(SDNode *N, SDOperand Slct, SDOperand OtherOp,
            RHS.getOpcode() == ISD::Constant &&
            cast<ConstantSDNode>(RHS)->isNullValue()) {
     std::swap(LHS, RHS);
-    bool isInt = MVT::isInteger(isSlctCC ? Slct.getOperand(0).getValueType()
-                                : Slct.getOperand(0).getOperand(0).getValueType());
+    SDOperand Op0 = Slct.getOperand(0);
+    bool isInt = MVT::isInteger(isSlctCC ? Op0.getValueType()
+                                : Op0.getOperand(0).getValueType());
     CC = ISD::getSetCCInverse(CC, isInt);
     DoXform = true;
     InvCC = true;
@@ -1685,8 +1690,7 @@ SDOperand DAGCombiner::visitAND(SDNode *N) {
   if (N1C && N0.getOpcode() == ISD::LOAD) {
     LoadSDNode *LN0 = cast<LoadSDNode>(N0);
     if (LN0->getExtensionType() != ISD::SEXTLOAD &&
-        LN0->getAddressingMode() == ISD::UNINDEXED &&
-        N0.hasOneUse()) {
+        LN0->isUnindexed() && N0.hasOneUse()) {
       MVT::ValueType EVT, LoadedVT;
       if (N1C->getValue() == 255)
         EVT = MVT::i8;
@@ -3632,20 +3636,30 @@ SDOperand DAGCombiner::visitFP_TO_UINT(SDNode *N) {
 
 SDOperand DAGCombiner::visitFP_ROUND(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
+  SDOperand N1 = N->getOperand(1);
   ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
   MVT::ValueType VT = N->getValueType(0);
   
   // fold (fp_round c1fp) -> c1fp
   if (N0CFP && N0.getValueType() != MVT::ppcf128)
-    return DAG.getNode(ISD::FP_ROUND, VT, N0);
+    return DAG.getNode(ISD::FP_ROUND, VT, N0, N1);
   
   // fold (fp_round (fp_extend x)) -> x
   if (N0.getOpcode() == ISD::FP_EXTEND && VT == N0.getOperand(0).getValueType())
     return N0.getOperand(0);
   
+  // fold (fp_round (fp_round x)) -> (fp_round x)
+  if (N0.getOpcode() == ISD::FP_ROUND) {
+    // This is a value preserving truncation if both round's are.
+    bool IsTrunc = N->getConstantOperandVal(1) == 1 &&
+                   N0.Val->getConstantOperandVal(1) == 1;
+    return DAG.getNode(ISD::FP_ROUND, VT, N0.getOperand(0),
+                       DAG.getIntPtrConstant(IsTrunc));
+  }
+  
   // fold (fp_round (copysign X, Y)) -> (copysign (fp_round X), Y)
   if (N0.getOpcode() == ISD::FCOPYSIGN && N0.Val->hasOneUse()) {
-    SDOperand Tmp = DAG.getNode(ISD::FP_ROUND, VT, N0.getOperand(0));
+    SDOperand Tmp = DAG.getNode(ISD::FP_ROUND, VT, N0.getOperand(0), N1);
     AddToWorkList(Tmp.Val);
     return DAG.getNode(ISD::FCOPYSIGN, VT, Tmp, N0.getOperand(1));
   }
@@ -3675,12 +3689,22 @@ SDOperand DAGCombiner::visitFP_EXTEND(SDNode *N) {
   // 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)
     return SDOperand();
-  
+
   // fold (fp_extend c1fp) -> c1fp
   if (N0CFP && VT != MVT::ppcf128)
     return DAG.getNode(ISD::FP_EXTEND, VT, N0);
-  
-  // fold (fpext (load x)) -> (fpext (fpround (extload x)))
+
+  // Turn fp_extend(fp_round(X, 1)) -> x since the fp_round doesn't affect the
+  // value of X.
+  if (N0.getOpcode() == ISD::FP_ROUND && N0.Val->getConstantOperandVal(1) == 1){
+    SDOperand In = N0.getOperand(0);
+    if (In.getValueType() == VT) return In;
+    if (VT < In.getValueType())
+      return DAG.getNode(ISD::FP_ROUND, VT, In, N0.getOperand(1));
+    return DAG.getNode(ISD::FP_EXTEND, VT, In);
+  }
+      
+  // fold (fpext (load x)) -> (fpext (fptrunc (extload x)))
   if (ISD::isNON_EXTLoad(N0.Val) && N0.hasOneUse() &&
       (!AfterLegalize||TLI.isLoadXLegal(ISD::EXTLOAD, N0.getValueType()))) {
     LoadSDNode *LN0 = cast<LoadSDNode>(N0);
@@ -3691,7 +3715,8 @@ SDOperand DAGCombiner::visitFP_EXTEND(SDNode *N) {
                                        LN0->isVolatile(), 
                                        LN0->getAlignment());
     CombineTo(N, ExtLoad);
-    CombineTo(N0.Val, DAG.getNode(ISD::FP_ROUND, N0.getValueType(), ExtLoad),
+    CombineTo(N0.Val, DAG.getNode(ISD::FP_ROUND, N0.getValueType(), ExtLoad,
+                                  DAG.getIntPtrConstant(1)),
               ExtLoad.getValue(1));
     return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
   }
@@ -3793,7 +3818,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
   SDOperand Ptr;
   MVT::ValueType VT;
   if (LoadSDNode *LD  = dyn_cast<LoadSDNode>(N)) {
-    if (LD->getAddressingMode() != ISD::UNINDEXED)
+    if (LD->isIndexed())
       return false;
     VT = LD->getLoadedVT();
     if (!TLI.isIndexedLoadLegal(ISD::PRE_INC, VT) &&
@@ -3801,7 +3826,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
       return false;
     Ptr = LD->getBasePtr();
   } else if (StoreSDNode *ST  = dyn_cast<StoreSDNode>(N)) {
-    if (ST->getAddressingMode() != ISD::UNINDEXED)
+    if (ST->isIndexed())
       return false;
     VT = ST->getStoredVT();
     if (!TLI.isIndexedStoreLegal(ISD::PRE_INC, VT) &&
@@ -3920,7 +3945,7 @@ bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) {
   SDOperand Ptr;
   MVT::ValueType VT;
   if (LoadSDNode *LD  = dyn_cast<LoadSDNode>(N)) {
-    if (LD->getAddressingMode() != ISD::UNINDEXED)
+    if (LD->isIndexed())
       return false;
     VT = LD->getLoadedVT();
     if (!TLI.isIndexedLoadLegal(ISD::POST_INC, VT) &&
@@ -3928,7 +3953,7 @@ bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) {
       return false;
     Ptr = LD->getBasePtr();
   } else if (StoreSDNode *ST  = dyn_cast<StoreSDNode>(N)) {
-    if (ST->getAddressingMode() != ISD::UNINDEXED)
+    if (ST->isIndexed())
       return false;
     VT = ST->getStoredVT();
     if (!TLI.isIndexedStoreLegal(ISD::POST_INC, VT) &&
@@ -4055,16 +4080,54 @@ SDOperand DAGCombiner::visitLOAD(SDNode *N) {
   if (!LD->isVolatile()) {
     if (N->getValueType(1) == MVT::Other) {
       // Unindexed loads.
-      if (N->hasNUsesOfValue(0, 0))
-        return CombineTo(N, DAG.getNode(ISD::UNDEF, N->getValueType(0)), Chain);
+      if (N->hasNUsesOfValue(0, 0)) {
+        // It's not safe to use the two value CombineTo variant here. e.g.
+        // v1, chain2 = load chain1, loc
+        // v2, chain3 = load chain2, loc
+        // v3         = add v2, c
+        // Now we replace use of v1 with undef, use of chain2 with chain1.
+        // ReplaceAllUsesWith() will iterate through uses of the first load and
+        // update operands:
+        // v1, chain2 = load chain1, loc
+        // v2, chain3 = load chain1, loc
+        // v3         = add v2, c
+        // Now the second load is the same as the first load, SelectionDAG cse
+        // will ensure the use of second load is replaced with the first load.
+        // v1, chain2 = load chain1, loc
+        // v3         = add v1, c
+        // Then v1 is replaced with undef and bad things happen.
+        std::vector<SDNode*> NowDead;
+        SDOperand Undef = DAG.getNode(ISD::UNDEF, N->getValueType(0));
+        DOUT << "\nReplacing.6 "; DEBUG(N->dump(&DAG));
+        DOUT << "\nWith: "; DEBUG(Undef.Val->dump(&DAG));
+        DOUT << " and 1 other value\n";
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Undef, &NowDead);
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Chain, &NowDead);
+        removeFromWorkList(N);
+        for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
+          removeFromWorkList(NowDead[i]);
+        DAG.DeleteNode(N);
+        return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
+      }
     } else {
       // Indexed loads.
       assert(N->getValueType(2) == MVT::Other && "Malformed indexed loads?");
       if (N->hasNUsesOfValue(0, 0) && N->hasNUsesOfValue(0, 1)) {
-        SDOperand Undef0 = DAG.getNode(ISD::UNDEF, N->getValueType(0));
-        SDOperand Undef1 = DAG.getNode(ISD::UNDEF, N->getValueType(1));
-        SDOperand To[] = { Undef0, Undef1, Chain };
-        return CombineTo(N, To, 3);
+        std::vector<SDNode*> NowDead;
+        SDOperand Undef = DAG.getNode(ISD::UNDEF, N->getValueType(0));
+        DOUT << "\nReplacing.6 "; DEBUG(N->dump(&DAG));
+        DOUT << "\nWith: "; DEBUG(Undef.Val->dump(&DAG));
+        DOUT << " and 2 other values\n";
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Undef, &NowDead);
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1),
+                                    DAG.getNode(ISD::UNDEF, N->getValueType(1)),
+                                      &NowDead);
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 2), Chain, &NowDead);
+        removeFromWorkList(N);
+        for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
+          removeFromWorkList(NowDead[i]);
+        DAG.DeleteNode(N);
+        return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
       }
     }
   }
@@ -4122,6 +4185,7 @@ SDOperand DAGCombiner::visitLOAD(SDNode *N) {
   return SDOperand();
 }
 
+
 SDOperand DAGCombiner::visitSTORE(SDNode *N) {
   StoreSDNode *ST  = cast<StoreSDNode>(N);
   SDOperand Chain = ST->getChain();
@@ -4131,7 +4195,7 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) {
   // If this is a store of a bit convert, store the input value if the
   // resultant store does not need a higher alignment than the original.
   if (Value.getOpcode() == ISD::BIT_CONVERT && !ST->isTruncatingStore() &&
-      ST->getAddressingMode() == ISD::UNINDEXED) {
+      ST->isUnindexed()) {
     unsigned Align = ST->getAlignment();
     MVT::ValueType SVT = Value.getOperand(0).getValueType();
     unsigned OrigAlign = TLI.getTargetMachine().getTargetData()->
@@ -4206,12 +4270,13 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) {
       SDOperand ReplStore;
       if (ST->isTruncatingStore()) {
         ReplStore = DAG.getTruncStore(BetterChain, Value, Ptr,
-          ST->getSrcValue(), ST->getSrcValueOffset(), ST->getStoredVT(),
-          ST->isVolatile(), ST->getAlignment());
+                                      ST->getSrcValue(),ST->getSrcValueOffset(),
+                                      ST->getStoredVT(),
+                                      ST->isVolatile(), ST->getAlignment());
       } else {
         ReplStore = DAG.getStore(BetterChain, Value, Ptr,
-          ST->getSrcValue(), ST->getSrcValueOffset(),
-          ST->isVolatile(), ST->getAlignment());
+                                 ST->getSrcValue(), ST->getSrcValueOffset(),
+                                 ST->isVolatile(), ST->getAlignment());
       }
       
       // Create token to keep both nodes around.
@@ -4228,7 +4293,7 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) {
     return SDOperand(N, 0);
 
   // FIXME: is there such a thing as a truncating indexed store?
-  if (ST->isTruncatingStore() && ST->getAddressingMode() == ISD::UNINDEXED &&
+  if (ST->isTruncatingStore() && ST->isUnindexed() &&
       MVT::isInteger(Value.getValueType())) {
     // See if we can simplify the input to this truncstore with knowledge that
     // only the low bits are being used.  For example:
@@ -4250,15 +4315,28 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) {
   // If this is a load followed by a store to the same location, then the store
   // is dead/noop.
   if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Value)) {
-    if (Chain.Val == Ld && Ld->getBasePtr() == Ptr &&
-        ST->getAddressingMode() == ISD::UNINDEXED &&
-        ST->getStoredVT() == Ld->getLoadedVT() &&
-        !ST->isVolatile()) {
+    if (Ld->getBasePtr() == Ptr && ST->getStoredVT() == Ld->getLoadedVT() &&
+        ST->isUnindexed() && !ST->isVolatile() &&
+        // There can't be any side effects between the load and store, such as
+        // a call or store.
+        Chain.reachesChainWithoutSideEffects(SDOperand(Ld, 1))) {
       // The store is dead, remove it.
       return Chain;
     }
   }
   
+  // If this is an FP_ROUND or TRUNC followed by a store, fold this into a
+  // truncating store.  We can do this even if this is already a truncstore.
+  if ((Value.getOpcode() == ISD::FP_ROUND || Value.getOpcode() == ISD::TRUNCATE)
+      && TLI.isTypeLegal(Value.getOperand(0).getValueType()) &&
+      Value.Val->hasOneUse() && ST->isUnindexed() &&
+      TLI.isTruncStoreLegal(Value.getOperand(0).getValueType(),
+                            ST->getStoredVT())) {
+    return DAG.getTruncStore(Chain, Value.getOperand(0), Ptr, ST->getSrcValue(),
+                             ST->getSrcValueOffset(), ST->getStoredVT(),
+                             ST->isVolatile(), ST->getAlignment());
+  }
+  
   return SDOperand();
 }
 
@@ -4394,13 +4472,11 @@ SDOperand DAGCombiner::visitBUILD_VECTOR(SDNode *N) {
 
       // Otherwise, use InIdx + VecSize
       unsigned Idx = cast<ConstantSDNode>(Extract.getOperand(1))->getValue();
-      BuildVecIndices.push_back(DAG.getConstant(Idx+NumInScalars,
-                                                TLI.getPointerTy()));
+      BuildVecIndices.push_back(DAG.getIntPtrConstant(Idx+NumInScalars));
     }
     
     // Add count and size info.
-    MVT::ValueType BuildVecVT =
-      MVT::getVectorType(TLI.getPointerTy(), NumElts);
+    MVT::ValueType BuildVecVT = MVT::getVectorType(TLI.getPointerTy(), NumElts);
     
     // Return the new VECTOR_SHUFFLE node.
     SDOperand Ops[5];