From 12d830346b78b8e92dc0346e710f261cc680480f Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 5 Mar 2006 05:30:57 +0000 Subject: [PATCH] Add some simple copysign folds git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26543 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 66 +++++++++++++++++++++++++++---- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 2 + 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0cf6801831f..1e05d583e83 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -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(N0); + ConstantFPSDNode *N1CFP = dyn_cast(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(); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 534015ccf93..57f10663d03 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -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 -- 2.11.0