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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37054 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2007-05-14 22:04:50 +00:00
parent f2f4bb2594
commit 2944652569

View File

@ -344,9 +344,114 @@ CombineTo(SDNode *N, SDOperand Res0, SDOperand Res1) {
}
//===----------------------------------------------------------------------===//
// 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 @@ SDOperand DAGCombiner::ReassociateOps(unsigned Opc, SDOperand N0, SDOperand N1){
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 @@ SDOperand DAGCombiner::visitFADD(SDNode *N) {
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 @@ SDOperand DAGCombiner::visitFSUB(SDNode *N) {
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 @@ SDOperand DAGCombiner::visitFMUL(SDNode *N) {
// 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 @@ SDOperand DAGCombiner::visitFDIV(SDNode *N) {
// 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();
}