Hi, the patch below is an attempt to deal with PR 80293 as non-invasively as possible. Basically, it switches off total SRA scalarization of any local aggregates which contains an array of elements that have one byte (or less).
The logic behind this is that accessing such arrays element-wise usually results in poor code and that such char arrays are often used for non-statically-typed content anyway, and we do not want to copy that byte per byte. Alan, do you think this could impact your constant pool scalarization too severely? Richi, if you or Alan does not object in a few days, I'd like to commit this in time for gcc7. It has passed bootstrap and testing on x86_64-linux (but the constant pool SRA work was aimed primarily at ARM). Thanks, Martin 2017-04-10 Martin Jambor <mjam...@suse.cz> * tree-sra.c (scalarizable_type_p): Make char arrays not totally scalarizable. testsuite/ * g++.dg/tree-ssa/pr80293.C: New test. --- gcc/testsuite/g++.dg/tree-ssa/pr80293.C | 45 +++++++++++++++++++++++++++++++++ gcc/tree-sra.c | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr80293.C diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr80293.C b/gcc/testsuite/g++.dg/tree-ssa/pr80293.C new file mode 100644 index 00000000000..7faf35ae983 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr80293.C @@ -0,0 +1,45 @@ +// { dg-do compile } +// { dg-options "-O2 -std=gnu++11 -fdump-tree-optimized" } */ + +#include <array> + +// Return a copy of the underlying memory of an arbitrary value. +template < + typename T, + typename = typename std::enable_if<std::is_trivially_copyable<T>::value>::type +> +auto getMem( + T const & value +) -> std::array<char, sizeof(T)> { + auto ret = std::array<char, sizeof(T)>{}; + __builtin_memcpy(ret.data(), &value, sizeof(T)); + return ret; +} + +template < + typename T, + typename = typename std::enable_if<std::is_trivially_copyable<T>::value>::type +> +auto fromMem( + std::array<char, sizeof(T)> const & buf +) -> T { + auto ret = T{}; + __builtin_memcpy(&ret, buf.data(), sizeof(T)); + return ret; +} + +double foo1(std::uint64_t arg) { + return fromMem<double>(getMem(arg)); +} + +double foo2(std::uint64_t arg) { + return *reinterpret_cast<double*>(&arg); +} + +double foo3(std::uint64_t arg) { + double ret; + __builtin_memcpy(&ret, &arg, sizeof(arg)); + return ret; +} + +// { dg-final { scan-tree-dump-not "BIT_FIELD_REF" "optimized" } } diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 02453d3ed9a..cbe9e862a2f 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -981,7 +981,7 @@ scalarizable_type_p (tree type) if (TYPE_DOMAIN (type) == NULL_TREE || !tree_fits_shwi_p (TYPE_SIZE (type)) || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (type))) - || (tree_to_shwi (TYPE_SIZE (TREE_TYPE (type))) <= 0) + || (tree_to_shwi (TYPE_SIZE (TREE_TYPE (type))) <= BITS_PER_UNIT) || !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type)))) return false; if (tree_to_shwi (TYPE_SIZE (type)) == 0 -- 2.12.0