aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2018-12-14 20:37:38 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2018-12-14 20:37:38 +0100
commit0fca07e31dc85bea3b1d669d7cc1d51d22192335 (patch)
tree662864e452bc122b8f1cff2569205e4a587d86c0 /gcc/gimplify.c
parentfaa9232da39587b27b46341667d6d415d2af9280 (diff)
downloadgcc-0fca07e31dc85bea3b1d669d7cc1d51d22192335.zip
gcc-0fca07e31dc85bea3b1d669d7cc1d51d22192335.tar.gz
gcc-0fca07e31dc85bea3b1d669d7cc1d51d22192335.tar.bz2
re PR c++/82294 (Array of objects with constexpr constructors initialized from space-inefficient memory image)
PR c++/82294 PR c++/87436 * expr.h (categorize_ctor_elements): Add p_unique_nz_elts argument. * expr.c (categorize_ctor_elements_1): Likewise. Compute it like p_nz_elts, except don't multiply it by mult. Adjust recursive call. Fix up COMPLEX_CST handling. (categorize_ctor_elements): Add p_unique_nz_elts argument, initialize it and pass it through to categorize_ctor_elements_1. (mostly_zeros_p, all_zeros_p): Adjust categorize_ctor_elements callers. * gimplify.c (gimplify_init_constructor): Likewise. Don't force ctor into readonly data section if num_unique_nonzero_elements is smaller or equal to 1/8 of num_nonzero_elements and size is >= 64 bytes. * g++.dg/tree-ssa/pr82294.C: New test. * g++.dg/tree-ssa/pr87436.C: New test. From-SVN: r267143
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 9022ef8..465d138 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4778,7 +4778,15 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
{
struct gimplify_init_ctor_preeval_data preeval_data;
HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
+ HOST_WIDE_INT num_unique_nonzero_elements;
bool cleared, complete_p, valid_const_initializer;
+ /* Use readonly data for initializers of this or smaller size
+ regardless of the num_nonzero_elements / num_unique_nonzero_elements
+ ratio. */
+ const HOST_WIDE_INT min_unique_size = 64;
+ /* If num_nonzero_elements / num_unique_nonzero_elements ratio
+ is smaller than this, use readonly data. */
+ const int unique_nonzero_ratio = 8;
/* Aggregate types must lower constructors to initialization of
individual elements. The exception is that a CONSTRUCTOR node
@@ -4795,6 +4803,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
can only do so if it known to be a valid constant initializer. */
valid_const_initializer
= categorize_ctor_elements (ctor, &num_nonzero_elements,
+ &num_unique_nonzero_elements,
&num_ctor_elements, &complete_p);
/* If a const aggregate variable is being initialized, then it
@@ -4803,7 +4812,15 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
&& num_nonzero_elements > 1
&& TREE_READONLY (object)
&& VAR_P (object)
- && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)))
+ && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object))
+ /* For ctors that have many repeated nonzero elements
+ represented through RANGE_EXPRs, prefer initializing
+ those through runtime loops over copies of large amounts
+ of data from readonly data section. */
+ && (num_unique_nonzero_elements
+ > num_nonzero_elements / unique_nonzero_ratio
+ || ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
+ <= (unsigned HOST_WIDE_INT) min_unique_size)))
{
if (notify_temp_creation)
return GS_ERROR;
@@ -4896,6 +4913,13 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
is so large as to make individual moves inefficient. */
if (size > 0
&& num_nonzero_elements > 1
+ /* For ctors that have many repeated nonzero elements
+ represented through RANGE_EXPRs, prefer initializing
+ those through runtime loops over copies of large amounts
+ of data from readonly data section. */
+ && (num_unique_nonzero_elements
+ > num_nonzero_elements / unique_nonzero_ratio
+ || size <= min_unique_size)
&& (size < num_nonzero_elements
|| !can_move_by_pieces (size, align)))
{