diff options
author | Thomas Preud'homme <thomas.preudhomme@arm.com> | 2016-11-14 18:55:05 +0000 |
---|---|---|
committer | Thomas Preud'homme <thopre01@gcc.gnu.org> | 2016-11-14 18:55:05 +0000 |
commit | bf166718a9252bc7f867cbbe4e7772bf731acb0e (patch) | |
tree | 79b8405f2e07fe96cbec3d3749ccad885c4f34b0 /gcc | |
parent | d32e1fd8b9e1263d50bb697e40d4d92ece54c439 (diff) | |
download | gcc-bf166718a9252bc7f867cbbe4e7772bf731acb0e.zip gcc-bf166718a9252bc7f867cbbe4e7772bf731acb0e.tar.gz gcc-bf166718a9252bc7f867cbbe4e7772bf731acb0e.tar.bz2 |
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 <thomas.preudhomme@arm.com>
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 66 |
2 files changed, 37 insertions, 37 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f1cbd8..f259470 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-11-14 Thomas Preud'homme <thomas.preudhomme@arm.com> + + * 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 <ubizjak@gmail.com> * 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 c315da8..b28c808 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)) |