[RFA][PATCH] Eliminate more unnecessary type conversions
Richard Biener
richard.guenther@gmail.com
Mon Apr 29 09:53:00 GMT 2013
On Fri, Apr 26, 2013 at 8:53 PM, Jeff Law <law@redhat.com> wrote:
>
> So looking at more dumps made it pretty obvious that my previous patch to
> tree-vrp.c to eliminate useless casts to boolean types which fed into
> comparisons could and should be generalized.
>
> Given:
>
> x1 = (T1) x0;
> if (x1 COND CONST)
>
> If the known value range for x0 fits into T1, then we can rewrite as
>
> x1 = (T1) x0;
> if (x0 COND (T)CONST)
>
> Which typically makes the first statement dead and may allow further
> simplifications.
>
> Bootstrapped and regression tested on x86_64-unknown-linux-gnu. OK for the
> trunk?
Ok.
Thanks,
Richard.
>
> commit ad290c7270201042bfc3cde1d84c12e639e4bff7
> Author: Jeff Law <law@redhat.com>
> Date: Fri Apr 26 12:52:06 2013 -0600
>
> * 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.
>
> diff --git a/gcc/ChangeLog b/gcc/ChangeLog
> index d06eee6..f9b207c 100644
> --- a/gcc/ChangeLog
> +++ b/gcc/ChangeLog
> @@ -1,3 +1,10 @@
> +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-26 Vladimir Makarov <vmakarov@redhat.com>
>
> * rtl.h (struct rtx_def): Add comment for field jump.
> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
> index bbea9fa..6d7839f 100644
> --- a/gcc/testsuite/ChangeLog
> +++ b/gcc/testsuite/ChangeLog
> @@ -1,3 +1,7 @@
> +2013-04-26 Jeff Law <law@redhat.com>
> +
> + * gcc.dg/tree-ssa/vrp88.c: New test.
> +
> 2013-04-26 Jakub Jelinek <jakub@redhat.com>
>
> PR go/57045
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp88.c
> b/gcc/testsuite/gcc.dg/tree-ssa/vrp88.c
> new file mode 100644
> index 0000000..e43bdff
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp88.c
> @@ -0,0 +1,39 @@
> +/* { 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" } } */
> +
> +
> diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
> index cb4a09a..07e3e01 100644
> --- a/gcc/tree-vrp.c
> +++ b/gcc/tree-vrp.c
> @@ -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
>
More information about the Gcc-patches
mailing list