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
This commit is contained in:
Roger Sayle 2003-02-18 19:37:01 +00:00 committed by Roger Sayle
parent e360ab394f
commit 080ea642c0
2 changed files with 67 additions and 9 deletions

View file

@ -1,3 +1,10 @@
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.

View file

@ -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))
{