aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-02-18 19:37:01 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-02-18 19:37:01 +0000
commit080ea642c0b75fe30d551afe5e3ab0ab70e78720 (patch)
tree0ee4094bf8509462d5d0eb24bc8180303c0134d1 /gcc
parente360ab394f9e67d79095b9d01fc1d68af0007bbc (diff)
downloadgcc-080ea642c0b75fe30d551afe5e3ab0ab70e78720.zip
gcc-080ea642c0b75fe30d551afe5e3ab0ab70e78720.tar.gz
gcc-080ea642c0b75fe30d551afe5e3ab0ab70e78720.tar.bz2
fold-const.c (negate_expr_p): New function to determine whether an expression can be negated cheaply.
* fold-const.c (negate_expr_p): New function to determine whether an expression can be negated cheaply. (fold) [MINUS_EXPR]: Use it to determine whether to transform -A - B into -B - A for floating point types. From-SVN: r63059
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c69
2 files changed, 67 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d791614..42b21cf4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2003-02-18 Roger Sayle <roger@eyesopen.com>
+ * fold-const.c (negate_expr_p): New function to determine whether
+ an expression can be negated cheaply.
+ (fold) [MINUS_EXPR]: Use it to determine whether to transform
+ -A - B into -B - A for floating point types.
+
+2003-02-18 Roger Sayle <roger@eyesopen.com>
+
* sbitmap.c (sbitmap_resize): New function.
* sbitmap.h (sbitmap_resize): Prototype here.
* recog.c (split_all_insns): Use sbitmap_resize.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index d6f3561..5dfa1e4 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1,6 +1,6 @@
/* Fold a constant sub-tree into a single node for C-compiler
- Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -63,6 +63,7 @@ static void encode PARAMS ((HOST_WIDE_INT *,
static void decode PARAMS ((HOST_WIDE_INT *,
unsigned HOST_WIDE_INT *,
HOST_WIDE_INT *));
+static bool negate_expr_p PARAMS ((tree));
static tree negate_expr PARAMS ((tree));
static tree split_tree PARAMS ((tree, enum tree_code, tree *, tree *,
tree *, int));
@@ -835,6 +836,55 @@ div_and_round_double (code, uns,
return overflow;
}
+/* Determine whether an expression T can be cheaply negated using
+ the function negate_expr. */
+
+static bool
+negate_expr_p (t)
+ tree t;
+{
+ unsigned HOST_WIDE_INT val;
+ unsigned int prec;
+ tree type;
+
+ if (t == 0)
+ return false;
+
+ type = TREE_TYPE (t);
+
+ STRIP_SIGN_NOPS (t);
+ switch (TREE_CODE (t))
+ {
+ case INTEGER_CST:
+ if (TREE_UNSIGNED (type))
+ return false;
+
+ /* Check that -CST will not overflow type. */
+ prec = TYPE_PRECISION (type);
+ if (prec > HOST_BITS_PER_WIDE_INT)
+ {
+ if (TREE_INT_CST_LOW (t) != 0)
+ return true;
+ prec -= HOST_BITS_PER_WIDE_INT;
+ val = TREE_INT_CST_HIGH (t);
+ }
+ else
+ val = TREE_INT_CST_LOW (t);
+ if (prec < HOST_BITS_PER_WIDE_INT)
+ val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
+ return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
+
+ case REAL_CST:
+ case NEGATE_EXPR:
+ case MINUS_EXPR:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+}
+
/* Given T, an expression, return the negation of T. Allow for T to be
null, in which case return null. */
@@ -5479,13 +5529,14 @@ fold (expr)
/* A - (-B) -> A + B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
- /* (-A) - CST -> (-CST) - A for floating point (what about ints ?) */
- if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == REAL_CST)
- return
- fold (build (MINUS_EXPR, type,
- build_real (TREE_TYPE (arg1),
- REAL_VALUE_NEGATE (TREE_REAL_CST (arg1))),
- TREE_OPERAND (arg0, 0)));
+ /* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
+ if (TREE_CODE (arg0) == NEGATE_EXPR
+ && FLOAT_TYPE_P (type)
+ && negate_expr_p (arg1)
+ && (! TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
+ && (! TREE_SIDE_EFFECTS (arg1) || TREE_CONSTANT (arg0)))
+ return fold (build (MINUS_EXPR, type, negate_expr (arg1),
+ TREE_OPERAND (arg0, 0)));
if (! FLOAT_TYPE_P (type))
{