aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2004-02-07 15:35:40 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2004-02-07 15:35:40 +0000
commitdfb36f9be274a9968048ab7137eb52a258aa7106 (patch)
tree04db5646c3835e0841ea50cc2a2ab2d6036b7d68 /gcc
parent0ea5865c17469625fcd91d2dcecf5dec6fe4ce10 (diff)
downloadgcc-dfb36f9be274a9968048ab7137eb52a258aa7106.zip
gcc-dfb36f9be274a9968048ab7137eb52a258aa7106.tar.gz
gcc-dfb36f9be274a9968048ab7137eb52a258aa7106.tar.bz2
fold-const.c (negate_expr_p, [...]): Optimize -(A+B) into either (-A)-B or (-B)-A...
* fold-const.c (negate_expr_p, negate_expr): Optimize -(A+B) into either (-A)-B or (-B)-A, if A or B is easily negated respectively. (fold) <MINUS_EXPR>: Optimize (A*C) - (B*C) -> (A-B)*C for both integer types and floating point with unsafe_math_optimizations. Add similar optimization for (A*C1) - (A*C2) -> A*(C1-C2). Optimize A - B as A + (-B), if B is easily negated. From-SVN: r77453
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/fold-const.c72
2 files changed, 68 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7b08da7..ef66edd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2004-02-07 Roger Sayle <roger@eyesopen.com>
+
+ * fold-const.c (negate_expr_p, negate_expr): Optimize -(A+B) into
+ either (-A)-B or (-B)-A, if A or B is easily negated respectively.
+ (fold) <MINUS_EXPR>: Optimize (A*C) - (B*C) -> (A-B)*C for both
+ integer types and floating point with unsafe_math_optimizations.
+ Add similar optimization for (A*C1) - (A*C2) -> A*(C1-C2).
+ Optimize A - B as A + (-B), if B is easily negated.
+
2004-02-07 Kazu Hirata <kazu@cs.umass.edu>
* c-ppoutput.c, cfganal.c, diagnostic.h, print-rtl.c,
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 264e5f0..b93665c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -878,6 +878,17 @@ negate_expr_p (tree t)
return negate_expr_p (TREE_REALPART (t))
&& negate_expr_p (TREE_IMAGPART (t));
+ case PLUS_EXPR:
+ if (FLOAT_TYPE_P (type) && !flag_unsafe_math_optimizations)
+ return false;
+ /* -(A + B) -> (-B) - A. */
+ if (negate_expr_p (TREE_OPERAND (t, 1))
+ && reorder_operands_p (TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1)))
+ return true;
+ /* -(A + B) -> (-A) - B. */
+ return negate_expr_p (TREE_OPERAND (t, 0));
+
case MINUS_EXPR:
/* We can't turn -(A-B) into B-A when we honor signed zeros. */
return (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
@@ -979,6 +990,26 @@ negate_expr (tree t)
case NEGATE_EXPR:
return convert (type, TREE_OPERAND (t, 0));
+ case PLUS_EXPR:
+ if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+ {
+ /* -(A + B) -> (-B) - A. */
+ if (negate_expr_p (TREE_OPERAND (t, 1))
+ && reorder_operands_p (TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1)))
+ return convert (type,
+ fold (build (MINUS_EXPR, TREE_TYPE (t),
+ negate_expr (TREE_OPERAND (t, 1)),
+ TREE_OPERAND (t, 0))));
+ /* -(A + B) -> (-A) - B. */
+ if (negate_expr_p (TREE_OPERAND (t, 0)))
+ return convert (type,
+ fold (build (MINUS_EXPR, TREE_TYPE (t),
+ negate_expr (TREE_OPERAND (t, 0)),
+ TREE_OPERAND (t, 1))));
+ }
+ break;
+
case MINUS_EXPR:
/* - (A - B) -> B - A */
if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
@@ -6089,19 +6120,6 @@ fold (tree expr)
if (integer_zerop (arg1))
return non_lvalue (convert (type, arg0));
- /* (A * C) - (B * C) -> (A-B) * C. Since we are most concerned
- about the case where C is a constant, just try one of the
- four possibilities. */
-
- if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0))
- return fold (build (MULT_EXPR, type,
- fold (build (MINUS_EXPR, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0))),
- TREE_OPERAND (arg0, 1)));
-
/* Fold A - (A & B) into ~B & A. */
if (!TREE_SIDE_EFFECTS (arg0)
&& TREE_CODE (arg1) == BIT_AND_EXPR)
@@ -6158,6 +6176,34 @@ fold (tree expr)
&& operand_equal_p (arg0, arg1, 0))
return convert (type, integer_zero_node);
+ /* A - B -> A + (-B) if B is easily negatable. */
+ if (!wins && negate_expr_p (arg1)
+ && (FLOAT_TYPE_P (type)
+ || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)))
+ return fold (build (PLUS_EXPR, type, arg0, negate_expr (arg1)));
+
+ if (TREE_CODE (arg0) == MULT_EXPR
+ && TREE_CODE (arg1) == MULT_EXPR
+ && (INTEGRAL_TYPE_P (type) || flag_unsafe_math_optimizations))
+ {
+ /* (A * C) - (B * C) -> (A-B) * C. */
+ if (operand_equal_p (TREE_OPERAND (arg0, 1),
+ TREE_OPERAND (arg1, 1), 0))
+ return fold (build (MULT_EXPR, type,
+ fold (build (MINUS_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0))),
+ TREE_OPERAND (arg0, 1)));
+ /* (A * C1) - (A * C2) -> A * (C1-C2). */
+ if (operand_equal_p (TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0), 0))
+ return fold (build (MULT_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ fold (build (MINUS_EXPR, type,
+ TREE_OPERAND (arg0, 1),
+ TREE_OPERAND (arg1, 1)))));
+ }
+
goto associate;
case MULT_EXPR: