Hi all,

There is an off-by-one error in the clear_bit_region helper in store merging in 
the case where it deals with
multi-byte quantities starting at a non-zero bit offset. The particular input is
{0xff, 0xff, 0xff} and we want to clear all bits except the least and most 
significant i.e. we want:
{0x01, 0x00, 0x80} so it's called as clear_bit_region (input, 1, 22);
This ends up clearing one more bit due to this bug. The patch fixes that.
The last argument to clear_bit_region is the number of bits left to clear and 
since in the previous call we cleared
BITS_PER_UNIT - start bits we should subtract exactly that amount from len when 
calculating the bits left to clear.
This was uncovered when writing initial unit tests for these functions which 
are included in the followup patch.

Bootstrapped and tested on aarch64 and x86_64 (the affected function is only 
called for little-endian code).

Ok for trunk?
Thanks,
Kyrill

2016-11-08  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

    PR tree-optimization/78234
    * gimple-ssa-store-merging.c (clear_bit_region): Fix off-by-one error
    in start != 0 case.
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 36bc833af910f85c4c8ed7581a247f5d3182053d..46f92ba2d2f4e85c4256be11be5c8b1d40c21499 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -337,7 +337,7 @@ clear_bit_region (unsigned char *ptr, unsigned int start,
   else if (start != 0)
     {
       clear_bit_region (ptr, start, BITS_PER_UNIT - start);
-      clear_bit_region (ptr + 1, 0, len - (BITS_PER_UNIT - start) + 1);
+      clear_bit_region (ptr + 1, 0, len - (BITS_PER_UNIT - start));
     }
   /* Whole bytes need to be cleared.  */
   else if (start == 0 && len > BITS_PER_UNIT)

Reply via email to