On Thu, Oct 4, 2012 at 6:31 PM, Jakub Jelinek <ja...@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 <ja...@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