[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Chris Lattner
sabre at nondot.org
Mon May 14 15:05:08 PDT 2007
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();
}
More information about the llvm-commits
mailing list