From cd29ee4b5a1b281f08bdbf32878efed5285aca6d Mon Sep 17 00:00:00 2001 From: sayle Date: Wed, 1 Nov 2006 02:56:45 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@118355 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 8 ++++++ gcc/fold-const.c | 57 +++++++++++++++++++++++++++++++--------- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/pr23470-1.c | 12 +++++++++ gcc/tree.h | 2 +- 5 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr23470-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bb44011e05c..65b835a337c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2006-10-31 Roger Sayle + + 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 PR target/24071 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a822abdce90..a718f1414df 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. */ 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 12e6d5d58a0..e5457e0eff2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-10-31 Roger Sayle + + PR middle-end/23470 + * gcc.dg/pr23470-1.c: New test case. + 2006-11-01 Bernhard Fischer 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 00000000000..2ddf6f2f22f --- /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 ce9daa64705..6c8133f6186 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); -- 2.11.0