This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Teach VRP to handle if ((unsigned_narrowing_cast) x != 0) similarly to if ((x & 0xffff) != 0) (PR tree-optimization/54810)


On Thu, Oct 4, 2012 at 6:31 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> This patch handles unsigned narrowing casts the same as
> BIT_AND_EXPR with the unsigned narrow type's max value.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux,
> ok for trunk?

Ok.

Thanks,
Richard.

> 2012-10-04  Jakub Jelinek  <jakub@redhat.com>
>
>         PR tree-optimization/54810
>         * tree-vrp.c (register_edge_assert_for_2): Handle
>         NAME = (unsigned) NAME2; if (NAME cmp CST) for
>         narrowing casts to unsigned integral type like
>         NAME = NAME2 & CST2; if (NAME cmp CST) where CST2
>         is the max value of the unsigned integral type.
>
> --- gcc/tree-vrp.c.jj   2012-09-25 14:45:48.000000000 +0200
> +++ gcc/tree-vrp.c      2012-10-04 11:43:32.334988401 +0200
> @@ -4712,6 +4712,11 @@ register_edge_assert_for_2 (tree name, e
>        tree val2 = NULL_TREE;
>        double_int mask = double_int_zero;
>        unsigned int prec = TYPE_PRECISION (TREE_TYPE (val));
> +      unsigned int nprec = prec;
> +      enum tree_code rhs_code = ERROR_MARK;
> +
> +      if (is_gimple_assign (def_stmt))
> +       rhs_code = gimple_assign_rhs_code (def_stmt);
>
>        /* Add asserts for NAME cmp CST and NAME being defined
>          as NAME = (int) NAME2.  */
> @@ -4721,7 +4726,7 @@ register_edge_assert_for_2 (tree name, e
>           && gimple_assign_cast_p (def_stmt))
>         {
>           name2 = gimple_assign_rhs1 (def_stmt);
> -         if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
> +         if (CONVERT_EXPR_CODE_P (rhs_code)
>               && INTEGRAL_TYPE_P (TREE_TYPE (name2))
>               && TYPE_UNSIGNED (TREE_TYPE (name2))
>               && prec == TYPE_PRECISION (TREE_TYPE (name2))
> @@ -4767,8 +4772,7 @@ register_edge_assert_for_2 (tree name, e
>          NAME = NAME2 >> CST2.
>
>          Extract CST2 from the right shift.  */
> -      if (is_gimple_assign (def_stmt)
> -         && gimple_assign_rhs_code (def_stmt) == RSHIFT_EXPR)
> +      if (rhs_code == RSHIFT_EXPR)
>         {
>           name2 = gimple_assign_rhs1 (def_stmt);
>           cst2 = gimple_assign_rhs2 (def_stmt);
> @@ -4840,21 +4844,37 @@ register_edge_assert_for_2 (tree name, e
>        /* Add asserts for NAME cmp CST and NAME being defined as
>          NAME = NAME2 & CST2.
>
> -        Extract CST2 from the and.  */
> +        Extract CST2 from the and.
> +
> +        Also handle
> +        NAME = (unsigned) NAME2;
> +        casts where NAME's type is unsigned and has smaller precision
> +        than NAME2's type as if it was NAME = NAME2 & MASK.  */
>        names[0] = NULL_TREE;
>        names[1] = NULL_TREE;
>        cst2 = NULL_TREE;
> -      if (is_gimple_assign (def_stmt)
> -         && gimple_assign_rhs_code (def_stmt) == BIT_AND_EXPR)
> +      if (rhs_code == BIT_AND_EXPR
> +         || (CONVERT_EXPR_CODE_P (rhs_code)
> +             && TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE
> +             && TYPE_UNSIGNED (TREE_TYPE (val))
> +             && TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def_stmt)))
> +                > prec
> +             && !retval))
>         {
>           name2 = gimple_assign_rhs1 (def_stmt);
> -         cst2 = gimple_assign_rhs2 (def_stmt);
> +         if (rhs_code == BIT_AND_EXPR)
> +           cst2 = gimple_assign_rhs2 (def_stmt);
> +         else
> +           {
> +             cst2 = TYPE_MAX_VALUE (TREE_TYPE (val));
> +             nprec = TYPE_PRECISION (TREE_TYPE (name2));
> +           }
>           if (TREE_CODE (name2) == SSA_NAME
>               && INTEGRAL_TYPE_P (TREE_TYPE (name2))
>               && TREE_CODE (cst2) == INTEGER_CST
>               && !integer_zerop (cst2)
> -             && prec <= HOST_BITS_PER_DOUBLE_INT
> -             && (prec > 1
> +             && nprec <= HOST_BITS_PER_DOUBLE_INT
> +             && (nprec > 1
>                   || TYPE_UNSIGNED (TREE_TYPE (val))))
>             {
>               gimple def_stmt2 = SSA_NAME_DEF_STMT (name2);
> @@ -4881,12 +4901,12 @@ register_edge_assert_for_2 (tree name, e
>           bool valid_p = false, valn = false, cst2n = false;
>           enum tree_code ccode = comp_code;
>
> -         valv = tree_to_double_int (val).zext (prec);
> -         cst2v = tree_to_double_int (cst2).zext (prec);
> +         valv = tree_to_double_int (val).zext (nprec);
> +         cst2v = tree_to_double_int (cst2).zext (nprec);
>           if (!TYPE_UNSIGNED (TREE_TYPE (val)))
>             {
> -             valn = valv.sext (prec).is_negative ();
> -             cst2n = cst2v.sext (prec).is_negative ();
> +             valn = valv.sext (nprec).is_negative ();
> +             cst2n = cst2v.sext (nprec).is_negative ();
>             }
>           /* If CST2 doesn't have most significant bit set,
>              but VAL is negative, we have comparison like
> @@ -4894,7 +4914,7 @@ register_edge_assert_for_2 (tree name, e
>           if (!cst2n && valn)
>             ccode = ERROR_MARK;
>           if (cst2n)
> -           sgnbit = double_int_one.llshift (prec - 1, prec).zext (prec);
> +           sgnbit = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
>           else
>             sgnbit = double_int_zero;
>           minv = valv & cst2v;
> @@ -4906,12 +4926,12 @@ register_edge_assert_for_2 (tree name, e
>                  have folded the comparison into false) and
>                  maximum unsigned value is VAL | ~CST2.  */
>               maxv = valv | ~cst2v;
> -             maxv = maxv.zext (prec);
> +             maxv = maxv.zext (nprec);
>               valid_p = true;
>               break;
>             case NE_EXPR:
>               tem = valv | ~cst2v;
> -             tem = tem.zext (prec);
> +             tem = tem.zext (nprec);
>               /* If VAL is 0, handle (X & CST2) != 0 as (X & CST2) > 0U.  */
>               if (valv.is_zero ())
>                 {
> @@ -4921,7 +4941,7 @@ register_edge_assert_for_2 (tree name, e
>                 }
>               /* If (VAL | ~CST2) is all ones, handle it as
>                  (X & CST2) < VAL.  */
> -             if (tem == double_int::mask (prec))
> +             if (tem == double_int::mask (nprec))
>                 {
>                   cst2n = false;
>                   valn = false;
> @@ -4929,8 +4949,9 @@ register_edge_assert_for_2 (tree name, e
>                   goto lt_expr;
>                 }
>               if (!cst2n
> -                 && cst2v.sext (prec).is_negative ())
> -               sgnbit = double_int_one.llshift (prec - 1, prec).zext (prec);
> +                 && cst2v.sext (nprec).is_negative ())
> +               sgnbit
> +                 = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
>               if (!sgnbit.is_zero ())
>                 {
>                   if (valv == sgnbit)
> @@ -4939,7 +4960,7 @@ register_edge_assert_for_2 (tree name, e
>                       valn = true;
>                       goto gt_expr;
>                     }
> -                 if (tem == double_int::mask (prec - 1))
> +                 if (tem == double_int::mask (nprec - 1))
>                     {
>                       cst2n = true;
>                       goto lt_expr;
> @@ -4958,22 +4979,22 @@ register_edge_assert_for_2 (tree name, e
>                 {
>                   /* If (VAL & CST2) != VAL, X & CST2 can't be equal to
>                      VAL.  */
> -                 minv = masked_increment (valv, cst2v, sgnbit, prec);
> +                 minv = masked_increment (valv, cst2v, sgnbit, nprec);
>                   if (minv == valv)
>                     break;
>                 }
> -             maxv = double_int::mask (prec - (cst2n ? 1 : 0));
> +             maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
>               valid_p = true;
>               break;
>             case GT_EXPR:
>             gt_expr:
>               /* Find out smallest MINV where MINV > VAL
>                  && (MINV & CST2) == MINV, if any.  If VAL is signed and
> -                CST2 has MSB set, compute it biased by 1 << (prec - 1).  */
> -             minv = masked_increment (valv, cst2v, sgnbit, prec);
> +                CST2 has MSB set, compute it biased by 1 << (nprec - 1).  */
> +             minv = masked_increment (valv, cst2v, sgnbit, nprec);
>               if (minv == valv)
>                 break;
> -             maxv = double_int::mask (prec - (cst2n ? 1 : 0));
> +             maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
>               valid_p = true;
>               break;
>             case LE_EXPR:
> @@ -4989,13 +5010,13 @@ register_edge_assert_for_2 (tree name, e
>                 maxv = valv;
>               else
>                 {
> -                 maxv = masked_increment (valv, cst2v, sgnbit, prec);
> +                 maxv = masked_increment (valv, cst2v, sgnbit, nprec);
>                   if (maxv == valv)
>                     break;
>                   maxv -= double_int_one;
>                 }
>               maxv |= ~cst2v;
> -             maxv = maxv.zext (prec);
> +             maxv = maxv.zext (nprec);
>               minv = sgnbit;
>               valid_p = true;
>               break;
> @@ -5017,13 +5038,13 @@ register_edge_assert_for_2 (tree name, e
>                 }
>               else
>                 {
> -                 maxv = masked_increment (valv, cst2v, sgnbit, prec);
> +                 maxv = masked_increment (valv, cst2v, sgnbit, nprec);
>                   if (maxv == valv)
>                     break;
>                 }
>               maxv -= double_int_one;
>               maxv |= ~cst2v;
> -             maxv = maxv.zext (prec);
> +             maxv = maxv.zext (nprec);
>               minv = sgnbit;
>               valid_p = true;
>               break;
> @@ -5031,7 +5052,7 @@ register_edge_assert_for_2 (tree name, e
>               break;
>             }
>           if (valid_p
> -             && (maxv - minv).zext (prec) != double_int::mask (prec))
> +             && (maxv - minv).zext (nprec) != double_int::mask (nprec))
>             {
>               tree tmp, new_val, type;
>               int i;
> @@ -5044,7 +5065,7 @@ register_edge_assert_for_2 (tree name, e
>                     type = TREE_TYPE (names[i]);
>                     if (!TYPE_UNSIGNED (type))
>                       {
> -                       type = build_nonstandard_integer_type (prec, 1);
> +                       type = build_nonstandard_integer_type (nprec, 1);
>                         tmp = build1 (NOP_EXPR, type, names[i]);
>                       }
>                     if (!minv.is_zero ())
> --- gcc/testsuite/gcc.dg/tree-ssa/vrp85.c.jj    2012-10-04 11:32:18.787781121 +0200
> +++ gcc/testsuite/gcc.dg/tree-ssa/vrp85.c       2012-10-04 11:49:18.128031124 +0200
> @@ -0,0 +1,40 @@
> +/* PR tree-optimization/54810 */
> +/* { dg-do link } */
> +/* { dg-options "-O2 -fdump-tree-vrp1" } */
> +
> +extern void link_error (void);
> +
> +#define T(n, ntype, wtype) \
> +void                           \
> +f##n (wtype s)                 \
> +{                              \
> +  if ((ntype) s == 0)          \
> +    return;                    \
> +  if (s == 0)                  \
> +    link_error ();             \
> +}
> +
> +T(1, unsigned char, unsigned char)
> +T(2, unsigned char, unsigned short)
> +T(3, unsigned char, unsigned int)
> +T(4, unsigned char, unsigned long int)
> +T(5, unsigned char, unsigned long long int)
> +T(6, unsigned short int, unsigned short int)
> +T(7, unsigned short int, unsigned int)
> +T(8, unsigned short int, unsigned long int)
> +T(9, unsigned short int, unsigned long long int)
> +T(10, unsigned int, unsigned int)
> +T(11, unsigned int, unsigned long int)
> +T(12, unsigned int, unsigned long long int)
> +T(13, unsigned long int, unsigned long int)
> +T(14, unsigned long int, unsigned long long int)
> +T(15, unsigned long long int, unsigned long long int)
> +
> +int
> +main ()
> +{
> +  return 0;
> +}
> +
> +/* { dg-final { scan-tree-dump-not "link_error" "vrp1"} } */
> +/* { dg-final { cleanup-tree-dump "vrp1" } } */
>
>         Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]