On Tue, Sep 25, 2012 at 1:23 PM, Jakub Jelinek <ja...@redhat.com> wrote:
> Hi!
>
> This patch fixes two spots where signed 1-bit precision isn't handled
> properly in VRP.  With that type, build_int_cst (TREE_TYPE (min), 1)
> will overflow and thus adding it to something or subtracting leads to
> ICEs or bad code.  In the first spot min is different from max, which
> for 1-bit precision implies either all values, or none (but we don't have
> empty ranges and fallback to varying for those anyway).

emty ranges are turned into VR_UNDEFINED in intersect_range for example
(but not consistently so I see, not in set_and_canonicalize_value_range
at least).

> In the second case we can optimize if the anti range is singleton, then
> the corresponding range is singleton too (the other value).
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.

Thanks,
Richard.

> 2012-09-25  Jakub Jelinek  <ja...@redhat.com>
>
>         PR tree-optimization/54676
>         * tree-vrp.c (set_and_canonicalize_value_range): Handle
>         one bit precision properly.
>
>         * gcc.dg/pr54676.c: New test.
>
> --- gcc/tree-vrp.c.jj   2012-09-17 11:13:12.000000000 +0200
> +++ gcc/tree-vrp.c      2012-09-24 10:06:10.814376659 +0200
> @@ -501,8 +501,19 @@ set_and_canonicalize_value_range (value_
>       to adjust them.  */
>    if (tree_int_cst_lt (max, min))
>      {
> -      tree one = build_int_cst (TREE_TYPE (min), 1);
> -      tree tmp = int_const_binop (PLUS_EXPR, max, one);
> +      tree one, tmp;
> +
> +      /* For one bit precision if max < min, then the swapped
> +        range covers all values, so for VR_RANGE it is varying and
> +        for VR_ANTI_RANGE empty range, so drop to varying as well.  */
> +      if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
> +       {
> +         set_value_range_to_varying (vr);
> +         return;
> +       }
> +
> +      one = build_int_cst (TREE_TYPE (min), 1);
> +      tmp = int_const_binop (PLUS_EXPR, max, one);
>        max = int_const_binop (MINUS_EXPR, min, one);
>        min = tmp;
>
> @@ -531,6 +542,24 @@ set_and_canonicalize_value_range (value_
>           set_value_range_to_varying (vr);
>           return;
>         }
> +      else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
> +              && !TYPE_UNSIGNED (TREE_TYPE (min))
> +              && (is_min || is_max))
> +       {
> +         /* For signed 1-bit precision, one is not in-range and
> +            thus adding/subtracting it would result in overflows.  */
> +         if (operand_equal_p (min, max, 0))
> +           {
> +             min = max = is_min ? vrp_val_max (TREE_TYPE (min))
> +                                : vrp_val_min (TREE_TYPE (min));
> +             t = VR_RANGE;
> +           }
> +         else
> +           {
> +             set_value_range_to_varying (vr);
> +             return;
> +           }
> +       }
>        else if (is_min
>                /* As a special exception preserve non-null ranges.  */
>                && !(TYPE_UNSIGNED (TREE_TYPE (min))
> --- gcc/testsuite/gcc.dg/pr54676.c.jj   2012-09-24 10:52:48.911691835 +0200
> +++ gcc/testsuite/gcc.dg/pr54676.c      2012-09-24 10:52:30.000000000 +0200
> @@ -0,0 +1,23 @@
> +/* PR tree-optimization/54676 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -fno-tree-ccp -fno-tree-copy-prop -fno-tree-fre 
> -ftree-vrp" } */
> +
> +struct S
> +{
> +  int s:1;
> +};
> +
> +struct S bar (void);
> +
> +int a;
> +
> +void
> +foo (int x)
> +{
> +  struct S s = bar ();
> +  while (!a)
> +    {
> +      int l = 94967295;
> +      a = x || (s.s &= l);
> +    }
> +}
>
>         Jakub

Reply via email to