From 1f1e8aed3afc08e9d70bba9110e289f7fa329453 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 17 Jul 2017 10:14:16 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 11 +++++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr81396.c | 25 ++++++++++++++++ gcc/tree-ssa-math-opts.c | 39 +++++++++++++++++++++++-- 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr81396.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 67b7ff12d95..f57ef041ab2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2017-07-17 Jakub Jelinek + + 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 PR target/81069 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 872d24e0109..67ffc3ef502 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-07-17 Jakub Jelinek + + PR tree-optimization/81396 + * gcc.dg/tree-ssa/pr81396.c: New test. + 2017-07-16 Eric Botcazou * gnat.dg/opt65.adb: New test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81396.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81396.c new file mode 100644 index 00000000000..9f4a08d1c22 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81396.c @@ -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" } } */ diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index c59dce08f44..7ac1659fa06 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -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); -- 2.30.2