diff mbox

PR 64454: Improve VRP for %

Message ID alpine.DEB.2.02.1505081650350.18616@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse May 8, 2015, 2:59 p.m. UTC
Hello,

here is a rewrite of the patch, using wide_int, and improving a bit the 
result. Same ChangeLog, tested again on x86_64-linux-gnu.

Comments

Richard Biener May 8, 2015, 3:28 p.m. UTC | #1
On Fri, May 8, 2015 at 4:59 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
> Hello,
>
> here is a rewrite of the patch, using wide_int, and improving a bit the
> result. Same ChangeLog, tested again on x86_64-linux-gnu.

Please use /* */ for comments.

Otherwise ok!

Thanks,
Richard.

> --
> Marc Glisse
> Index: gcc/testsuite/gcc.dg/tree-ssa/vrp97.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/vrp97.c       (revision 0)
> +++ gcc/testsuite/gcc.dg/tree-ssa/vrp97.c       (working copy)
> @@ -0,0 +1,19 @@
> +/* PR tree-optimization/64454 */
> +/* { dg-options "-O2 -fdump-tree-vrp1" } */
> +
> +int f(int a, int b)
> +{
> +    if (a < -3 || a > 13) __builtin_unreachable();
> +    if (b < -6 || b > 9) __builtin_unreachable();
> +    int c = a % b;
> +    return c >= -3 && c <= 8;
> +}
> +
> +int g(int a, int b)
> +{
> +  int c = a % b;
> +  return c != -__INT_MAX__ - 1;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "return 1;" 2 "vrp1" } } */
> +/* { dg-final { cleanup-tree-dump "vrp1" } } */
> Index: gcc/testsuite/gcc.dg/vect/slp-perm-7.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/vect/slp-perm-7.c      (revision 222906)
> +++ gcc/testsuite/gcc.dg/vect/slp-perm-7.c      (working copy)
> @@ -63,15 +63,15 @@ int main (int argc, const char* argv[])
>
>    foo (input, output, input2, output2);
>
>    for (i = 0; i < N; i++)
>       if (output[i] != check_results[i] || output2[i] != check_results2[i])
>         abort ();
>
>    return 0;
>  }
>
> -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect"  {
> target vect_perm } } } */
> +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect"  {
> target vect_perm } } } */
>  /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect"
> { target vect_perm } } } */
>  /* { dg-final { cleanup-tree-dump "vect" } } */
>
>
> Index: gcc/tree-vrp.c
> ===================================================================
> --- gcc/tree-vrp.c      (revision 222906)
> +++ gcc/tree-vrp.c      (working copy)
> @@ -3189,40 +3189,73 @@ extract_range_from_binary_expr_1 (value_
>             }
>         }
>        else
>         {
>           extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
>           return;
>         }
>      }
>    else if (code == TRUNC_MOD_EXPR)
>      {
> -      if (vr1.type != VR_RANGE
> -         || range_includes_zero_p (vr1.min, vr1.max) != 0
> -         || vrp_val_is_min (vr1.min))
> +      if (range_is_null (&vr1))
>         {
> -         set_value_range_to_varying (vr);
> +         set_value_range_to_undefined (vr);
>           return;
>         }
> +      // ABS (A % B) < ABS (B) and either 0 <= A % B <= A or A <= A % B <=
> 0.
>        type = VR_RANGE;
> -      /* Compute MAX <|vr1.min|, |vr1.max|> - 1.  */
> -      max = fold_unary_to_constant (ABS_EXPR, expr_type, vr1.min);
> -      if (tree_int_cst_lt (max, vr1.max))
> -       max = vr1.max;
> -      max = int_const_binop (MINUS_EXPR, max, build_int_cst (TREE_TYPE
> (max), 1));
> -      /* If the dividend is non-negative the modulus will be
> -        non-negative as well.  */
> -      if (TYPE_UNSIGNED (expr_type)
> -         || value_range_nonnegative_p (&vr0))
> -       min = build_int_cst (TREE_TYPE (max), 0);
> +      signop sgn = TYPE_SIGN (expr_type);
> +      unsigned int prec = TYPE_PRECISION (expr_type);
> +      wide_int wmin, wmax, tmp;
> +      wide_int zero = wi::zero (prec);
> +      wide_int one = wi::one (prec);
> +      if (vr1.type == VR_RANGE && !symbolic_range_p (&vr1))
> +       {
> +         wmax = wi::sub (vr1.max, one);
> +         if (sgn == SIGNED)
> +           {
> +             tmp = wi::sub (wi::minus_one (prec), vr1.min);
> +             wmax = wi::smax (wmax, tmp);
> +           }
> +       }
> +      else
> +       {
> +         wmax = wi::max_value (prec, sgn);
> +         // X % INT_MIN may be INT_MAX.
> +         if (sgn == UNSIGNED)
> +           wmax = wmax - one;
> +       }
> +
> +      if (sgn == UNSIGNED)
> +       wmin = zero;
>        else
> -       min = fold_unary_to_constant (NEGATE_EXPR, expr_type, max);
> +       {
> +         wmin = -wmax;
> +         if (vr0.type == VR_RANGE && TREE_CODE (vr0.min) == INTEGER_CST)
> +           {
> +             tmp = vr0.min;
> +             if (wi::gts_p (tmp, zero))
> +               tmp = zero;
> +             wmin = wi::smax (wmin, tmp);
> +           }
> +       }
> +
> +      if (vr0.type == VR_RANGE && TREE_CODE (vr0.max) == INTEGER_CST)
> +       {
> +         tmp = vr0.max;
> +         if (sgn == SIGNED && wi::neg_p (tmp))
> +           tmp = zero;
> +         wmax = wi::min (wmax, tmp, sgn);
> +       }
> +
> +      min = wide_int_to_tree (expr_type, wmin);
> +      max = wide_int_to_tree (expr_type, wmax);
>      }
>    else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code ==
> BIT_XOR_EXPR)
>      {
>        bool int_cst_range0, int_cst_range1;
>        wide_int may_be_nonzero0, may_be_nonzero1;
>        wide_int must_be_nonzero0, must_be_nonzero1;
>
>        int_cst_range0 = zero_nonzero_bits_from_vr (expr_type, &vr0,
>                                                   &may_be_nonzero0,
>                                                   &must_be_nonzero0);
>
diff mbox

Patch

Index: gcc/testsuite/gcc.dg/tree-ssa/vrp97.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/vrp97.c	(revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/vrp97.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* PR tree-optimization/64454 */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+int f(int a, int b)
+{
+    if (a < -3 || a > 13) __builtin_unreachable();
+    if (b < -6 || b > 9) __builtin_unreachable();
+    int c = a % b;
+    return c >= -3 && c <= 8;
+}
+
+int g(int a, int b)
+{
+  int c = a % b;
+  return c != -__INT_MAX__ - 1;
+}
+
+/* { dg-final { scan-tree-dump-times "return 1;" 2 "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
Index: gcc/testsuite/gcc.dg/vect/slp-perm-7.c
===================================================================
--- gcc/testsuite/gcc.dg/vect/slp-perm-7.c	(revision 222906)
+++ gcc/testsuite/gcc.dg/vect/slp-perm-7.c	(working copy)
@@ -63,15 +63,15 @@  int main (int argc, const char* argv[])
 
   foo (input, output, input2, output2);
 
   for (i = 0; i < N; i++)
      if (output[i] != check_results[i] || output2[i] != check_results2[i])
        abort ();
 
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect"  { target vect_perm } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect"  { target vect_perm } } } */
 /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_perm } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 
 
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	(revision 222906)
+++ gcc/tree-vrp.c	(working copy)
@@ -3189,40 +3189,73 @@  extract_range_from_binary_expr_1 (value_
 	    }
 	}
       else
 	{
 	  extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
 	  return;
 	}
     }
   else if (code == TRUNC_MOD_EXPR)
     {
-      if (vr1.type != VR_RANGE
-	  || range_includes_zero_p (vr1.min, vr1.max) != 0
-	  || vrp_val_is_min (vr1.min))
+      if (range_is_null (&vr1))
 	{
-	  set_value_range_to_varying (vr);
+	  set_value_range_to_undefined (vr);
 	  return;
 	}
+      // ABS (A % B) < ABS (B) and either 0 <= A % B <= A or A <= A % B <= 0.
       type = VR_RANGE;
-      /* Compute MAX <|vr1.min|, |vr1.max|> - 1.  */
-      max = fold_unary_to_constant (ABS_EXPR, expr_type, vr1.min);
-      if (tree_int_cst_lt (max, vr1.max))
-	max = vr1.max;
-      max = int_const_binop (MINUS_EXPR, max, build_int_cst (TREE_TYPE (max), 1));
-      /* If the dividend is non-negative the modulus will be
-	 non-negative as well.  */
-      if (TYPE_UNSIGNED (expr_type)
-	  || value_range_nonnegative_p (&vr0))
-	min = build_int_cst (TREE_TYPE (max), 0);
+      signop sgn = TYPE_SIGN (expr_type);
+      unsigned int prec = TYPE_PRECISION (expr_type);
+      wide_int wmin, wmax, tmp;
+      wide_int zero = wi::zero (prec);
+      wide_int one = wi::one (prec);
+      if (vr1.type == VR_RANGE && !symbolic_range_p (&vr1))
+	{
+	  wmax = wi::sub (vr1.max, one);
+	  if (sgn == SIGNED)
+	    {
+	      tmp = wi::sub (wi::minus_one (prec), vr1.min);
+	      wmax = wi::smax (wmax, tmp);
+	    }
+	}
+      else
+	{
+	  wmax = wi::max_value (prec, sgn);
+	  // X % INT_MIN may be INT_MAX.
+	  if (sgn == UNSIGNED)
+	    wmax = wmax - one;
+	}
+
+      if (sgn == UNSIGNED)
+	wmin = zero;
       else
-	min = fold_unary_to_constant (NEGATE_EXPR, expr_type, max);
+	{
+	  wmin = -wmax;
+	  if (vr0.type == VR_RANGE && TREE_CODE (vr0.min) == INTEGER_CST)
+	    {
+	      tmp = vr0.min;
+	      if (wi::gts_p (tmp, zero))
+		tmp = zero;
+	      wmin = wi::smax (wmin, tmp);
+	    }
+	}
+
+      if (vr0.type == VR_RANGE && TREE_CODE (vr0.max) == INTEGER_CST)
+	{
+	  tmp = vr0.max;
+	  if (sgn == SIGNED && wi::neg_p (tmp))
+	    tmp = zero;
+	  wmax = wi::min (wmax, tmp, sgn);
+	}
+
+      min = wide_int_to_tree (expr_type, wmin);
+      max = wide_int_to_tree (expr_type, wmax);
     }
   else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR)
     {
       bool int_cst_range0, int_cst_range1;
       wide_int may_be_nonzero0, may_be_nonzero1;
       wide_int must_be_nonzero0, must_be_nonzero1;
 
       int_cst_range0 = zero_nonzero_bits_from_vr (expr_type, &vr0,
 						  &may_be_nonzero0,
 						  &must_be_nonzero0);