[PR 80293] Dont totally-scalarize char arrays

2017-05-31  Martin Jambor  <mjambor@suse.cz>

        Backport from mainline
        2017-04-24  Martin Jambor  <mjambor@suse.cz>

        PR tree-optimization/80293
        * tree-sra.c (scalarizable_type_p): New parameter const_decl, make
        char arrays not totally scalarizable if it is false.
        (analyze_all_variable_accesses): Pass correct value in the new
        parameter.  Add a statistics counter.

testsuite/
        * g++.dg/tree-ssa/pr80293.C: New test.

From-SVN: r248724
This commit is contained in:
Martin Jambor 2017-05-31 10:45:23 +02:00 committed by Martin Jambor
parent 23558e4988
commit 7a928bc1d7
4 changed files with 81 additions and 6 deletions

View File

@ -1,3 +1,14 @@
2017-05-31 Martin Jambor <mjambor@suse.cz>
Backport from mainline
2017-04-24 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/80293
* tree-sra.c (scalarizable_type_p): New parameter const_decl, make
char arrays not totally scalarizable if it is false.
(analyze_all_variable_accesses): Pass correct value in the new
parameter. Add a statistics counter.
2017-05-30 Max Filippov <jcmvbkbc@gmail.com>
Backport from mainline

View File

@ -1,3 +1,11 @@
2017-05-31 Martin Jambor <mjambor@suse.cz>
Backport from mainline
2017-04-24 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/80293
* g++.dg/tree-ssa/pr80293.C: New test.
2017-05-29 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
Backport from mainline

View File

@ -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" } }

View File

@ -949,10 +949,12 @@ create_access (tree expr, gimple *stmt, bool write)
/* Return true iff TYPE is scalarizable - i.e. a RECORD_TYPE or fixed-length
ARRAY_TYPE with fields that are either of gimple register types (excluding
bit-fields) or (recursively) scalarizable types. */
bit-fields) or (recursively) scalarizable types. CONST_DECL must be true if
we are considering a decl from constant pool. If it is false, char arrays
will be refused. */
static bool
scalarizable_type_p (tree type)
scalarizable_type_p (tree type, bool const_decl)
{
gcc_assert (!is_gimple_reg_type (type));
if (type_contains_placeholder_p (type))
@ -970,7 +972,7 @@ scalarizable_type_p (tree type)
return false;
if (!is_gimple_reg_type (ft)
&& !scalarizable_type_p (ft))
&& !scalarizable_type_p (ft, const_decl))
return false;
}
@ -978,10 +980,16 @@ scalarizable_type_p (tree type)
case ARRAY_TYPE:
{
HOST_WIDE_INT min_elem_size;
if (const_decl)
min_elem_size = 0;
else
min_elem_size = BITS_PER_UNIT;
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))) <= min_elem_size)
|| !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
return false;
if (tree_to_shwi (TYPE_SIZE (type)) == 0
@ -995,7 +1003,7 @@ scalarizable_type_p (tree type)
tree elem = TREE_TYPE (type);
if (!is_gimple_reg_type (elem)
&& !scalarizable_type_p (elem))
&& !scalarizable_type_p (elem, const_decl))
return false;
return true;
}
@ -2660,13 +2668,16 @@ analyze_all_variable_accesses (void)
{
tree var = candidate (i);
if (VAR_P (var) && scalarizable_type_p (TREE_TYPE (var)))
if (VAR_P (var) && scalarizable_type_p (TREE_TYPE (var),
constant_decl_p (var)))
{
if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var)))
<= max_scalarization_size)
{
create_total_scalarization_access (var);
completely_scalarize (var, TREE_TYPE (var), 0, var);
statistics_counter_event (cfun,
"Totally-scalarized aggregates", 1);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Will attempt to totally scalarize ");