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>
* 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>
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,
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
test if the range information indicates only one value can satisfy
the original conditional. */
......@@ -8590,18 +8641,15 @@ simplify_cond_using_ranges (gimple stmt)
}
}
/* If we have a comparison of a SSA_NAME boolean against
a constant (which obviously must be [0..1]), see if the
SSA_NAME was set by a type conversion where the source
of the conversion is another SSA_NAME with a range [0..1].
/* If we have a comparison of an SSA_NAME (OP0) against a constant,
see if OP0 was set by a type conversion where the source of
the conversion is another SSA_NAME with a range that fits
into the range of OP0's type.
If so, we can replace the SSA_NAME in the comparison with
the RHS of the conversion. This will often make the type
conversion dead code which DCE will clean up. */
If so, the conversion is redundant as the earlier SSA_NAME can be
used for the comparison directly if we just massage the constant in the
comparison. */
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)
{
gimple def_stmt = SSA_NAME_DEF_STMT (op0);
......@@ -8618,8 +8666,9 @@ simplify_cond_using_ranges (gimple stmt)
value_range_t *vr = get_value_range (innerop);
if (range_int_cst_p (vr)
&& operand_equal_p (vr->min, integer_zero_node, 0)
&& operand_equal_p (vr->max, integer_one_node, 0))
&& range_fits_type_p (vr,
TYPE_PRECISION (TREE_TYPE (op0)),
TYPE_UNSIGNED (TREE_TYPE (op0))))
{
tree newconst = fold_convert (TREE_TYPE (innerop), op1);
gimple_cond_set_lhs (stmt, innerop);
......@@ -8809,57 +8858,6 @@ simplify_conversion_using_ranges (gimple stmt)
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. */
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