* Introduce a new SelectionDAG::getIntPtrConstant method
[oota-llvm.git] / lib / CodeGen / SelectionDAG / DAGCombiner.cpp
index e581ed3d948a3acb4473e0db2741c59eb2998870..ad176d4ff36e8a09491f3cdf50b6d6920687fd34 100644 (file)
@@ -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));
   }
 }
 
@@ -3632,12 +3636,13 @@ 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())
@@ -3645,7 +3650,7 @@ SDOperand DAGCombiner::visitFP_ROUND(SDNode *N) {
   
   // 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 +3680,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 +3706,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!
   }
@@ -4055,16 +4071,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 +4176,7 @@ SDOperand DAGCombiner::visitLOAD(SDNode *N) {
   return SDOperand();
 }
 
+
 SDOperand DAGCombiner::visitSTORE(SDNode *N) {
   StoreSDNode *ST  = cast<StoreSDNode>(N);
   SDOperand Chain = ST->getChain();
@@ -4250,10 +4305,12 @@ 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 &&
+    if (Ld->getBasePtr() == Ptr && ST->getStoredVT() == Ld->getLoadedVT() &&
         ST->getAddressingMode() == ISD::UNINDEXED &&
-        ST->getStoredVT() == Ld->getLoadedVT() &&
-        !ST->isVolatile()) {
+        !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;
     }
@@ -4394,13 +4451,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];