On Thu, Nov 16, 2017 at 5:21 PM, Nathan Froyd <[email protected]> wrote:
> Default-initialization of scalar arrays in C++ member initialization
> lists produced rather slow code, laboriously setting each element of the
> array to zero. It would be much faster to block-initialize the array,
> and that's what this patch does.
>
> The patch works for me, but I'm not sure if it's the best way to
> accomplish this. At least two other possibilities come to mind:
>
> 1) Detect this case in build_vec_init_expr and act as though the user
> wrote 'member{0}', which the front-end already produces efficient
> code for.
>
> 2) Detect this case in build_vec_init, but again, act as though the user
> wrote 'member{0}' and let everything proceed as normal.
> (Alternatively, handle this case prior to calling build_vec_init and
> pass different arguments to build_vec_init.)
>
> Opinions as to the best way forward here? I'm unsure of whether the
> code below is front-end friendly; I see in the gimple dumps that the
> solution below adds an extra CLOBBER on 'this' for 'member()', whereas
> 'member{0}' does not. It's possible that I'm missing something.
>
> Bootstrapped on x86_64-unknown-linux-gnu, no regressions.
>
> OK for trunk?
Ok. This is certainly the form the middle-end likes most.
Richard.
> -Nathan
>
> gcc/cp/
> PR c++/82888
> * init.c (build_vec_init): Handle default-initialization of array
> types.
>
> gcc/testsuite/
> PR c++/82888
> * g++.dg/init/pr82888.C: New.
>
> diff --git a/gcc/cp/init.c b/gcc/cp/init.c
> index c76460d..53d6133 100644
> --- a/gcc/cp/init.c
> +++ b/gcc/cp/init.c
> @@ -4038,6 +4038,15 @@ build_vec_init (tree base, tree maxindex, tree init,
> }
> }
>
> + /* Default-initialize scalar arrays directly. */
> + if (TREE_CODE (atype) == ARRAY_TYPE
> + && SCALAR_TYPE_P (TREE_TYPE (atype))
> + && !init)
> + {
> + gcc_assert (!from_array);
> + return build2 (MODIFY_EXPR, atype, base, build_constructor (atype,
> NULL));
> + }
> +
> /* If we have a braced-init-list or string constant, make sure that the
> array
> is big enough for all the initializers. */
> bool length_check = (init
> diff --git a/gcc/testsuite/g++.dg/init/pr82888.C
> b/gcc/testsuite/g++.dg/init/pr82888.C
> new file mode 100644
> index 0000000..9225e23
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/init/pr82888.C
> @@ -0,0 +1,18 @@
> +// { dg-do compile }
> +// { dg-options "-fdump-tree-gimple" }
> +
> +class A
> +{
> +public:
> + A();
> +
> +private:
> + unsigned char mStorage[4096];
> +};
> +
> +A::A()
> + : mStorage()
> +{}
> +
> +// { dg-final { scan-tree-dump "this->mStorage = {}" "gimple" } }
> +// { dg-final { scan-tree-dump-not "&this->mStorage" "gimple" } }