Commit ebbd90d8 by Jeff Law Committed by Jeff Law

tree-vrp.c (range_fits_type_p): Move to earlier point in file.

	* tree-vrp.c (range_fits_type_p): Move to earlier point in file.
        (simplify_cond_using_ranges): Generalize code to simplify
        COND_EXPRs where one argument is a constant and the other
        is an SSA_NAME created by an integral type conversion.

	* gcc.dg/tree-ssa/vrp88.c: New test.

From-SVN: r198413
parent 8b9b57eb
2013-04-26 Jeff Law <law@redhat.com>
* tree-vrp.c (range_fits_type_p): Move to earlier point in file.
(simplify_cond_using_ranges): Generalize code to simplify
COND_EXPRs where one argument is a constant and the other
is an SSA_NAME created by an integral type conversion.
2013-04-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com> 2013-04-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/arm/arm.md (store_minmaxsi): Use only when * config/arm/arm.md (store_minmaxsi): Use only when
......
2013-04-26 Jeff Law <law@redhat.com>
* gcc.dg/tree-ssa/vrp88.c: New test.
2013-04-29 Christian Bruel <christian.bruel@st.com> 2013-04-29 Christian Bruel <christian.bruel@st.com>
PR target/57108 PR target/57108
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
typedef const struct bitmap_head_def *const_bitmap;
typedef unsigned long BITMAP_WORD;
typedef struct bitmap_element_def {
struct bitmap_element_def *next;
BITMAP_WORD bits[((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u))];
} bitmap_element;
typedef struct bitmap_head_def {
bitmap_element *first;
} bitmap_head;
unsigned char
bitmap_single_bit_set_p (const_bitmap a)
{
unsigned long count = 0;
const bitmap_element *elt;
unsigned ix;
if ((!(a)->first))
return 0;
elt = a->first;
if (elt->next != ((void *)0))
return 0;
for (ix = 0; ix != ((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u)); ix++)
{
count += __builtin_popcountl (elt->bits[ix]);
if (count > 1)
return 0;
}
return count == 1;
}
/* Verify that VRP simplified an "if" statement. */
/* { dg-final { scan-tree-dump "Folded into: if.*" "vrp1"} } */
/* { dg-final { cleanup-tree-dump "vrp1" } } */
...@@ -8509,6 +8509,57 @@ test_for_singularity (enum tree_code cond_code, tree op0, ...@@ -8509,6 +8509,57 @@ test_for_singularity (enum tree_code cond_code, tree op0,
return NULL; return NULL;
} }
/* Return whether the value range *VR fits in an integer type specified
by PRECISION and UNSIGNED_P. */
static bool
range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
{
tree src_type;
unsigned src_precision;
double_int tem;
/* We can only handle integral and pointer types. */
src_type = TREE_TYPE (vr->min);
if (!INTEGRAL_TYPE_P (src_type)
&& !POINTER_TYPE_P (src_type))
return false;
/* An extension is fine unless VR is signed and unsigned_p,
and so is an identity transform. */
src_precision = TYPE_PRECISION (TREE_TYPE (vr->min));
if ((src_precision < precision
&& !(unsigned_p && !TYPE_UNSIGNED (src_type)))
|| (src_precision == precision
&& TYPE_UNSIGNED (src_type) == unsigned_p))
return true;
/* Now we can only handle ranges with constant bounds. */
if (vr->type != VR_RANGE
|| TREE_CODE (vr->min) != INTEGER_CST
|| TREE_CODE (vr->max) != INTEGER_CST)
return false;
/* For sign changes, the MSB of the double_int has to be clear.
An unsigned value with its MSB set cannot be represented by
a signed double_int, while a negative value cannot be represented
by an unsigned double_int. */
if (TYPE_UNSIGNED (src_type) != unsigned_p
&& (TREE_INT_CST_HIGH (vr->min) | TREE_INT_CST_HIGH (vr->max)) < 0)
return false;
/* Then we can perform the conversion on both ends and compare
the result for equality. */
tem = tree_to_double_int (vr->min).ext (precision, unsigned_p);
if (tree_to_double_int (vr->min) != tem)
return false;
tem = tree_to_double_int (vr->max).ext (precision, unsigned_p);
if (tree_to_double_int (vr->max) != tem)
return false;
return true;
}
/* Simplify a conditional using a relational operator to an equality /* Simplify a conditional using a relational operator to an equality
test if the range information indicates only one value can satisfy test if the range information indicates only one value can satisfy
the original conditional. */ the original conditional. */
...@@ -8590,18 +8641,15 @@ simplify_cond_using_ranges (gimple stmt) ...@@ -8590,18 +8641,15 @@ simplify_cond_using_ranges (gimple stmt)
} }
} }
/* If we have a comparison of a SSA_NAME boolean against /* If we have a comparison of an SSA_NAME (OP0) against a constant,
a constant (which obviously must be [0..1]), see if the see if OP0 was set by a type conversion where the source of
SSA_NAME was set by a type conversion where the source the conversion is another SSA_NAME with a range that fits
of the conversion is another SSA_NAME with a range [0..1]. into the range of OP0's type.
If so, we can replace the SSA_NAME in the comparison with If so, the conversion is redundant as the earlier SSA_NAME can be
the RHS of the conversion. This will often make the type used for the comparison directly if we just massage the constant in the
conversion dead code which DCE will clean up. */ comparison. */
if (TREE_CODE (op0) == SSA_NAME if (TREE_CODE (op0) == SSA_NAME
&& (TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
|| (INTEGRAL_TYPE_P (TREE_TYPE (op0))
&& TYPE_PRECISION (TREE_TYPE (op0)) == 1))
&& TREE_CODE (op1) == INTEGER_CST) && TREE_CODE (op1) == INTEGER_CST)
{ {
gimple def_stmt = SSA_NAME_DEF_STMT (op0); gimple def_stmt = SSA_NAME_DEF_STMT (op0);
...@@ -8618,8 +8666,9 @@ simplify_cond_using_ranges (gimple stmt) ...@@ -8618,8 +8666,9 @@ simplify_cond_using_ranges (gimple stmt)
value_range_t *vr = get_value_range (innerop); value_range_t *vr = get_value_range (innerop);
if (range_int_cst_p (vr) if (range_int_cst_p (vr)
&& operand_equal_p (vr->min, integer_zero_node, 0) && range_fits_type_p (vr,
&& operand_equal_p (vr->max, integer_one_node, 0)) TYPE_PRECISION (TREE_TYPE (op0)),
TYPE_UNSIGNED (TREE_TYPE (op0))))
{ {
tree newconst = fold_convert (TREE_TYPE (innerop), op1); tree newconst = fold_convert (TREE_TYPE (innerop), op1);
gimple_cond_set_lhs (stmt, innerop); gimple_cond_set_lhs (stmt, innerop);
...@@ -8809,57 +8858,6 @@ simplify_conversion_using_ranges (gimple stmt) ...@@ -8809,57 +8858,6 @@ simplify_conversion_using_ranges (gimple stmt)
return true; return true;
} }
/* Return whether the value range *VR fits in an integer type specified
by PRECISION and UNSIGNED_P. */
static bool
range_fits_type_p (value_range_t *vr, unsigned precision, bool unsigned_p)
{
tree src_type;
unsigned src_precision;
double_int tem;
/* We can only handle integral and pointer types. */
src_type = TREE_TYPE (vr->min);
if (!INTEGRAL_TYPE_P (src_type)
&& !POINTER_TYPE_P (src_type))
return false;
/* An extension is fine unless VR is signed and unsigned_p,
and so is an identity transform. */
src_precision = TYPE_PRECISION (TREE_TYPE (vr->min));
if ((src_precision < precision
&& !(unsigned_p && !TYPE_UNSIGNED (src_type)))
|| (src_precision == precision
&& TYPE_UNSIGNED (src_type) == unsigned_p))
return true;
/* Now we can only handle ranges with constant bounds. */
if (vr->type != VR_RANGE
|| TREE_CODE (vr->min) != INTEGER_CST
|| TREE_CODE (vr->max) != INTEGER_CST)
return false;
/* For sign changes, the MSB of the double_int has to be clear.
An unsigned value with its MSB set cannot be represented by
a signed double_int, while a negative value cannot be represented
by an unsigned double_int. */
if (TYPE_UNSIGNED (src_type) != unsigned_p
&& (TREE_INT_CST_HIGH (vr->min) | TREE_INT_CST_HIGH (vr->max)) < 0)
return false;
/* Then we can perform the conversion on both ends and compare
the result for equality. */
tem = tree_to_double_int (vr->min).ext (precision, unsigned_p);
if (tree_to_double_int (vr->min) != tem)
return false;
tem = tree_to_double_int (vr->max).ext (precision, unsigned_p);
if (tree_to_double_int (vr->max) != tem)
return false;
return true;
}
/* Simplify a conversion from integral SSA name to float in STMT. */ /* Simplify a conversion from integral SSA name to float in STMT. */
static bool static bool
......
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