+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
--- /dev/null
+/* 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" } } */
- 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[],
tree alias_set;
tree vuse;
unsigned HOST_WIDE_INT range;
+ int n_ops;
};
#define BITS_PER_MARKER 8
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;
return NULL;
}
n->n = n1->n | n2->n;
+ n->n_ops = n1->n_ops + n2->n_ops;
return source_stmt;
}
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;
}
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);