Add some simple copysign folds
authorChris Lattner <sabre@nondot.org>
Sun, 5 Mar 2006 05:30:57 +0000 (05:30 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 5 Mar 2006 05:30:57 +0000 (05:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26543 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp

index 0cf6801831f6cf080b1048ecf8ff41d825a61aca..1e05d583e8374ef3fa3b61b1a2731e01da2ca1cc 100644 (file)
@@ -195,6 +195,7 @@ namespace {
     SDOperand visitFMUL(SDNode *N);
     SDOperand visitFDIV(SDNode *N);
     SDOperand visitFREM(SDNode *N);
+    SDOperand visitFCOPYSIGN(SDNode *N);
     SDOperand visitSINT_TO_FP(SDNode *N);
     SDOperand visitUINT_TO_FP(SDNode *N);
     SDOperand visitFP_TO_SINT(SDNode *N);
@@ -627,6 +628,7 @@ SDOperand DAGCombiner::visit(SDNode *N) {
   case ISD::FMUL:               return visitFMUL(N);
   case ISD::FDIV:               return visitFDIV(N);
   case ISD::FREM:               return visitFREM(N);
+  case ISD::FCOPYSIGN:          return visitFCOPYSIGN(N);
   case ISD::SINT_TO_FP:         return visitSINT_TO_FP(N);
   case ISD::UINT_TO_FP:         return visitUINT_TO_FP(N);
   case ISD::FP_TO_SINT:         return visitFP_TO_SINT(N);
@@ -1999,6 +2001,54 @@ SDOperand DAGCombiner::visitFREM(SDNode *N) {
   return SDOperand();
 }
 
+SDOperand DAGCombiner::visitFCOPYSIGN(SDNode *N) {
+  SDOperand N0 = N->getOperand(0);
+  SDOperand N1 = N->getOperand(1);
+  ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
+  ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
+  MVT::ValueType VT = N->getValueType(0);
+
+  if (N0CFP && N1CFP)  // Constant fold
+    return DAG.getNode(ISD::FCOPYSIGN, VT, N0, N1);
+  
+  if (N1CFP) {
+    // copysign(x, c1) -> fabs(x)       iff ispos(c1)
+    // copysign(x, c1) -> fneg(fabs(x)) iff isneg(c1)
+    union {
+      double d;
+      int64_t i;
+    } u;
+    u.d = N1CFP->getValue();
+    if (u.i >= 0)
+      return DAG.getNode(ISD::FABS, VT, N0);
+    else
+      return DAG.getNode(ISD::FNEG, VT, DAG.getNode(ISD::FABS, VT, N0));
+  }
+  
+  // copysign(fabs(x), y) -> copysign(x, y)
+  // copysign(fneg(x), y) -> copysign(x, y)
+  // copysign(copysign(x,z), y) -> copysign(x, y)
+  if (N0.getOpcode() == ISD::FABS || N0.getOpcode() == ISD::FNEG ||
+      N0.getOpcode() == ISD::FCOPYSIGN)
+    return DAG.getNode(ISD::FCOPYSIGN, VT, N0.getOperand(0), N1);
+
+  // copysign(x, abs(y)) -> abs(x)
+  if (N1.getOpcode() == ISD::FABS)
+    return DAG.getNode(ISD::FABS, VT, N0);
+  
+  // copysign(x, copysign(y,z)) -> copysign(x, z)
+  if (N1.getOpcode() == ISD::FCOPYSIGN)
+    return DAG.getNode(ISD::FCOPYSIGN, VT, N0, N1.getOperand(1));
+  
+  // copysign(x, fp_extend(y)) -> copysign(x, y)
+  // copysign(x, fp_round(y)) -> copysign(x, y)
+  if (N1.getOpcode() == ISD::FP_EXTEND || N1.getOpcode() == ISD::FP_ROUND)
+    return DAG.getNode(ISD::FCOPYSIGN, VT, N0, N1.getOperand(0));
+  
+  return SDOperand();
+}
+
+
 
 SDOperand DAGCombiner::visitSINT_TO_FP(SDNode *N) {
   SDOperand N0 = N->getOperand(0);
@@ -2089,11 +2139,11 @@ SDOperand DAGCombiner::visitFNEG(SDNode *N) {
   if (N0CFP)
     return DAG.getNode(ISD::FNEG, VT, N0);
   // fold (fneg (sub x, y)) -> (sub y, x)
-  if (N->getOperand(0).getOpcode() == ISD::SUB)
-    return DAG.getNode(ISD::SUB, VT, N->getOperand(1), N->getOperand(0));
+  if (N0.getOpcode() == ISD::SUB)
+    return DAG.getNode(ISD::SUB, VT, N0.getOperand(1), N0.getOperand(0));
   // fold (fneg (fneg x)) -> x
-  if (N->getOperand(0).getOpcode() == ISD::FNEG)
-    return N->getOperand(0).getOperand(0);
+  if (N0.getOpcode() == ISD::FNEG)
+    return N0.getOperand(0);
   return SDOperand();
 }
 
@@ -2106,11 +2156,13 @@ SDOperand DAGCombiner::visitFABS(SDNode *N) {
   if (N0CFP)
     return DAG.getNode(ISD::FABS, VT, N0);
   // fold (fabs (fabs x)) -> (fabs x)
-  if (N->getOperand(0).getOpcode() == ISD::FABS)
+  if (N0.getOpcode() == ISD::FABS)
     return N->getOperand(0);
   // fold (fabs (fneg x)) -> (fabs x)
-  if (N->getOperand(0).getOpcode() == ISD::FNEG)
-    return DAG.getNode(ISD::FABS, VT, N->getOperand(0).getOperand(0));
+  // fold (fabs (fcopysign x, y)) -> (fabs x)
+  if (N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FCOPYSIGN)
+    return DAG.getNode(ISD::FABS, VT, N0.getOperand(0));
+  
   return SDOperand();
 }
 
index 534015ccf930b4e4172676a2a8809ad03e0d2b9f..57f10663d03fe7414e600658d137d1c51850c262 100644 (file)
@@ -1250,6 +1250,8 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
       case ISD::FREM :
         if (C2) return getConstantFP(fmod(C1, C2), VT);
         break;
+      case ISD::FCOPYSIGN:
+        return getConstantFP(copysign(C1, C2), VT);
       default: break;
       }
     } else {      // Cannonicalize constant to RHS if commutative