Changes in directory llvm/lib/CodeGen/SelectionDAG:
DAGCombiner.cpp updated: 1.302 -> 1.303 --- Log message: implement a simple fneg optimization/propagation thing. This compiles: CodeGen/PowerPC/fneg.ll into: _t4: fmul f0, f3, f4 fmadd f1, f1, f2, f0 blr instead of: _t4: fneg f0, f3 fmul f0, f0, f4 fmsub f1, f1, f2, f0 blr --- Diffs of the changes: (+144 -7) DAGCombiner.cpp | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 144 insertions(+), 7 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.302 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.303 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.302 Wed May 9 16:49:47 2007 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon May 14 17:04:50 2007 @@ -344,9 +344,114 @@ } +//===----------------------------------------------------------------------===// +// Helper Functions +//===----------------------------------------------------------------------===// +/// isNegatibleForFree - Return 1 if we can compute the negated form of the +/// specified expression for the same cost as the expression itself, or 2 if we +/// can compute the negated form more cheaply than the expression itself. +static char isNegatibleForFree(SDOperand Op) { + // fneg is removable even if it has multiple uses. + if (Op.getOpcode() == ISD::FNEG) return 2; + + // Don't allow anything with multiple uses. + if (!Op.hasOneUse()) return 0; + + switch (Op.getOpcode()) { + default: return false; + case ISD::ConstantFP: + return 1; + case ISD::FADD: + // FIXME: determine better conditions for this xform. + if (!UnsafeFPMath) return 0; + + // -(A+B) -> -A - B + if (char V = isNegatibleForFree(Op.getOperand(0))) + return V; + // -(A+B) -> -B - A + return isNegatibleForFree(Op.getOperand(1)); + case ISD::FSUB: + // We can't turn -(A-B) into B-A when we honor signed zeros. + if (!UnsafeFPMath) return 0; + + // -(A-B) -> B-A + return 1; + + case ISD::FMUL: + case ISD::FDIV: + if (HonorSignDependentRoundingFPMath()) return 0; + + // -(X*Y) -> (-X * Y) or (X*-Y) + if (char V = isNegatibleForFree(Op.getOperand(0))) + return V; + + return isNegatibleForFree(Op.getOperand(1)); + + case ISD::FP_EXTEND: + case ISD::FP_ROUND: + case ISD::FSIN: + return isNegatibleForFree(Op.getOperand(0)); + } +} -//===----------------------------------------------------------------------===// +/// GetNegatedExpression - If isNegatibleForFree returns true, this function +/// returns the newly negated expression. +static SDOperand GetNegatedExpression(SDOperand Op, SelectionDAG &DAG) { + // fneg is removable even if it has multiple uses. + if (Op.getOpcode() == ISD::FNEG) return Op.getOperand(0); + + // Don't allow anything with multiple uses. + assert(Op.hasOneUse() && "Unknown reuse!"); + + switch (Op.getOpcode()) { + default: assert(0 && "Unknown code"); + case ISD::ConstantFP: + return DAG.getConstantFP(-cast<ConstantFPSDNode>(Op)->getValue(), + Op.getValueType()); + case ISD::FADD: + // FIXME: determine better conditions for this xform. + assert(UnsafeFPMath); + + // -(A+B) -> -A - B + if (isNegatibleForFree(Op.getOperand(0))) + return DAG.getNode(ISD::FSUB, Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG), + Op.getOperand(1)); + // -(A+B) -> -B - A + return DAG.getNode(ISD::FSUB, Op.getValueType(), + GetNegatedExpression(Op.getOperand(1), DAG), + Op.getOperand(0)); + case ISD::FSUB: + // We can't turn -(A-B) into B-A when we honor signed zeros. + assert(UnsafeFPMath); + + // -(A-B) -> B-A + return DAG.getNode(ISD::FSUB, Op.getValueType(), Op.getOperand(1), + Op.getOperand(0)); + + case ISD::FMUL: + case ISD::FDIV: + assert(!HonorSignDependentRoundingFPMath()); + + // -(X*Y) -> -X * Y + if (isNegatibleForFree(Op.getOperand(0))) + return DAG.getNode(Op.getOpcode(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG), + Op.getOperand(1)); + + // -(X*Y) -> X * -Y + return DAG.getNode(Op.getOpcode(), Op.getValueType(), + Op.getOperand(0), + GetNegatedExpression(Op.getOperand(1), DAG)); + + case ISD::FP_EXTEND: + case ISD::FP_ROUND: + case ISD::FSIN: + return DAG.getNode(Op.getOpcode(), Op.getValueType(), + GetNegatedExpression(Op, DAG)); + } +} // isSetCCEquivalent - Return true if this node is a setcc, or is a select_cc @@ -416,6 +521,10 @@ return SDOperand(); } +//===----------------------------------------------------------------------===// +// Main DAG Combiner implementation +//===----------------------------------------------------------------------===// + void DAGCombiner::Run(bool RunningAfterLegalize) { // set the instance variable, so that the various visit routines may use it. AfterLegalize = RunningAfterLegalize; @@ -2743,11 +2852,11 @@ if (N0CFP && !N1CFP) return DAG.getNode(ISD::FADD, VT, N1, N0); // fold (A + (-B)) -> A-B - if (N1.getOpcode() == ISD::FNEG) - return DAG.getNode(ISD::FSUB, VT, N0, N1.getOperand(0)); + if (isNegatibleForFree(N1) == 2) + return DAG.getNode(ISD::FSUB, VT, N0, GetNegatedExpression(N1, DAG)); // fold ((-A) + B) -> B-A - if (N0.getOpcode() == ISD::FNEG) - return DAG.getNode(ISD::FSUB, VT, N1, N0.getOperand(0)); + if (isNegatibleForFree(N0) == 2) + return DAG.getNode(ISD::FSUB, VT, N1, GetNegatedExpression(N0, DAG)); // If allowed, fold (fadd (fadd x, c1), c2) -> (fadd x, (fadd c1, c2)) if (UnsafeFPMath && N1CFP && N0.getOpcode() == ISD::FADD && @@ -2769,8 +2878,9 @@ if (N0CFP && N1CFP) return DAG.getNode(ISD::FSUB, VT, N0, N1); // fold (A-(-B)) -> A+B - if (N1.getOpcode() == ISD::FNEG) - return DAG.getNode(ISD::FADD, VT, N0, N1.getOperand(0)); + if (isNegatibleForFree(N1)) + return DAG.getNode(ISD::FADD, VT, N0, GetNegatedExpression(N1, DAG)); + return SDOperand(); } @@ -2790,6 +2900,20 @@ // fold (fmul X, 2.0) -> (fadd X, X) if (N1CFP && N1CFP->isExactlyValue(+2.0)) return DAG.getNode(ISD::FADD, VT, N0, N0); + // fold (fmul X, -1.0) -> (fneg X) + if (N1CFP && N1CFP->isExactlyValue(-1.0)) + return DAG.getNode(ISD::FNEG, VT, N0); + + // -X * -Y -> X*Y + if (char LHSNeg = isNegatibleForFree(N0)) { + if (char RHSNeg = isNegatibleForFree(N1)) { + // Both can be negated for free, check to see if at least one is cheaper + // negated. + if (LHSNeg == 2 || RHSNeg == 2) + return DAG.getNode(ISD::FMUL, VT, GetNegatedExpression(N0, DAG), + GetNegatedExpression(N1, DAG)); + } + } // If allowed, fold (fmul (fmul x, c1), c2) -> (fmul x, (fmul c1, c2)) if (UnsafeFPMath && N1CFP && N0.getOpcode() == ISD::FMUL && @@ -2810,6 +2934,19 @@ // fold (fdiv c1, c2) -> c1/c2 if (N0CFP && N1CFP) return DAG.getNode(ISD::FDIV, VT, N0, N1); + + + // -X / -Y -> X*Y + if (char LHSNeg = isNegatibleForFree(N0)) { + if (char RHSNeg = isNegatibleForFree(N1)) { + // Both can be negated for free, check to see if at least one is cheaper + // negated. + if (LHSNeg == 2 || RHSNeg == 2) + return DAG.getNode(ISD::FDIV, VT, GetNegatedExpression(N0, DAG), + GetNegatedExpression(N1, DAG)); + } + } + return SDOperand(); } _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits