Commit 440d3472 by Jakub Jelinek Committed by Jakub Jelinek

re PR tree-optimization/54810 (VRP doesn't handle comparison of narrowing cast…

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
parent 5e3e4fe8
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> 2012-10-04 Jeff Law <law@redhat.com>
* PR target/50356 * PR target/50356
......
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> 2012-10-04 David Edelsohn <dje.gcc@gmail.com>
* gcc.dg/ucnid-7.c: Skip on AIX. * gcc.dg/ucnid-7.c: Skip on AIX.
......
/* 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, ...@@ -4712,6 +4712,11 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
tree val2 = NULL_TREE; tree val2 = NULL_TREE;
double_int mask = double_int_zero; double_int mask = double_int_zero;
unsigned int prec = TYPE_PRECISION (TREE_TYPE (val)); 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 /* Add asserts for NAME cmp CST and NAME being defined
as NAME = (int) NAME2. */ as NAME = (int) NAME2. */
...@@ -4721,7 +4726,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -4721,7 +4726,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
&& gimple_assign_cast_p (def_stmt)) && gimple_assign_cast_p (def_stmt))
{ {
name2 = gimple_assign_rhs1 (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)) && INTEGRAL_TYPE_P (TREE_TYPE (name2))
&& TYPE_UNSIGNED (TREE_TYPE (name2)) && TYPE_UNSIGNED (TREE_TYPE (name2))
&& prec == TYPE_PRECISION (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, ...@@ -4767,8 +4772,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
NAME = NAME2 >> CST2. NAME = NAME2 >> CST2.
Extract CST2 from the right shift. */ Extract CST2 from the right shift. */
if (is_gimple_assign (def_stmt) if (rhs_code == RSHIFT_EXPR)
&& gimple_assign_rhs_code (def_stmt) == RSHIFT_EXPR)
{ {
name2 = gimple_assign_rhs1 (def_stmt); name2 = gimple_assign_rhs1 (def_stmt);
cst2 = gimple_assign_rhs2 (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, ...@@ -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 /* Add asserts for NAME cmp CST and NAME being defined as
NAME = NAME2 & CST2. 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[0] = NULL_TREE;
names[1] = NULL_TREE; names[1] = NULL_TREE;
cst2 = NULL_TREE; cst2 = NULL_TREE;
if (is_gimple_assign (def_stmt) if (rhs_code == BIT_AND_EXPR
&& gimple_assign_rhs_code (def_stmt) == 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); 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 if (TREE_CODE (name2) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (name2)) && INTEGRAL_TYPE_P (TREE_TYPE (name2))
&& TREE_CODE (cst2) == INTEGER_CST && TREE_CODE (cst2) == INTEGER_CST
&& !integer_zerop (cst2) && !integer_zerop (cst2)
&& prec <= HOST_BITS_PER_DOUBLE_INT && nprec <= HOST_BITS_PER_DOUBLE_INT
&& (prec > 1 && (nprec > 1
|| TYPE_UNSIGNED (TREE_TYPE (val)))) || TYPE_UNSIGNED (TREE_TYPE (val))))
{ {
gimple def_stmt2 = SSA_NAME_DEF_STMT (name2); 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, ...@@ -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; bool valid_p = false, valn = false, cst2n = false;
enum tree_code ccode = comp_code; enum tree_code ccode = comp_code;
valv = tree_to_double_int (val).zext (prec); valv = tree_to_double_int (val).zext (nprec);
cst2v = tree_to_double_int (cst2).zext (prec); cst2v = tree_to_double_int (cst2).zext (nprec);
if (!TYPE_UNSIGNED (TREE_TYPE (val))) if (!TYPE_UNSIGNED (TREE_TYPE (val)))
{ {
valn = valv.sext (prec).is_negative (); valn = valv.sext (nprec).is_negative ();
cst2n = cst2v.sext (prec).is_negative (); cst2n = cst2v.sext (nprec).is_negative ();
} }
/* If CST2 doesn't have most significant bit set, /* If CST2 doesn't have most significant bit set,
but VAL is negative, we have comparison like 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, ...@@ -4894,7 +4914,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
if (!cst2n && valn) if (!cst2n && valn)
ccode = ERROR_MARK; ccode = ERROR_MARK;
if (cst2n) if (cst2n)
sgnbit = double_int_one.llshift (prec - 1, prec).zext (prec); sgnbit = double_int_one.llshift (nprec - 1, nprec).zext (nprec);
else else
sgnbit = double_int_zero; sgnbit = double_int_zero;
minv = valv & cst2v; minv = valv & cst2v;
...@@ -4906,12 +4926,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -4906,12 +4926,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
have folded the comparison into false) and have folded the comparison into false) and
maximum unsigned value is VAL | ~CST2. */ maximum unsigned value is VAL | ~CST2. */
maxv = valv | ~cst2v; maxv = valv | ~cst2v;
maxv = maxv.zext (prec); maxv = maxv.zext (nprec);
valid_p = true; valid_p = true;
break; break;
case NE_EXPR: case NE_EXPR:
tem = valv | ~cst2v; tem = valv | ~cst2v;
tem = tem.zext (prec); tem = tem.zext (nprec);
/* If VAL is 0, handle (X & CST2) != 0 as (X & CST2) > 0U. */ /* If VAL is 0, handle (X & CST2) != 0 as (X & CST2) > 0U. */
if (valv.is_zero ()) if (valv.is_zero ())
{ {
...@@ -4921,7 +4941,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -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 /* If (VAL | ~CST2) is all ones, handle it as
(X & CST2) < VAL. */ (X & CST2) < VAL. */
if (tem == double_int::mask (prec)) if (tem == double_int::mask (nprec))
{ {
cst2n = false; cst2n = false;
valn = false; valn = false;
...@@ -4929,8 +4949,9 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -4929,8 +4949,9 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
goto lt_expr; goto lt_expr;
} }
if (!cst2n if (!cst2n
&& cst2v.sext (prec).is_negative ()) && cst2v.sext (nprec).is_negative ())
sgnbit = double_int_one.llshift (prec - 1, prec).zext (prec); sgnbit
= double_int_one.llshift (nprec - 1, nprec).zext (nprec);
if (!sgnbit.is_zero ()) if (!sgnbit.is_zero ())
{ {
if (valv == sgnbit) if (valv == sgnbit)
...@@ -4939,7 +4960,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -4939,7 +4960,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
valn = true; valn = true;
goto gt_expr; goto gt_expr;
} }
if (tem == double_int::mask (prec - 1)) if (tem == double_int::mask (nprec - 1))
{ {
cst2n = true; cst2n = true;
goto lt_expr; goto lt_expr;
...@@ -4958,22 +4979,22 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -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 /* If (VAL & CST2) != VAL, X & CST2 can't be equal to
VAL. */ VAL. */
minv = masked_increment (valv, cst2v, sgnbit, prec); minv = masked_increment (valv, cst2v, sgnbit, nprec);
if (minv == valv) if (minv == valv)
break; break;
} }
maxv = double_int::mask (prec - (cst2n ? 1 : 0)); maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
valid_p = true; valid_p = true;
break; break;
case GT_EXPR: case GT_EXPR:
gt_expr: gt_expr:
/* Find out smallest MINV where MINV > VAL /* Find out smallest MINV where MINV > VAL
&& (MINV & CST2) == MINV, if any. If VAL is signed and && (MINV & CST2) == MINV, if any. If VAL is signed and
CST2 has MSB set, compute it biased by 1 << (prec - 1). */ CST2 has MSB set, compute it biased by 1 << (nprec - 1). */
minv = masked_increment (valv, cst2v, sgnbit, prec); minv = masked_increment (valv, cst2v, sgnbit, nprec);
if (minv == valv) if (minv == valv)
break; break;
maxv = double_int::mask (prec - (cst2n ? 1 : 0)); maxv = double_int::mask (nprec - (cst2n ? 1 : 0));
valid_p = true; valid_p = true;
break; break;
case LE_EXPR: case LE_EXPR:
...@@ -4989,13 +5010,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -4989,13 +5010,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
maxv = valv; maxv = valv;
else else
{ {
maxv = masked_increment (valv, cst2v, sgnbit, prec); maxv = masked_increment (valv, cst2v, sgnbit, nprec);
if (maxv == valv) if (maxv == valv)
break; break;
maxv -= double_int_one; maxv -= double_int_one;
} }
maxv |= ~cst2v; maxv |= ~cst2v;
maxv = maxv.zext (prec); maxv = maxv.zext (nprec);
minv = sgnbit; minv = sgnbit;
valid_p = true; valid_p = true;
break; break;
...@@ -5017,13 +5038,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5017,13 +5038,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
} }
else else
{ {
maxv = masked_increment (valv, cst2v, sgnbit, prec); maxv = masked_increment (valv, cst2v, sgnbit, nprec);
if (maxv == valv) if (maxv == valv)
break; break;
} }
maxv -= double_int_one; maxv -= double_int_one;
maxv |= ~cst2v; maxv |= ~cst2v;
maxv = maxv.zext (prec); maxv = maxv.zext (nprec);
minv = sgnbit; minv = sgnbit;
valid_p = true; valid_p = true;
break; break;
...@@ -5031,7 +5052,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5031,7 +5052,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
break; break;
} }
if (valid_p if (valid_p
&& (maxv - minv).zext (prec) != double_int::mask (prec)) && (maxv - minv).zext (nprec) != double_int::mask (nprec))
{ {
tree tmp, new_val, type; tree tmp, new_val, type;
int i; int i;
...@@ -5044,7 +5065,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5044,7 +5065,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
type = TREE_TYPE (names[i]); type = TREE_TYPE (names[i]);
if (!TYPE_UNSIGNED (type)) 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]); tmp = build1 (NOP_EXPR, type, names[i]);
} }
if (!minv.is_zero ()) if (!minv.is_zero ())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment