Currently expand_constructor when it comes to BLKmode types, we store out the constructor to memory. But for the zero case, we could just use `const_int 0` instead for types who are less than or equal to BITS_PER_WORD. This is only valid if we expanding without a target.
This fixes the storing zeros of `char[3]` and `char[7]` into registers. Boostrapped and tested on x86_64-linux-gnu. Build and tested for aarch64-linux-gnu. PR middle-end/110459 gcc/ChangeLog: * expr.cc (expand_constructor): For expansion of `{}` without a target and the size is less than BITS_PER_WORD, just return the constant 0. gcc/testsuite/ChangeLog: * g++.target/aarch64/array-return-1.C: New test. * g++.target/i386/array-return-1.C: New test. Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com> --- gcc/expr.cc | 13 +++++++++++ .../g++.target/aarch64/array-return-1.C | 22 +++++++++++++++++++ .../g++.target/i386/array-return-1.C | 20 +++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 gcc/testsuite/g++.target/aarch64/array-return-1.C create mode 100644 gcc/testsuite/g++.target/i386/array-return-1.C diff --git a/gcc/expr.cc b/gcc/expr.cc index b3b46a26626..a230847e8da 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -9412,6 +9412,19 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier, return constructor; } + /* For expanding of `{}` (or all zeros) without a target + with a non addressable constant constructor which will + fit into an integral mode, just return the constant 0. */ + if (mode == BLKmode + && !TREE_ADDRESSABLE (exp) + && TREE_CONSTANT (exp) + && target == NULL_RTX + && modifier == EXPAND_NORMAL + && all_zeros_p (exp) + && tree_fits_uhwi_p (TYPE_SIZE (type)) + && tree_to_uhwi (TYPE_SIZE (type)) <= BITS_PER_WORD) + return const0_rtx; + /* If the CTOR is available in static storage and not mostly zeros and we can move it by pieces prefer to do so since that's usually more efficient than performing a series of diff --git a/gcc/testsuite/g++.target/aarch64/array-return-1.C b/gcc/testsuite/g++.target/aarch64/array-return-1.C new file mode 100644 index 00000000000..7c0aa480775 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/array-return-1.C @@ -0,0 +1,22 @@ +// { dg-do compile } +// { dg-options "-O2" } +// { dg-final { check-function-bodies "**" "" "" { target { le } } } } + +// PR middle-end/110459 + +/* +**_Z7sample2c: +** and w0, w0, 255 +** ret +*/ + +struct array { + char data[4]; +}; + +// There should be no adjustment to the stack +// { dg-final { scan-assembler-not "sp, sp," } } +auto sample2(char c) { + array buffer = {c, 0, 0, 0}; + return buffer; +} diff --git a/gcc/testsuite/g++.target/i386/array-return-1.C b/gcc/testsuite/g++.target/i386/array-return-1.C new file mode 100644 index 00000000000..f11905d01e5 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/array-return-1.C @@ -0,0 +1,20 @@ +// { dg-do compile } +// { dg-options "-O2" } +// { dg-final { check-function-bodies "**" "" "" { target { ! ia32 } } } } + +// PR middle-end/110459 + +/* +**_Z7sample2c: +** movzbl %dil, %eax +** ret +*/ + +struct array { + char data[4]; +}; + +array sample2(char c) { + array buffer = {c, 0, 0, 0}; + return buffer; +} -- 2.43.0