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]

Re: [PATCH] Improve x % y to x VRP optimization (PR tree-optimization/79408)


On Mon, Feb 13, 2017 at 09:59:12AM +0100, Richard Biener wrote:
> On Sun, 12 Feb 2017, Marc Glisse wrote:
> 
> > On Sun, 12 Feb 2017, Marc Glisse wrote:
> > 
> > > On Tue, 7 Feb 2017, Jakub Jelinek wrote:
> > > 
> > > > 	* tree-vrp.c (simplify_div_or_mod_using_ranges): If op1 is not
> > > > 	constant, but SSA_NAME with a known integer range, use the minimum
> > > > 	of that range instead of op1 to determine if modulo can be replaced
> > > > 	with its first operand.
> > > 
> > > Would it make sense to use something like the operand_less_p helper so we
> > > would also handle an INTEGER_CST lhs?
> > 
> > Oops, operand_less_p is just a helper for compare_values_warnv and even that
> > one doesn't seem to use ranges, so there may not already be a nice function we
> > can call (?). The idea remains that reusing such code would help handle more
> > cases (it may even handle a few symbolic cases).
> 
> Yeah, we only have the compare_range_with_value / compare_ranges functions
> and those require you to "expand" the value you have a range for first.

I think we can do something like following, but not sure how you want to
actually simplify it using helpers.  The only thing I can think of is
something like get_value_range that works on both SSA_NAMEs and
INTEGER_CSTs, but then it either has to allocate a new value range struct
for the INTEGER_CST case, or be more like extract_range_from_tree and
then it would copy the range for the SSA_NAME case, penalizing the code.

2017-02-13  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/79408
	* tree-vrp.c (simplify_div_or_mod_using_ranges): Handle also the
	case when on TRUNC_MOD_EXPR op0 is INTEGER_CST.
	(simplify_stmt_using_ranges): Call simplify_div_or_mod_using_ranges
	also if rhs1 is INTEGER_CST.

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

--- gcc/tree-vrp.c.jj	2017-02-08 10:21:31.000000000 +0100
+++ gcc/tree-vrp.c	2017-02-13 10:55:00.755070795 +0100
@@ -9241,8 +9241,24 @@ simplify_div_or_mod_using_ranges (gimple
   tree val = NULL;
   tree op0 = gimple_assign_rhs1 (stmt);
   tree op1 = gimple_assign_rhs2 (stmt);
+  tree op0min = NULL_TREE, op0max = NULL_TREE;
   tree op1min = op1;
-  value_range *vr = get_value_range (op0);
+  value_range *vr = NULL;
+
+  if (TREE_CODE (op0) == INTEGER_CST)
+    {
+      op0min = op0;
+      op0max = op0;
+    }
+  else
+    {
+      vr = get_value_range (op0);
+      if (range_int_cst_p (vr))
+	{
+	  op0min = vr->min;
+	  op0max = vr->max;
+	}
+    }
 
   if (rhs_code == TRUNC_MOD_EXPR
       && TREE_CODE (op1) == SSA_NAME)
@@ -9254,13 +9270,13 @@ simplify_div_or_mod_using_ranges (gimple
   if (rhs_code == TRUNC_MOD_EXPR
       && TREE_CODE (op1min) == INTEGER_CST
       && tree_int_cst_sgn (op1min) == 1
-      && range_int_cst_p (vr)
-      && tree_int_cst_lt (vr->max, op1min))
+      && op0max
+      && tree_int_cst_lt (op0max, op1min))
     {
       if (TYPE_UNSIGNED (TREE_TYPE (op0))
-	  || tree_int_cst_sgn (vr->min) >= 0
+	  || tree_int_cst_sgn (op0min) >= 0
 	  || tree_int_cst_lt (fold_unary (NEGATE_EXPR, TREE_TYPE (op1min), op1min),
-			      vr->min))
+			      op0min))
 	{
 	  /* If op0 already has the range op0 % op1 has,
 	     then TRUNC_MOD_EXPR won't change anything.  */
@@ -9269,6 +9285,9 @@ simplify_div_or_mod_using_ranges (gimple
 	}
     }
 
+  if (TREE_CODE (op0) != SSA_NAME)
+    return false;
+
   if (!integer_pow2p (op1))
     {
       /* X % -Y can be only optimized into X % Y either if
@@ -10377,7 +10396,8 @@ simplify_stmt_using_ranges (gimple_stmt_
 	 range.  */
 	case TRUNC_DIV_EXPR:
 	case TRUNC_MOD_EXPR:
-	  if (TREE_CODE (rhs1) == SSA_NAME
+	  if ((TREE_CODE (rhs1) == SSA_NAME
+	       || TREE_CODE (rhs1) == INTEGER_CST)
 	      && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
 	    return simplify_div_or_mod_using_ranges (gsi, stmt);
 	  break;
--- gcc/testsuite/gcc.dg/tree-ssa/pr79408-2.c.jj	2017-02-13 10:51:13.939063664 +0100
+++ gcc/testsuite/gcc.dg/tree-ssa/pr79408-2.c	2017-02-13 10:52:33.868008990 +0100
@@ -0,0 +1,34 @@
+/* PR tree-optimization/79408 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void link_error (void);
+
+void
+foo (unsigned int y)
+{
+  if (y <= 7312)
+    return;
+  if (7312 % y != 7312)
+    link_error ();
+}
+
+void
+bar (int x, int y)
+{
+  if (y <= 7312)
+    return;
+  if (7312 % y != 7312)
+    link_error ();
+}
+
+void
+baz (int x, int y)
+{
+  if (y <= 7312)
+    return;
+  if (-7312 % y != -7312)
+    link_error ();
+}
+
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */


	Jakub


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