From: Thomas Preud'homme Date: Mon, 14 Nov 2016 18:55:05 +0000 (+0000) Subject: tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg and cmpnop in... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bf166718a9252bc7f867cbbe4e7772bf731acb0e;p=gcc.git tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg and cmpnop in two steps... 2016-11-14 Thomas Preud'homme gcc/ * tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg and cmpnop in two steps: first the ones not accessed in original gimple expression in a endian independent way and then the ones not accessed in the final result in an endian-specific way. (bswap_replace): Stop doing big endian adjustment. From-SVN: r242394 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f1cbd83e85..f259470e9fa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-11-14 Thomas Preud'homme + + * tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg + and cmpnop in two steps: first the ones not accessed in original gimple + expression in a endian independent way and then the ones not accessed + in the final result in an endian-specific way. + (bswap_replace): Stop doing big endian adjustment. + 2016-11-14 Uros Bizjak * config/i386/i386.md (*andndi3_doubleword): Merge operand constraints. diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index c315da88ce4..b28c808c554 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -2504,9 +2504,11 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit) static gimple * find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap) { - /* The number which the find_bswap_or_nop_1 result should match in order - to have a full byte swap. The number is shifted to the right - according to the size of the symbolic number before using it. */ + unsigned rsize; + uint64_t tmpn, mask; +/* The number which the find_bswap_or_nop_1 result should match in order + to have a full byte swap. The number is shifted to the right + according to the size of the symbolic number before using it. */ uint64_t cmpxchg = CMPXCHG; uint64_t cmpnop = CMPNOP; @@ -2527,28 +2529,38 @@ find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap) /* Find real size of result (highest non-zero byte). */ if (n->base_addr) - { - unsigned HOST_WIDE_INT rsize; - uint64_t tmpn; - - for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++); - if (BYTES_BIG_ENDIAN && n->range != rsize) - /* This implies an offset, which is currently not handled by - bswap_replace. */ - return NULL; - n->range = rsize; - } + for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++); + else + rsize = n->range; - /* Zero out the extra bits of N and CMP*. */ + /* Zero out the bits corresponding to untouched bytes in original gimple + expression. */ if (n->range < (int) sizeof (int64_t)) { - uint64_t mask; - mask = ((uint64_t) 1 << (n->range * BITS_PER_MARKER)) - 1; cmpxchg >>= (64 / BITS_PER_MARKER - n->range) * BITS_PER_MARKER; cmpnop &= mask; } + /* Zero out the bits corresponding to unused bytes in the result of the + gimple expression. */ + if (rsize < n->range) + { + if (BYTES_BIG_ENDIAN) + { + mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1; + cmpxchg &= mask; + cmpnop >>= (n->range - rsize) * BITS_PER_MARKER; + } + else + { + mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1; + cmpxchg >>= (n->range - rsize) * BITS_PER_MARKER; + cmpnop &= mask; + } + n->range = rsize; + } + /* A complete byte swap should make the symbolic number to start with the largest digit in the highest order byte. Unchanged symbolic number indicates a read with same endianness as target architecture. */ @@ -2636,26 +2648,6 @@ bswap_replace (gimple *cur_stmt, gimple *src_stmt, tree fndecl, HOST_WIDE_INT load_offset = 0; align = get_object_alignment (src); - /* If the new access is smaller than the original one, we need - to perform big endian adjustment. */ - if (BYTES_BIG_ENDIAN) - { - HOST_WIDE_INT bitsize, bitpos; - machine_mode mode; - int unsignedp, reversep, volatilep; - tree offset; - - get_inner_reference (src, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &reversep, &volatilep); - if (n->range < (unsigned HOST_WIDE_INT) bitsize) - { - load_offset = (bitsize - n->range) / BITS_PER_UNIT; - unsigned HOST_WIDE_INT l - = (load_offset * BITS_PER_UNIT) & (align - 1); - if (l) - align = least_bit_hwi (l); - } - } if (bswap && align < GET_MODE_ALIGNMENT (TYPE_MODE (load_type))