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.

Jason


> Thanks,
> Richard.
>
> 2019-06-11  Richard Biener  <rguent...@suse.de>
>
>         PR c++/90801
>         * typeck2.c (split_nonconstant_init_1): Avoid ordered remove
>         from CONSTRUCTOR by marking to remove elements and doing all
>         of them in a O(n) scan.
>
> Index: gcc/cp/typeck2.c
> ===================================================================
> --- gcc/cp/typeck2.c    (revision 272147)
> +++ 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;
> +  unsigned HOST_WIDE_INT idx, tidx;
>    tree field_index, value;
>    tree type = TREE_TYPE (dest);
>    tree inner_type = NULL;
> @@ -657,7 +657,8 @@ split_nonconstant_init_1 (tree dest, tre
>               if (!split_nonconstant_init_1 (sub, value))
>                 complete_p = false;
>               else
> -               CONSTRUCTOR_ELTS (init)->ordered_remove (idx--);
> +               /* Mark element for removal.  */
> +               CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE;
>               num_split_elts++;
>             }
>           else if (!initializer_constant_valid_p (value, inner_type))
> @@ -665,15 +666,8 @@ split_nonconstant_init_1 (tree dest, tre
>               tree code;
>               tree sub;
>
> -             /* FIXME: Ordered removal is O(1) so the whole function is
> -                worst-case quadratic. This could be fixed using an aside
> -                bitmap to record which elements must be removed and remove
> -                them all at the same time. Or by merging
> -                split_non_constant_init into
> process_init_constructor_array,
> -                that is separating constants from non-constants while
> building
> -                the vector.  */
> -             CONSTRUCTOR_ELTS (init)->ordered_remove (idx);
> -             --idx;
> +             /* Mark element for removal.  */
> +             CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE;
>
>               if (TREE_CODE (field_index) == RANGE_EXPR)
>                 {
> @@ -711,6 +705,21 @@ split_nonconstant_init_1 (tree dest, tre
>               num_split_elts++;
>             }
>         }
> +      if (num_split_elts != 0)
> +       {
> +         /* Perform the delayed ordered removal of non-constant elements
> +            we split out.  */
> +         for (tidx = 0, idx = 0; 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);
> +               ++tidx;
> +             }
> +         vec_safe_truncate (CONSTRUCTOR_ELTS (init), tidx);
> +       }
>        break;
>
>      case VECTOR_TYPE:
>

Reply via email to