This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

VRP: range info of new variables


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.glisse@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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]