summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Preud'homme <thomas.preudhomme@arm.com>2016-11-14 18:55:05 +0000
committerThomas Preud'homme <thopre01@gcc.gnu.org>2016-11-14 18:55:05 +0000
commitbf166718a9252bc7f867cbbe4e7772bf731acb0e (patch)
tree79b8405f2e07fe96cbec3d3749ccad885c4f34b0
parentd32e1fd8b9e1263d50bb697e40d4d92ece54c439 (diff)
downloadgcc-bf166718a9252bc7f867cbbe4e7772bf731acb0e.tar.gz
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/tree-ssa-math-opts.c66
2 files changed, 37 insertions, 37 deletions
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 <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 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))