re PR tree-optimization/54810 (VRP doesn't handle comparison of narrowing cast like comparison of BIT_AND_EXPR)
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.dg/tree-ssa/vrp85.c: New test. From-SVN: r192115
This commit is contained in:
parent
5e3e4fe874
commit
440d347233
4 changed files with 106 additions and 31 deletions
|
@ -1,3 +1,12 @@
|
|||
2012-10-05 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.
|
||||
|
||||
2012-10-04 Jeff Law <law@redhat.com>
|
||||
|
||||
* PR target/50356
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2012-10-05 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/54810
|
||||
* gcc.dg/tree-ssa/vrp85.c: New test.
|
||||
|
||||
2012-10-04 David Edelsohn <dje.gcc@gmail.com>
|
||||
|
||||
* gcc.dg/ucnid-7.c: Skip on AIX.
|
||||
|
|
40
gcc/testsuite/gcc.dg/tree-ssa/vrp85.c
Normal file
40
gcc/testsuite/gcc.dg/tree-ssa/vrp85.c
Normal file
|
@ -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" } } */
|
|
@ -4712,6 +4712,11 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
|
|||
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, edge e, gimple_stmt_iterator bsi,
|
|||
&& 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, edge e, gimple_stmt_iterator bsi,
|
|||
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, edge e, gimple_stmt_iterator bsi,
|
|||
/* 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, edge e, gimple_stmt_iterator bsi,
|
|||
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, edge e, gimple_stmt_iterator bsi,
|
|||
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, edge e, gimple_stmt_iterator bsi,
|
|||
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, edge e, gimple_stmt_iterator bsi,
|
|||
}
|
||||
/* 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, edge e, gimple_stmt_iterator bsi,
|
|||
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, edge e, gimple_stmt_iterator bsi,
|
|||
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, edge e, gimple_stmt_iterator bsi,
|
|||
{
|
||||
/* 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, edge e, gimple_stmt_iterator bsi,
|
|||
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, edge e, gimple_stmt_iterator bsi,
|
|||
}
|
||||
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, edge e, gimple_stmt_iterator bsi,
|
|||
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, edge e, gimple_stmt_iterator bsi,
|
|||
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 ())
|
||||
|
|
Loading…
Add table
Reference in a new issue