aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2006-11-01 02:56:45 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2006-11-01 02:56:45 +0000
commit682d039597faffc4ec84e7a569b93e9447b3e681 (patch)
treed9a9688ea50ffdbd59bbb3b045ca29467f5f137c /gcc
parenta3a1ebb559bce23379e851067df080d9f103f55e (diff)
downloadgcc-682d039597faffc4ec84e7a569b93e9447b3e681.zip
gcc-682d039597faffc4ec84e7a569b93e9447b3e681.tar.gz
gcc-682d039597faffc4ec84e7a569b93e9447b3e681.tar.bz2
re PR middle-end/23470 (a*a (for floats) is not considered always postive (-ffast-math only))
PR middle-end/23470 * tree.h (tree_expr_nonnegative_p): Return "bool" instead of "int". * fold-const.c (tree_expr_nonnegative_p): Likewise. Consider pow(x,y) and powi(x,y) to be nonnegative if either x is nonnegative or y is an even integer. * gcc.dg/pr23470-1.c: New test case. From-SVN: r118355
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c57
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr23470-1.c12
-rw-r--r--gcc/tree.h2
5 files changed, 70 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bb44011..65b835a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2006-10-31 Roger Sayle <roger@eyesopen.com>
+
+ PR middle-end/23470
+ * tree.h (tree_expr_nonnegative_p): Return "bool" instead of "int".
+ * fold-const.c (tree_expr_nonnegative_p): Likewise. Consider
+ pow(x,y) and powi(x,y) to be nonnegative if either x is nonnegative
+ or y is an even integer.
+
2006-10-31 Eric Botcazou <ebotcazou@libertysurf.fr>
PR target/24071
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index a822abd..a718f14 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -12109,14 +12109,14 @@ multiple_of_p (tree type, tree top, tree bottom)
/* Return true if `t' is known to be non-negative. */
-int
+bool
tree_expr_nonnegative_p (tree t)
{
if (t == error_mark_node)
- return 0;
+ return false;
if (TYPE_UNSIGNED (TREE_TYPE (t)))
- return 1;
+ return true;
switch (TREE_CODE (t))
{
@@ -12129,7 +12129,7 @@ tree_expr_nonnegative_p (tree t)
/* We can't return 1 if flag_wrapv is set because
ABS_EXPR<INT_MIN> = INT_MIN. */
if (!(flag_wrapv && INTEGRAL_TYPE_P (TREE_TYPE (t))))
- return 1;
+ return true;
break;
case INTEGER_CST:
@@ -12166,7 +12166,7 @@ tree_expr_nonnegative_p (tree t)
{
/* x * x for floating point x is always non-negative. */
if (operand_equal_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1), 0))
- return 1;
+ return true;
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
&& tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
}
@@ -12184,7 +12184,7 @@ tree_expr_nonnegative_p (tree t)
return TYPE_PRECISION (inner1) + TYPE_PRECISION (inner2)
< TYPE_PRECISION (TREE_TYPE (t));
}
- return 0;
+ return false;
case BIT_AND_EXPR:
case MAX_EXPR:
@@ -12234,7 +12234,7 @@ tree_expr_nonnegative_p (tree t)
if (TREE_CODE (inner_type) == INTEGER_TYPE)
{
if (TYPE_UNSIGNED (inner_type))
- return 1;
+ return true;
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
}
}
@@ -12277,7 +12277,7 @@ tree_expr_nonnegative_p (tree t)
&& TREE_OPERAND (t, 0) == temp)
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
- return 0;
+ return false;
}
case CALL_EXPR:
@@ -12303,12 +12303,12 @@ tree_expr_nonnegative_p (tree t)
CASE_INT_FN (BUILT_IN_PARITY):
CASE_INT_FN (BUILT_IN_POPCOUNT):
/* Always true. */
- return 1;
+ return true;
CASE_FLT_FN (BUILT_IN_SQRT):
/* sqrt(-0.0) is -0.0. */
if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (t))))
- return 1;
+ return true;
return tree_expr_nonnegative_p (TREE_VALUE (arglist));
CASE_FLT_FN (BUILT_IN_ASINH):
@@ -12332,7 +12332,6 @@ tree_expr_nonnegative_p (tree t)
CASE_FLT_FN (BUILT_IN_LROUND):
CASE_FLT_FN (BUILT_IN_MODF):
CASE_FLT_FN (BUILT_IN_NEARBYINT):
- CASE_FLT_FN (BUILT_IN_POW):
CASE_FLT_FN (BUILT_IN_RINT):
CASE_FLT_FN (BUILT_IN_ROUND):
CASE_FLT_FN (BUILT_IN_SIGNBIT):
@@ -12356,6 +12355,38 @@ tree_expr_nonnegative_p (tree t)
/* True if the 2nd argument is nonnegative. */
return tree_expr_nonnegative_p (TREE_VALUE (TREE_CHAIN (arglist)));
+ CASE_FLT_FN (BUILT_IN_POWI):
+ /* True if the 1st argument is nonnegative or the second
+ argument is an even integer. */
+ if (TREE_CODE (TREE_VALUE (TREE_CHAIN (arglist))) == INTEGER_CST)
+ {
+ tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ if ((TREE_INT_CST_LOW (arg1) & 1) == 0)
+ return true;
+ }
+ return tree_expr_nonnegative_p (TREE_VALUE (arglist));
+
+ CASE_FLT_FN (BUILT_IN_POW):
+ /* True if the 1st argument is nonnegative or the second
+ argument is an even integer valued real. */
+ if (TREE_CODE (TREE_VALUE (TREE_CHAIN (arglist))) == REAL_CST)
+ {
+ REAL_VALUE_TYPE c;
+ HOST_WIDE_INT n;
+
+ c = TREE_REAL_CST (TREE_VALUE (TREE_CHAIN (arglist)));
+ n = real_to_integer (&c);
+ if ((n & 1) == 0)
+ {
+ REAL_VALUE_TYPE cint;
+ real_from_integer (&cint, VOIDmode, n,
+ n < 0 ? -1 : 0, 0);
+ if (real_identical (&c, &cint))
+ return true;
+ }
+ }
+ return tree_expr_nonnegative_p (TREE_VALUE (arglist));
+
default:
break;
}
@@ -12366,11 +12397,11 @@ tree_expr_nonnegative_p (tree t)
default:
if (truth_value_p (TREE_CODE (t)))
/* Truth values evaluate to 0 or 1, which is nonnegative. */
- return 1;
+ return true;
}
/* We don't know sign of `t', so be conservative and return false. */
- return 0;
+ return false;
}
/* Return true when T is an address and is known to be nonzero.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 12e6d5d..e5457e0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-10-31 Roger Sayle <roger@eyesopen.com>
+
+ PR middle-end/23470
+ * gcc.dg/pr23470-1.c: New test case.
+
2006-11-01 Bernhard Fischer <aldot@gcc.gnu.org>
PR fortran/29537
diff --git a/gcc/testsuite/gcc.dg/pr23470-1.c b/gcc/testsuite/gcc.dg/pr23470-1.c
new file mode 100644
index 0000000..2ddf6f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr23470-1.c
@@ -0,0 +1,12 @@
+/* PR middle-end/23470 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -fdump-tree-original" } */
+
+int f(double a, double b)
+{
+ if (((a*a) + (b*b))<0)
+ link_error();
+}
+
+/* { dg-final { scan-tree-dump-times "if \\(0\\)" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/tree.h b/gcc/tree.h
index ce9daa6..6c8133f 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3606,7 +3606,7 @@ extern HOST_WIDE_INT tree_low_cst (tree, int);
extern int tree_int_cst_msb (tree);
extern int tree_int_cst_sgn (tree);
extern int tree_int_cst_sign_bit (tree);
-extern int tree_expr_nonnegative_p (tree);
+extern bool tree_expr_nonnegative_p (tree);
extern bool may_negate_without_overflow_p (tree);
extern tree get_inner_array_type (tree);