On Tue, 11 Jun 2019, Jason Merrill wrote: > On Tue, Jun 11, 2019, 6:45 AM Richard Biener <rguent...@suse.de> wrote: > > > > > The following fixes the documented(!) quadraticness in > > split_nonconstant_init_1 by simply marking to be removed > > constructor elements and doing that in a second run over > > the constructor. > > > > More micro-optimizing would be possible by recording the > > first removed element index and special-casing removing > > of a single element. If you think that's worth the extra > > complexity I can work on that (hopefully the case we > > increase num_split_elts but not actually split is a bug...). > > > > Bootstrap / regtest running on x86_64-unknown-linux-gnu. > > > > OK if that passes? > > > > Ok, thanks.
Installed. Below is the simplest variant re-adding optimized handling of single-element removal. Note the second hunk which moves the num_split_elts increment so it doesn't happen when split_nonconstant_init_1 returns false. Bootstrapped and tested on x86_64-unknown-linux-gnu. OK? Richard. 2019-06-12 Richard Biener <rguent...@suse.de> PR c++/90801 * typeck2.c (split_nonconstant_init_1): Properly count num_split_elts, optimize single constructor elt removal. Index: gcc/cp/typeck2.c =================================================================== --- gcc/cp/typeck2.c (revision 272177) +++ gcc/cp/typeck2.c (working copy) @@ -603,7 +603,7 @@ cxx_incomplete_type_error (location_t lo static bool split_nonconstant_init_1 (tree dest, tree init) { - unsigned HOST_WIDE_INT idx, tidx; + unsigned HOST_WIDE_INT idx, tidx = HOST_WIDE_INT_M1U; tree field_index, value; tree type = TREE_TYPE (dest); tree inner_type = NULL; @@ -657,9 +657,13 @@ split_nonconstant_init_1 (tree dest, tre if (!split_nonconstant_init_1 (sub, value)) complete_p = false; else - /* Mark element for removal. */ - CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE; - num_split_elts++; + { + /* Mark element for removal. */ + CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE; + if (idx < tidx) + tidx = idx; + num_split_elts++; + } } else if (!initializer_constant_valid_p (value, inner_type)) { @@ -668,6 +672,8 @@ split_nonconstant_init_1 (tree dest, tre /* Mark element for removal. */ CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE; + if (idx < tidx) + tidx = idx; if (TREE_CODE (field_index) == RANGE_EXPR) { @@ -705,17 +711,18 @@ split_nonconstant_init_1 (tree dest, tre num_split_elts++; } } - if (num_split_elts != 0) + if (num_split_elts == 1) + CONSTRUCTOR_ELTS (init)->ordered_remove (tidx); + else if (num_split_elts > 1) { /* Perform the delayed ordered removal of non-constant elements we split out. */ - for (tidx = 0, idx = 0; idx < CONSTRUCTOR_NELTS (init); ++idx) + for (idx = tidx; idx < CONSTRUCTOR_NELTS (init); ++idx) if (CONSTRUCTOR_ELT (init, idx)->index == NULL_TREE) ; else { - if (tidx != idx) - *CONSTRUCTOR_ELT (init, tidx) = *CONSTRUCTOR_ELT (init, idx); + *CONSTRUCTOR_ELT (init, tidx) = *CONSTRUCTOR_ELT (init, idx); ++tidx; } vec_safe_truncate (CONSTRUCTOR_ELTS (init), tidx);