diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3d6aba11fca3..8aec528dbe91 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2005-01-15 Jakub Jelinek + + PR tree-optimization/19060 + * tree-ssa-dom.c (extract_range_from_cond) : + Return 0 if op1 <= TYPE_MIN_VALUE () resp. op1 >= TYPE_MAX_VALUE (). + (simplify_cond_and_lookup_avail_expr): Add assert for dummy == 0 + and handle extract_range_from_cond returning false. + * fold-const.c (fold): Optimize comparisons with min/max even for + width > HOST_BITS_PER_WIDE_INT. + 2005-01-15 Ralf Corsepius * config/mips/rtems.h (MIPS_DEFAULT_GVALUE): Set to 0. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 7ccd3a895a82..24bd28bb6b96 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8439,28 +8439,57 @@ fold (tree expr) if (TREE_CODE (arg1) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg1) - && width <= HOST_BITS_PER_WIDE_INT + && width <= 2 * HOST_BITS_PER_WIDE_INT && (INTEGRAL_TYPE_P (TREE_TYPE (arg1)) || POINTER_TYPE_P (TREE_TYPE (arg1)))) { - unsigned HOST_WIDE_INT signed_max; - unsigned HOST_WIDE_INT max, min; + HOST_WIDE_INT signed_max_hi; + unsigned HOST_WIDE_INT signed_max_lo; + unsigned HOST_WIDE_INT max_hi, max_lo, min_hi, min_lo; - signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1; - - if (TYPE_UNSIGNED (TREE_TYPE (arg1))) + if (width <= HOST_BITS_PER_WIDE_INT) { - max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1; - min = 0; + signed_max_lo = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) + - 1; + signed_max_hi = 0; + max_hi = 0; + + if (TYPE_UNSIGNED (TREE_TYPE (arg1))) + { + max_lo = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1; + min_lo = 0; + min_hi = 0; + } + else + { + max_lo = signed_max_lo; + min_lo = ((unsigned HOST_WIDE_INT) -1 << (width - 1)); + min_hi = -1; + } } else { - max = signed_max; - min = ((unsigned HOST_WIDE_INT) -1 << (width - 1)); + width -= HOST_BITS_PER_WIDE_INT; + signed_max_lo = -1; + signed_max_hi = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) + - 1; + max_lo = -1; + min_lo = 0; + + if (TYPE_UNSIGNED (TREE_TYPE (arg1))) + { + max_hi = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1; + min_hi = 0; + } + else + { + max_hi = signed_max_hi; + min_hi = ((unsigned HOST_WIDE_INT) -1 << (width - 1)); + } } - if (TREE_INT_CST_HIGH (arg1) == 0 - && TREE_INT_CST_LOW (arg1) == max) + if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) == max_hi + && TREE_INT_CST_LOW (arg1) == max_lo) switch (code) { case GT_EXPR: @@ -8481,8 +8510,9 @@ fold (tree expr) default: break; } - else if (TREE_INT_CST_HIGH (arg1) == 0 - && TREE_INT_CST_LOW (arg1) == max - 1) + else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) + == max_hi + && TREE_INT_CST_LOW (arg1) == max_lo - 1) switch (code) { case GT_EXPR: @@ -8494,8 +8524,9 @@ fold (tree expr) default: break; } - else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0) - && TREE_INT_CST_LOW (arg1) == min) + else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) + == min_hi + && TREE_INT_CST_LOW (arg1) == min_lo) switch (code) { case LT_EXPR: @@ -8513,8 +8544,9 @@ fold (tree expr) default: break; } - else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0) - && TREE_INT_CST_LOW (arg1) == min + 1) + else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) + == min_hi + && TREE_INT_CST_LOW (arg1) == min_lo + 1) switch (code) { case GE_EXPR: @@ -8528,8 +8560,8 @@ fold (tree expr) } else if (!in_gimple_form - && TREE_INT_CST_HIGH (arg1) == 0 - && TREE_INT_CST_LOW (arg1) == signed_max + && TREE_INT_CST_HIGH (arg1) == signed_max_hi + && TREE_INT_CST_LOW (arg1) == signed_max_lo && TYPE_UNSIGNED (TREE_TYPE (arg1)) /* signed_type does not work on pointer types. */ && INTEGRAL_TYPE_P (TREE_TYPE (arg1))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ba010eb95874..0e05c9e83e2a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-01-15 Jakub Jelinek + + PR tree-optimization/19060 + * gcc.c-torture/execute/20050104-1.c: New test. + 2005-01-15 Bud Davis PR fortran/18983 diff --git a/gcc/testsuite/gcc.c-torture/execute/20050104-1.c b/gcc/testsuite/gcc.c-torture/execute/20050104-1.c new file mode 100644 index 000000000000..6083e9c0686f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20050104-1.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/19060 */ + +void abort (void); + +static +long long min () +{ + return -__LONG_LONG_MAX__ - 1; +} + +void +foo (long long j) +{ + if (j > 10 || j < min ()) + abort (); +} + +int +main (void) +{ + foo (10); + return 0; +} diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 67446b1432f3..36cac29b3ded 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -1,5 +1,5 @@ /* SSA Dominator optimizations for trees - Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Diego Novillo This file is part of GCC. @@ -2088,10 +2088,18 @@ simplify_cond_and_lookup_avail_expr (tree stmt, tree tmp_high, tmp_low; int dummy; - /* The last element has not been processed. Process it now. */ - extract_range_from_cond (element->cond, &tmp_high, - &tmp_low, &dummy); - + /* The last element has not been processed. Process it now. + record_range should ensure for cond inverted is not set. + This call can only fail if cond is x < min or x > max, + which fold should have optimized into false. + If that doesn't happen, just pretend all values are + in the range. */ + if (! extract_range_from_cond (element->cond, &tmp_high, + &tmp_low, &dummy)) + gcc_unreachable (); + else + gcc_assert (dummy == 0); + /* If this is the only element, then no merging is necessary, the high/low values from extract_range_from_cond are all we need. */ @@ -3204,8 +3212,10 @@ extract_range_from_cond (tree cond, tree *hi_p, tree *lo_p, int *inverted_p) break; case GT_EXPR: - low = int_const_binop (PLUS_EXPR, op1, integer_one_node, 1); high = TYPE_MAX_VALUE (type); + if (!tree_int_cst_lt (op1, high)) + return 0; + low = int_const_binop (PLUS_EXPR, op1, integer_one_node, 1); inverted = 0; break; @@ -3216,8 +3226,10 @@ extract_range_from_cond (tree cond, tree *hi_p, tree *lo_p, int *inverted_p) break; case LT_EXPR: - high = int_const_binop (MINUS_EXPR, op1, integer_one_node, 1); low = TYPE_MIN_VALUE (type); + if (!tree_int_cst_equal (low, op1)) + return 0; + high = int_const_binop (MINUS_EXPR, op1, integer_one_node, 1); inverted = 0; break;