aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c83
1 files changed, 52 insertions, 31 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index b728dddb8..de3eb2c6a 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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 ())