mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
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:
parent
f2f4bb2594
commit
2944652569
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user