[PATCH] Improve VRP of BIT_AND_EXPR
Jakub Jelinek
jakub@redhat.com
Thu Jul 8 17:06:00 GMT 2010
Hi!
Looking at PR44858, I was surprised VRP doesn't figure out
for
x = (a > b);
y = x & 2;
that y is 0. Similarly say for x & y when
x is [1024, 1039] and y is [2048, 2063], we can count
on the result being [0, 15] (the 0x400 and 0x800 bits are both cleared),
etc.
The following patch improves handling of BIT_AND_EXPR.
Bootstrapped/regtested on x86_64-linux and i686-linux. Ok for trunk?
In the testsuite slp-perm-4.c was the only failure, because in
for (i = 0; i < 16; i++)
{
i %= 256;
if (i > 200)
abort ();
...
}
with the patch the conditional and abort is now optimized away - previously
i &= 255; was VARYING, now is [0, 15].
As next step, I guess VRP should be able to optimize that &= 255 away
completely, because the argument is known to be [0, 15], so doesn't need
any masking.
2010-07-08 Jakub Jelinek <jakub@redhat.com>
* tree-vrp.c (extract_range_from_binary_expr) <BIT_AND_EXPR>: If
both ranges are range_int_cst_p with non-negative minimum,
try harder to derive smaller range.
* gcc.dg/tree-ssa/vrp50.c: New test.
* gcc.dg/vect/slp-perm-4.c (main): Make sure loop isn't vectorized.
--- gcc/tree-vrp.c.jj 2010-07-05 12:37:01.000000000 +0200
+++ gcc/tree-vrp.c 2010-07-08 16:03:11.000000000 +0200
@@ -2577,6 +2577,58 @@ extract_range_from_binary_expr (value_ra
if (vr0_int_cst_singleton_p && vr1_int_cst_singleton_p)
min = max = int_const_binop (code, vr0.max, vr1.max, 0);
+ else if (range_int_cst_p (&vr0)
+ && range_int_cst_p (&vr1)
+ && tree_int_cst_sgn (vr0.min) >= 0
+ && tree_int_cst_sgn (vr1.min) >= 0)
+ {
+ double_int vr0_mask = tree_to_double_int (vr0.min);
+ double_int vr1_mask = tree_to_double_int (vr1.min);
+ double_int maxd, diff;
+ tree mask;
+
+ min = build_int_cst (expr_type, 0);
+ /* Compute non-zero bits mask from both ranges. */
+ if (!vr0_int_cst_singleton_p)
+ {
+ maxd = tree_to_double_int (vr0.max);
+ diff = double_int_sub (maxd, vr0_mask);
+ if (diff.high)
+ {
+ diff.low = ~(unsigned HOST_WIDE_INT)0;
+ diff.high = ((HOST_WIDE_INT) 2
+ << floor_log2 (diff.high)) - 1;
+ }
+ else
+ diff.low = ((HOST_WIDE_INT) 2 << floor_log2 (diff.low)) - 1;
+ vr0_mask = double_int_ior (vr0_mask,
+ double_int_ior (maxd, diff));
+ }
+ if (!vr1_int_cst_singleton_p)
+ {
+ maxd = tree_to_double_int (vr1.max);
+ diff = double_int_sub (maxd, vr1_mask);
+ if (diff.high)
+ {
+ diff.low = ~(unsigned HOST_WIDE_INT)0;
+ diff.high = ((HOST_WIDE_INT) 2
+ << floor_log2 (diff.high)) - 1;
+ }
+ else
+ diff.low = ((HOST_WIDE_INT) 2 << floor_log2 (diff.low)) - 1;
+ vr1_mask = double_int_ior (vr1_mask,
+ double_int_ior (maxd, diff));
+ }
+ mask = double_int_to_tree (expr_type,
+ double_int_and (vr0_mask, vr1_mask));
+ max = vr0.max;
+ if (tree_int_cst_lt (vr1.max, max))
+ max = vr1.max;
+ if (!TREE_OVERFLOW (mask)
+ && tree_int_cst_lt (mask, max)
+ && tree_int_cst_sgn (mask) >= 0)
+ max = mask;
+ }
else if (vr0_int_cst_singleton_p
&& tree_int_cst_sgn (vr0.max) >= 0)
{
--- gcc/testsuite/gcc.dg/tree-ssa/vrp50.c.jj 2010-07-08 16:24:42.000000000 +0200
+++ gcc/testsuite/gcc.dg/tree-ssa/vrp50.c 2010-07-08 16:32:26.000000000 +0200
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+int
+foo (unsigned int i, unsigned int j)
+{
+ i &= 15;
+ j &= 15;
+ i += 1024;
+ j += 2048;
+ i &= j;
+ return i < 16;
+}
+
+int
+bar (int i)
+{
+ int c = 2;
+ c &= i > 6;
+ return c == 0;
+}
+
+int baz (int x, int y)
+{
+ x &= 15;
+ y &= 15;
+ x += 4;
+ y += 16;
+ x &= y;
+ return x < 20;
+}
+
+/* { dg-final { scan-tree-dump "Folding predicate i_\[^\n\r\]* to 1" "vrp1" } } */
+/* { dg-final { scan-tree-dump "Folding predicate c_\[^\n\r\]* to 1" "vrp1" } } */
+/* { dg-final { scan-tree-dump "Folding predicate x_\[^\n\r\]* to 1" "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
--- gcc/testsuite/gcc.dg/vect/slp-perm-4.c.jj 2010-06-11 11:00:46.000000000 +0200
+++ gcc/testsuite/gcc.dg/vect/slp-perm-4.c 2010-07-08 18:53:40.102558207 +0200
@@ -69,6 +69,7 @@ int main (int argc, const char* argv[])
if (input[i] > 200)
abort();
output[i] = 0;
+ __asm__ volatile ("");
}
foo (input, output);
Jakub
More information about the Gcc-patches
mailing list