Skip to content

Commit

Permalink
implement a simple fneg optimization/propagation thing. This compiles:
Browse files Browse the repository at this point in the history
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

llvm-svn: 37054
  • Loading branch information
lattner committed May 14, 2007
1 parent d1e6255 commit e49c974
Showing 1 changed file with 144 additions and 7 deletions.
151 changes: 144 additions & 7 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 &&
Expand All @@ -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();
}

Expand All @@ -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 &&
Expand All @@ -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();
}

Expand Down

0 comments on commit e49c974

Please sign in to comment.