re PR tree-optimization/81396 (Optimization of reading Little-Endian 64-bit number with portable code has a regression)
PR tree-optimization/81396 * tree-ssa-math-opts.c (struct symbolic_number): Add n_ops field. (init_symbolic_number): Initialize it to 1. (perform_symbolic_merge): Add n_ops from both operands into the new n_ops. (find_bswap_or_nop): Don't consider n->n == cmpnop computations without base_addr as useless if they need more than one operation. (bswap_replace): Handle !bswap case for NULL base_addr. * gcc.dg/tree-ssa/pr81396.c: New test. From-SVN: r250257
This commit is contained in:
parent
ed9091b270
commit
1f1e8aed3a
4 changed files with 78 additions and 2 deletions
|
@ -1,3 +1,14 @@
|
|||
2017-07-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/81396
|
||||
* tree-ssa-math-opts.c (struct symbolic_number): Add n_ops field.
|
||||
(init_symbolic_number): Initialize it to 1.
|
||||
(perform_symbolic_merge): Add n_ops from both operands into the new
|
||||
n_ops.
|
||||
(find_bswap_or_nop): Don't consider n->n == cmpnop computations
|
||||
without base_addr as useless if they need more than one operation.
|
||||
(bswap_replace): Handle !bswap case for NULL base_addr.
|
||||
|
||||
2017-07-17 Tom de Vries <tom@codesourcery.com>
|
||||
|
||||
PR target/81069
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2017-07-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/81396
|
||||
* gcc.dg/tree-ssa/pr81396.c: New test.
|
||||
|
||||
2017-07-16 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gnat.dg/opt65.adb: New test.
|
||||
|
|
25
gcc/testsuite/gcc.dg/tree-ssa/pr81396.c
Normal file
25
gcc/testsuite/gcc.dg/tree-ssa/pr81396.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* PR tree-optimization/81396 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
uint64_t
|
||||
foo (uint64_t word)
|
||||
{
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_LONG_LONG__ == 8
|
||||
const unsigned char *const ptr = (const unsigned char *) &word;
|
||||
return ((uint64_t) ptr[0]
|
||||
| ((uint64_t) ptr[1] << 8)
|
||||
| ((uint64_t) ptr[2] << (8 * 2))
|
||||
| ((uint64_t) ptr[3] << (8 * 3))
|
||||
| ((uint64_t) ptr[4] << (8 * 4))
|
||||
| ((uint64_t) ptr[5] << (8 * 5))
|
||||
| ((uint64_t) ptr[6] << (8 * 6))
|
||||
| ((uint64_t) ptr[7] << (8 * 7)));
|
||||
#else
|
||||
return word;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "return word_\[0-9]*\\(D\\);" "optimized" } } */
|
|
@ -1946,7 +1946,9 @@ make_pass_cse_sincos (gcc::context *ctxt)
|
|||
- a range which gives the difference between the highest and lowest accessed
|
||||
memory location to make such a symbolic number;
|
||||
- the address SRC of the source element of lowest address as a convenience
|
||||
to easily get BASE_ADDR + offset + lowest bytepos.
|
||||
to easily get BASE_ADDR + offset + lowest bytepos;
|
||||
- number of expressions N_OPS bitwise ored together to represent
|
||||
approximate cost of the computation.
|
||||
|
||||
Note 1: the range is different from size as size reflects the size of the
|
||||
type of the current expression. For instance, for an array char a[],
|
||||
|
@ -1968,6 +1970,7 @@ struct symbolic_number {
|
|||
tree alias_set;
|
||||
tree vuse;
|
||||
unsigned HOST_WIDE_INT range;
|
||||
int n_ops;
|
||||
};
|
||||
|
||||
#define BITS_PER_MARKER 8
|
||||
|
@ -2083,6 +2086,7 @@ init_symbolic_number (struct symbolic_number *n, tree src)
|
|||
return false;
|
||||
n->range = size;
|
||||
n->n = CMPNOP;
|
||||
n->n_ops = 1;
|
||||
|
||||
if (size < 64 / BITS_PER_MARKER)
|
||||
n->n &= ((uint64_t) 1 << (size * BITS_PER_MARKER)) - 1;
|
||||
|
@ -2293,6 +2297,7 @@ perform_symbolic_merge (gimple *source_stmt1, struct symbolic_number *n1,
|
|||
return NULL;
|
||||
}
|
||||
n->n = n1->n | n2->n;
|
||||
n->n_ops = n1->n_ops + n2->n_ops;
|
||||
|
||||
return source_stmt;
|
||||
}
|
||||
|
@ -2588,7 +2593,7 @@ find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap)
|
|||
return NULL;
|
||||
|
||||
/* Useless bit manipulation performed by code. */
|
||||
if (!n->base_addr && n->n == cmpnop)
|
||||
if (!n->base_addr && n->n == cmpnop && n->n_ops == 1)
|
||||
return NULL;
|
||||
|
||||
n->range *= BITS_PER_UNIT;
|
||||
|
@ -2747,6 +2752,36 @@ bswap_replace (gimple *cur_stmt, gimple *ins_stmt, tree fndecl,
|
|||
}
|
||||
src = val_tmp;
|
||||
}
|
||||
else if (!bswap)
|
||||
{
|
||||
gimple *g;
|
||||
if (!useless_type_conversion_p (TREE_TYPE (tgt), TREE_TYPE (src)))
|
||||
{
|
||||
if (!is_gimple_val (src))
|
||||
return false;
|
||||
g = gimple_build_assign (tgt, NOP_EXPR, src);
|
||||
}
|
||||
else
|
||||
g = gimple_build_assign (tgt, src);
|
||||
if (n->range == 16)
|
||||
nop_stats.found_16bit++;
|
||||
else if (n->range == 32)
|
||||
nop_stats.found_32bit++;
|
||||
else
|
||||
{
|
||||
gcc_assert (n->range == 64);
|
||||
nop_stats.found_64bit++;
|
||||
}
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (dump_file,
|
||||
"%d bit reshuffle in target endianness found at: ",
|
||||
(int) n->range);
|
||||
print_gimple_stmt (dump_file, cur_stmt, 0);
|
||||
}
|
||||
gsi_replace (&gsi, g, true);
|
||||
return true;
|
||||
}
|
||||
else if (TREE_CODE (src) == BIT_FIELD_REF)
|
||||
src = TREE_OPERAND (src, 0);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue