Commit bf166718 by Thomas Preud'homme Committed by Thomas Preud'homme

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
parent d32e1fd8
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> 2016-11-14 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (*andndi3_doubleword): Merge operand constraints. * config/i386/i386.md (*andndi3_doubleword): Merge operand constraints.
...@@ -2504,9 +2504,11 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit) ...@@ -2504,9 +2504,11 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit)
static gimple * static gimple *
find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap) 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 unsigned rsize;
to have a full byte swap. The number is shifted to the right uint64_t tmpn, mask;
according to the size of the symbolic number before using it. */ /* 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 cmpxchg = CMPXCHG;
uint64_t cmpnop = CMPNOP; uint64_t cmpnop = CMPNOP;
...@@ -2527,28 +2529,38 @@ find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap) ...@@ -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). */ /* Find real size of result (highest non-zero byte). */
if (n->base_addr) if (n->base_addr)
{ for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
unsigned HOST_WIDE_INT rsize; else
uint64_t tmpn; rsize = n->range;
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;
}
/* 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)) if (n->range < (int) sizeof (int64_t))
{ {
uint64_t mask;
mask = ((uint64_t) 1 << (n->range * BITS_PER_MARKER)) - 1; mask = ((uint64_t) 1 << (n->range * BITS_PER_MARKER)) - 1;
cmpxchg >>= (64 / BITS_PER_MARKER - n->range) * BITS_PER_MARKER; cmpxchg >>= (64 / BITS_PER_MARKER - n->range) * BITS_PER_MARKER;
cmpnop &= mask; 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 /* A complete byte swap should make the symbolic number to start with
the largest digit in the highest order byte. Unchanged symbolic the largest digit in the highest order byte. Unchanged symbolic
number indicates a read with same endianness as target architecture. */ number indicates a read with same endianness as target architecture. */
...@@ -2636,26 +2648,6 @@ bswap_replace (gimple *cur_stmt, gimple *src_stmt, tree fndecl, ...@@ -2636,26 +2648,6 @@ bswap_replace (gimple *cur_stmt, gimple *src_stmt, tree fndecl,
HOST_WIDE_INT load_offset = 0; HOST_WIDE_INT load_offset = 0;
align = get_object_alignment (src); 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 if (bswap
&& align < GET_MODE_ALIGNMENT (TYPE_MODE (load_type)) && align < GET_MODE_ALIGNMENT (TYPE_MODE (load_type))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment