Hello,
when VRP does some transforms, it may create new SSA_NAMEs, but doesn't
give them range information. This can prevent cascading transformations in
a single VRP pass. With this patch, I assign range information to the
variable introduced by one transformation, and in another transformation,
I get range information through get_range_info instead of get_value_range
in order to have access to the new information.
Some notes:
- get_range_info only applies to integers, not pointers. I hope we are not
losing much by restricting this transformation. I could also call
get_value_range and only fall back to get_range_info if that failed (and
we don't have a pointer), but it doesn't seem worth it.
- Now that I think of it, maybe I should check that the variable is not a
pointer before calling set_range_info? Having range [0, 1] makes it
unlikely, but who knows...
- wide_int is much more complicated to use than I expected :-(
- the foldings that disappear in pr69270.c are for dead variables that are
now eliminated earlier.
Bootstrap+regtest on powerpc64le-unknown-linux-gnu, I also checked
manually that an earlier version of the patch fixes vrp47.c on
x86_64-pc-linux-gnu.
2016-05-16 Marc Glisse <marc.gli...@inria.fr>
gcc/
* tree-vrp.c (simplify_truth_ops_using_ranges): Set range
information for new SSA_NAME.
(simplify_switch_using_ranges): Get range through get_range_info
instead of get_value_range.
gcc/testsuite/
* gcc.dg/tree-ssa/pr69270.c: Adjust.
* gcc.dg/tree-ssa/vrp99.c: New testcase.
--
Marc Glisse
Index: gcc/testsuite/gcc.dg/tree-ssa/pr69270.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/pr69270.c (revision 236194)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr69270.c (working copy)
@@ -1,21 +1,19 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fsplit-paths -fdump-tree-dom3-details" } */
/* There should be two references to bufferstep that turn into
constants. */
/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. with
constant .0." 1 "dom3"} } */
/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. with
constant .1." 1 "dom3"} } */
/* And some assignments ought to fold down to constants. */
-/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = -1;" 1 "dom3"} }
*/
-/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = -2;" 1 "dom3"} }
*/
/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 1;" 1 "dom3"} } */
/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 0;" 1 "dom3"} } */
/* The XOR operations should have been optimized to constants. */
/* { dg-final { scan-tree-dump-not "bit_xor" "dom3"} } */
extern int *stepsizeTable;
void
Index: gcc/testsuite/gcc.dg/tree-ssa/vrp99.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/vrp99.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/vrp99.c (working copy)
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+unsigned f(unsigned i){
+ i >>= __SIZEOF_INT__ * __CHAR_BIT__ - 1;
+ return i == 0;
+}
+
+/* { dg-final { scan-tree-dump-not "\\(unsigned int\\)" "vrp1" } } */
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c (revision 236194)
+++ gcc/tree-vrp.c (working copy)
@@ -8933,20 +8933,24 @@ simplify_truth_ops_using_ranges (gimple_
gimple_assign_set_rhs_with_ops (gsi,
need_conversion
? NOP_EXPR : TREE_CODE (op0), op0);
/* For A != B we substitute A ^ B. Either with conversion. */
else if (need_conversion)
{
tree tem = make_ssa_name (TREE_TYPE (op0));
gassign *newop
= gimple_build_assign (tem, BIT_XOR_EXPR, op0, op1);
gsi_insert_before (gsi, newop, GSI_SAME_STMT);
+ if (TYPE_PRECISION (TREE_TYPE (tem)) > 1)
+ set_range_info (tem, VR_RANGE,
+ wi::zero (TYPE_PRECISION (TREE_TYPE (tem))),
+ wi::one (TYPE_PRECISION (TREE_TYPE (tem))));
gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem);
}
/* Or without. */
else
gimple_assign_set_rhs_with_ops (gsi, BIT_XOR_EXPR, op0, op1);
update_stmt (gsi_stmt (*gsi));
return true;
}
@@ -9641,50 +9645,48 @@ simplify_switch_using_ranges (gswitch *s
return false;
}
/* Simplify an integral conversion from an SSA name in STMT. */
static bool
simplify_conversion_using_ranges (gimple *stmt)
{
tree innerop, middleop, finaltype;
gimple *def_stmt;
- value_range *innervr;
signop inner_sgn, middle_sgn, final_sgn;
unsigned inner_prec, middle_prec, final_prec;
widest_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
finaltype = TREE_TYPE (gimple_assign_lhs (stmt));
if (!INTEGRAL_TYPE_P (finaltype))
return false;
middleop = gimple_assign_rhs1 (stmt);
def_stmt = SSA_NAME_DEF_STMT (middleop);
if (!is_gimple_assign (def_stmt)
|| !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
return false;
innerop = gimple_assign_rhs1 (def_stmt);
if (TREE_CODE (innerop) != SSA_NAME
|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop))
return false;
- /* Get the value-range of the inner operand. */
- innervr = get_value_range (innerop);
- if (innervr->type != VR_RANGE
- || TREE_CODE (innervr->min) != INTEGER_CST
- || TREE_CODE (innervr->max) != INTEGER_CST)
+ /* Get the value-range of the inner operand. Use get_range_info in
+ case innerop was created during substitute-and-fold. */
+ wide_int imin, imax;
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (innerop))
+ || get_range_info (innerop, &imin, &imax) != VR_RANGE)
return false;
+ innermin = widest_int::from (imin, TYPE_SIGN (TREE_TYPE (innerop)));
+ innermax = widest_int::from (imax, TYPE_SIGN (TREE_TYPE (innerop)));
/* Simulate the conversion chain to check if the result is equal if
the middle conversion is removed. */
- innermin = wi::to_widest (innervr->min);
- innermax = wi::to_widest (innervr->max);
-
inner_prec = TYPE_PRECISION (TREE_TYPE (innerop));
middle_prec = TYPE_PRECISION (TREE_TYPE (middleop));
final_prec = TYPE_PRECISION (finaltype);
/* If the first conversion is not injective, the second must not
be widening. */
if (wi::gtu_p (innermax - innermin,
wi::mask <widest_int> (middle_prec, false))
&& middle_prec < final_prec)
return false;