Ping? Best regards,
Thomas > -----Original Message----- > From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches- > ow...@gcc.gnu.org] On Behalf Of Thomas Preud'homme > Sent: Thursday, August 07, 2014 1:57 PM > To: gcc-patches@gcc.gnu.org > Subject: RE: [PATCH] Fix confusion between target, host and symbolic > number byte sizes > > I suppose people were busy when I posted this patch and it got forgotten > since so here is a little ping. > > Best regards, > > Thomas > > > -----Original Message----- > > From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches- > > ow...@gcc.gnu.org] On Behalf Of Thomas Preud'homme > > Sent: Friday, July 04, 2014 12:53 PM > > To: gcc-patches@gcc.gnu.org > > Subject: [PATCH] Fix confusion between target, host and symbolic number > > byte sizes > > > > The bswap pass deals with 3 possibly different byte size: host, target and > the > > size a byte marker occupied in the symbolic_number structure [1]. > However, > > as of now the code mixes the three size. This works in practice as the pass > is > > only enabled for target with BITS_PER_UNIT == 8 and nobody runs GCC on > a > > host with CHAR_BIT != 8. As prompted by Jakub Jelinek, this patch fixes this > > mess. Byte marker are 8-bit quantities (they could be made 4-bit quantities > > but I prefered to keep the code working the same as before) for which a > > new macro is introduced (BITS_PER_MARKERS), anything related to storing > > the value or a byte marker in a variable should check for the host byte size > or > > wide integer size and anything aimed at manipulating the target value > should > > check for BITS_PER_UNIT. > > > > > > [1] Although the comment for this structure implies that a byte marker as > the > > same size as the host byte, the way it is used in the code (even before any > of > > my patch) shows that it uses a fixed size of 8 [2]. > > [2] Note that since the pass is only active for targets with BITS_PER_UNIT > == > > 8, it might be using the target byte size. > > > > gcc/ChangeLog: > > > > 2014-07-04 Thomas Preud'homme <thomas.preudho...@arm.com> > > > > * tree-ssa-math-opts.c (struct symbolic_number): Clarify comment > > about > > the size of byte markers. > > (do_shift_rotate): Fix confusion between host, target and marker > > byte > > size. > > (verify_symbolic_number_p): Likewise. > > (find_bswap_or_nop_1): Likewise. > > (find_bswap_or_nop): Likewise. > > > > > > diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c > > index ca2b30d..55c5df7 100644 > > --- a/gcc/tree-ssa-math-opts.c > > +++ b/gcc/tree-ssa-math-opts.c > > @@ -1602,11 +1602,10 @@ make_pass_cse_sincos (gcc::context *ctxt) > > > > /* A symbolic number is used to detect byte permutation and selection > > patterns. Therefore the field N contains an artificial number > > - consisting of byte size markers: > > + consisting of octet sized markers: > > > > - 0 - byte has the value 0 > > - 1..size - byte contains the content of the byte > > - number indexed with that value minus one. > > + 0 - target byte has the value 0 > > + 1..size - marker value is the target byte index minus one. > > > > To detect permutations on memory sources (arrays and structures), a > > symbolic > > number is also associated a base address (the array or structure the > > load > is > > @@ -1631,6 +1630,8 @@ struct symbolic_number { > > unsigned HOST_WIDE_INT range; > > }; > > > > +#define BITS_PER_MARKER 8 > > + > > /* The number which the find_bswap_or_nop_1 result should match in > > order to have a nop. The number is masked according to the size of > > the symbolic number before using it. */ > > @@ -1652,15 +1653,16 @@ do_shift_rotate (enum tree_code code, > > struct symbolic_number *n, > > int count) > > { > > - int bitsize = TYPE_PRECISION (n->type); > > + int size = TYPE_PRECISION (n->type) / BITS_PER_UNIT; > > > > - if (count % 8 != 0) > > + if (count % BITS_PER_UNIT != 0) > > return false; > > + count = (count / BITS_PER_UNIT) * BITS_PER_MARKER; > > > > /* Zero out the extra bits of N in order to avoid them being shifted > > into the significant bits. */ > > - if (bitsize < 8 * (int)sizeof (int64_t)) > > - n->n &= ((uint64_t)1 << bitsize) - 1; > > + if (size < 64 / BITS_PER_MARKER) > > + n->n &= ((uint64_t) 1 << (size * BITS_PER_MARKER)) - 1; > > > > switch (code) > > { > > @@ -1670,22 +1672,22 @@ do_shift_rotate (enum tree_code code, > > case RSHIFT_EXPR: > > /* Arithmetic shift of signed type: result is dependent on the > > value. */ > > if (!TYPE_UNSIGNED (n->type) > > - && (n->n & ((uint64_t) 0xff << (bitsize - 8)))) > > + && (n->n & ((uint64_t) 0xff << ((size - 1) * BITS_PER_MARKER)))) > > return false; > > n->n >>= count; > > break; > > case LROTATE_EXPR: > > - n->n = (n->n << count) | (n->n >> (bitsize - count)); > > + n->n = (n->n << count) | (n->n >> ((size * BITS_PER_MARKER) - > count)); > > break; > > case RROTATE_EXPR: > > - n->n = (n->n >> count) | (n->n << (bitsize - count)); > > + n->n = (n->n >> count) | (n->n << ((size * BITS_PER_MARKER) - > count)); > > break; > > default: > > return false; > > } > > /* Zero unused bits for size. */ > > - if (bitsize < 8 * (int)sizeof (int64_t)) > > - n->n &= ((uint64_t)1 << bitsize) - 1; > > + if (size < 64 / BITS_PER_MARKER) > > + n->n &= ((uint64_t) 1 << (size * BITS_PER_MARKER)) - 1; > > return true; > > } > > > > @@ -1726,13 +1728,13 @@ init_symbolic_number (struct > symbolic_number > > *n, tree src) > > if (size % BITS_PER_UNIT != 0) > > return false; > > size /= BITS_PER_UNIT; > > - if (size > (int)sizeof (uint64_t)) > > + if (size > 64 / BITS_PER_MARKER) > > return false; > > n->range = size; > > n->n = CMPNOP; > > > > - if (size < (int)sizeof (int64_t)) > > - n->n &= ((uint64_t)1 << (size * BITS_PER_UNIT)) - 1; > > + if (size < 64 / BITS_PER_MARKER) > > + n->n &= ((uint64_t) 1 << (size * BITS_PER_MARKER)) - 1; > > > > return true; > > } > > @@ -1870,15 +1872,17 @@ find_bswap_or_nop_1 (gimple stmt, struct > > symbolic_number *n, int limit) > > case BIT_AND_EXPR: > > { > > int i, size = TYPE_PRECISION (n->type) / BITS_PER_UNIT; > > - uint64_t val = int_cst_value (rhs2); > > - uint64_t tmp = val; > > + uint64_t val = int_cst_value (rhs2), mask = 0; > > + uint64_t tmp = (1 << BITS_PER_UNIT) - 1; > > > > /* Only constants masking full bytes are allowed. */ > > - for (i = 0; i < size; i++, tmp >>= BITS_PER_UNIT) > > - if ((tmp & 0xff) != 0 && (tmp & 0xff) != 0xff) > > + for (i = 0; i < size; i++, tmp <<= BITS_PER_UNIT) > > + if ((val & tmp) != 0 && (val & tmp) != tmp) > > return NULL; > > + else if (val & tmp) > > + mask |= (uint64_t) 0xff << (i * BITS_PER_MARKER); > > > > - n->n &= val; > > + n->n &= mask; > > } > > break; > > case LSHIFT_EXPR: > > @@ -1897,25 +1901,27 @@ find_bswap_or_nop_1 (gimple stmt, struct > > symbolic_number *n, int limit) > > type_size = TYPE_PRECISION (type); > > if (type_size % BITS_PER_UNIT != 0) > > return NULL; > > - if (type_size > (int)sizeof (uint64_t) * 8) > > + type_size /= BITS_PER_UNIT; > > + if (type_size > 64 / BITS_PER_MARKER) > > return NULL; > > > > /* Sign extension: result is dependent on the value. */ > > - old_type_size = TYPE_PRECISION (n->type); > > + old_type_size = TYPE_PRECISION (n->type) / BITS_PER_UNIT; > > if (!TYPE_UNSIGNED (n->type) > > && type_size > old_type_size > > - && n->n & ((uint64_t) 0xff << (old_type_size - 8))) > > + && n->n & ((uint64_t) 0xff << ((old_type_size - 1) > > + * BITS_PER_MARKER))) > > return NULL; > > > > - if (type_size / BITS_PER_UNIT < (int)(sizeof (int64_t))) > > + if (type_size < 64 / BITS_PER_MARKER) > > { > > /* If STMT casts to a smaller type mask out the bits not > > belonging to the target type. */ > > - n->n &= ((uint64_t)1 << type_size) - 1; > > + n->n &= ((uint64_t) 1 << (type_size * BITS_PER_MARKER)) - > > 1; > > } > > n->type = type; > > if (!n->base_addr) > > - n->range = type_size / BITS_PER_UNIT; > > + n->range = type_size; > > } > > break; > > default: > > @@ -1965,7 +1971,6 @@ find_bswap_or_nop_1 (gimple stmt, struct > > symbolic_number *n, int limit) > > != gimple_assign_rhs1 (source_stmt2)) > > { > > int64_t inc, mask; > > - unsigned i; > > HOST_WIDE_INT off_sub; > > struct symbolic_number *n_ptr; > > > > @@ -1989,21 +1994,23 @@ find_bswap_or_nop_1 (gimple stmt, struct > > symbolic_number *n, int limit) > > > > off_sub = n2.bytepos - n1.bytepos; > > > > - /* Check that the range of memory covered < biggest int size. */ > > - if (off_sub + n2.range > (int) sizeof (int64_t)) > > + /* Check that the range of memory covered can be represented > > by > > + a symbolic number. */ > > + if (off_sub + n2.range > 64 / BITS_PER_MARKER) > > return NULL; > > n->range = n2.range + off_sub; > > > > /* Reinterpret byte marks in symbolic number holding the value > > of > > bigger weight according to target endianness. */ > > inc = BYTES_BIG_ENDIAN ? off_sub + n2.range - n1.range : > > off_sub; > > - mask = 0xFF; > > + size = TYPE_PRECISION (n1.type) / BITS_PER_UNIT; > > + mask = 0xff; > > if (BYTES_BIG_ENDIAN) > > n_ptr = &n1; > > else > > n_ptr = &n2; > > - for (i = 0; i < sizeof (int64_t); i++, inc <<= 8, > > - mask <<= 8) > > + for (i = 0; i < size; i++, inc <<= BITS_PER_MARKER, > > + mask <<= BITS_PER_MARKER) > > { > > if (n_ptr->n & mask) > > n_ptr->n += inc; > > @@ -2023,7 +2030,7 @@ find_bswap_or_nop_1 (gimple stmt, struct > > symbolic_number *n, int limit) > > n->bytepos = n1.bytepos; > > n->type = n1.type; > > size = TYPE_PRECISION (n->type) / BITS_PER_UNIT; > > - for (i = 0, mask = 0xff; i < size; i++, mask <<= BITS_PER_UNIT) > > + for (i = 0, mask = 0xff; i < size; i++, mask <<= BITS_PER_MARKER) > > { > > uint64_t masked1, masked2; > > > > @@ -2084,17 +2091,17 @@ find_bswap_or_nop (gimple stmt, struct > > symbolic_number *n, bool *bswap) > > int rsize; > > uint64_t tmpn; > > > > - for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_UNIT, rsize++); > > + for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, > rsize++); > > n->range = rsize; > > } > > > > /* Zero out the extra bits of N and CMP*. */ > > - if (n->range < (int)sizeof (int64_t)) > > + if (n->range < (int) sizeof (int64_t)) > > { > > uint64_t mask; > > > > - mask = ((uint64_t)1 << (n->range * BITS_PER_UNIT)) - 1; > > - cmpxchg >>= (sizeof (int64_t) - n->range) * BITS_PER_UNIT; > > + mask = ((uint64_t) 1 << (n->range * BITS_PER_MARKER)) - 1; > > + cmpxchg >>= (64 / BITS_PER_MARKER - n->range) * > BITS_PER_MARKER; > > cmpnop &= mask; > > } > > > > Ok for trunk? > > > > Best regards, > > > > Thomas > > > > > > >