[PATCH] Fix PR31115, wrong code with VRP and shifts

Richard Guenther richard.guenther@gmail.com
Sun Mar 11 16:36:00 GMT 2007


On 3/11/07, Richard Guenther <rguenther@suse.de> wrote:
>
> This fixes PR31115, some oversights with my last patch introducing
> support for RSHIFT_EXPR in VRP and a bad interaction with the overflow
> handling changes.  Basically the problem is that -[-INF, -1] is now
> [1, +INF(OVL)] and we now "overflow" right shifting of that even if
> right shifting (by a positive shift) never overflows.  This does I
> believe cause some optimiation regressions :/
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to mainline.

Argh.  I should read what the svn commit prints ;)  Now Ian was first, so
I re-merged and committed.  I left in the now probably unused case of
overflowing RSHIFT_EXPR in vrp_int_const_binop.  The rest still applies.

Richard.

> Richard.
>
> 2007-03-11  Richard Guenther  <rguenther@suse.de>
>
>         PR tree-optimization/31115
>         * tree-vrp.c (extract_range_from_binary_expr): Make sure
>         the shift count is positive and non-anti-range for RSHIFT_EXPR.
>         A shift count of zero is not special as with *_DIV_EXPR.
>         (vrp_int_const_binop): Handle RSHIFT_EXPR for determining overflow
>         direction.
>
>         * gcc.dg/torture/pr31115.c: New testcase.
>
> Index: tree-vrp.c
> ===================================================================
> *** tree-vrp.c  (revision 122805)
> --- tree-vrp.c  (working copy)
> *************** vrp_int_const_binop (enum tree_code code
> *** 1554,1559 ****
> --- 1554,1565 ----
>               && (sgn1 >= 0
>                   ? !is_positive_overflow_infinity (val2)
>                   : is_negative_overflow_infinity (val2)))
> +         /* We only get in here with positive shift count, so the
> +            overflow direction is the same as the sign of val1.
> +            Actually rshift does not overflow at all, but we only
> +            handle the case of shifting overflowed -INF and +INF.  */
> +         || (code == RSHIFT_EXPR
> +             && sgn1 >= 0)
>           /* For division, the only case is -INF / -1 = +INF.  */
>           || code == TRUNC_DIV_EXPR
>           || code == FLOOR_DIV_EXPR
> *************** extract_range_from_binary_expr (value_ra
> *** 1787,1792 ****
> --- 1793,1809 ----
>           return;
>         }
>
> +       /* If we have a RSHIFT_EXPR with a possibly negative shift
> +        count or an anti-range shift count drop to VR_VARYING.
> +        We currently cannot handle the overflow cases correctly.  */
> +       if (code == RSHIFT_EXPR
> +         && (vr1.type == VR_ANTI_RANGE
> +             || !vrp_expr_computes_nonnegative (op1, &sop)))
> +       {
> +         set_value_range_to_varying (vr);
> +         return;
> +       }
> +
>         /* Multiplications and divisions are a bit tricky to handle,
>          depending on the mix of signs we have in the two ranges, we
>          need to operate on different values to get the minimum and
> *************** extract_range_from_binary_expr (value_ra
> *** 1801,1807 ****
>          the new range.  */
>
>         /* Divisions by zero result in a VARYING value.  */
> !       if (code != MULT_EXPR
>           && (vr0.type == VR_ANTI_RANGE || range_includes_zero_p (&vr1)))
>         {
>           set_value_range_to_varying (vr);
> --- 1818,1825 ----
>          the new range.  */
>
>         /* Divisions by zero result in a VARYING value.  */
> !       if ((code != MULT_EXPR
> !          && code != RSHIFT_EXPR)
>           && (vr0.type == VR_ANTI_RANGE || range_includes_zero_p (&vr1)))
>         {
>           set_value_range_to_varying (vr);
> Index: testsuite/gcc.dg/torture/pr31115.c
> ===================================================================
> *** testsuite/gcc.dg/torture/pr31115.c  (revision 0)
> --- testsuite/gcc.dg/torture/pr31115.c  (revision 0)
> ***************
> *** 0 ****
> --- 1,22 ----
> + /* { dg-do run } */
> +
> + extern void exit(int);
> + extern void abort();
> + void foo (int e1)
> + {
> +   if (e1 < 0)
> +     {
> +       e1 = -e1;
> +       if (e1 >>= 4)
> +         {
> +           if (e1 >= 1 << 5)
> +             exit(0);
> +         }
> +     }
> + }
> +
> + int main()
> + {
> +   foo(-(1<<9));
> +   abort();
> + }
>



More information about the Gcc-patches mailing list