Hi!

Ian reported a bug in optimize_range_tests_to_bit_test, high used to be
off-by-one.  E.g. if the topmost bit in mask is set (wi::clz (mask) is
0), then the highest number covered by the mask is lowi (which corresponds
to bit 0) + prec - 1, rather than lowi + prec.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
committed to trunk as obvious.

2014-10-25  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/63641
        * tree-ssa-reassoc.c (optimize_range_tests_to_bit_test): Set high
        to low + prec - 1 - clz (mask) instead of low + prec - clz (mask).

        * gcc.c-torture/execute/pr63641.c: New test.

--- gcc/tree-ssa-reassoc.c.jj   2014-10-17 12:53:59.000000000 +0200
+++ gcc/tree-ssa-reassoc.c      2014-10-24 22:38:55.762859480 +0200
@@ -2513,7 +2513,7 @@ optimize_range_tests_to_bit_test (enum t
        {
          tree high = wide_int_to_tree (TREE_TYPE (lowi),
                                        wi::to_widest (lowi)
-                                       + prec - wi::clz (mask));
+                                       + prec - 1 - wi::clz (mask));
          operand_entry_t oe = (*ops)[ranges[i].idx];
          tree op = oe->op;
          gimple stmt = op ? SSA_NAME_DEF_STMT (op)
--- gcc/testsuite/gcc.c-torture/execute/pr63641.c.jj    2014-10-25 
18:54:15.338191911 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr63641.c       2014-10-25 
18:53:21.000000000 +0200
@@ -0,0 +1,54 @@
+/* PR tree-optimization/63641 */
+
+__attribute__ ((noinline, noclone)) int
+foo (unsigned char b)
+{
+  if (0x0 <= b && b <= 0x8)
+    goto lab;
+  if (b == 0x0b)
+    goto lab;
+  if (0x0e <= b && b <= 0x1a)
+    goto lab;
+  if (0x1c <= b && b <= 0x1f)
+    goto lab;
+  return 0;
+lab:
+  return 1;
+}
+
+__attribute__ ((noinline, noclone)) int
+bar (unsigned char b)
+{
+  if (0x0 <= b && b <= 0x8)
+    goto lab;
+  if (b == 0x0b)
+    goto lab;
+  if (0x0e <= b && b <= 0x1a)
+    goto lab;
+  if (0x3c <= b && b <= 0x3f)
+    goto lab;
+  return 0;
+lab:
+  return 1;
+}
+
+char tab1[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 };
+char tab2[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 };
+
+int
+main ()
+{
+  int i;
+  asm volatile ("" : : : "memory");
+  for (i = 0; i < 256; i++)
+    if (foo (i) != (i < 32 ? tab1[i] : 0))
+      __builtin_abort ();
+  for (i = 0; i < 256; i++)
+    if (bar (i) != (i < 64 ? tab2[i] : 0))
+      __builtin_abort ();
+  return 0;
+}

        Jakub

Reply via email to