This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PR 64454: Improve VRP for %
- From: Marc Glisse <marc dot glisse at inria dot fr>
- To: Richard Biener <richard dot guenther at gmail dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 8 May 2015 16:59:10 +0200 (CEST)
- Subject: Re: PR 64454: Improve VRP for %
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot DEB dot 2 dot 02 dot 1505020023190 dot 30644 at stedding dot saclay dot inria dot fr> <CAFiYyc00PPtN9VvLB3z1k3zA2JUu9Gk0yunRWucE+-PyBiQU_A at mail dot gmail dot com> <alpine dot DEB dot 2 dot 11 dot 1505041543340 dot 2030 at laptop-mg dot saclay dot inria dot fr> <CAFiYyc2eCPMqbdbt2JsOrHOw=yn2rGV-2mOBrQv9xJs8W-RvTA at mail dot gmail dot com>
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.
--
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);