On Tue, May 31, 2022 at 5:37 AM Takayuki 'January June' Suwa via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > Hi all, > > In some targets, initialization code for char array may be split into two > parts even if the initialization consists of all zeros: > > /* example */ > extern void foo(char*); > void test(void) { > char a[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; > foo(a); > } > > ;; Xtensa (xtensa-lx106) > .LC0: > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .zero 246 > test: > movi a9, 0x110 > sub sp, sp, a9 > l32r a3, .LC1 > movi.n a4, 0xa > mov.n a2, sp > s32i a0, sp, 268 > call0 memcpy > movi a4, 0xf6 > movi.n a3, 0 > addi.n a2, sp, 10 > call0 memset > mov.n a2, sp > call0 foo > l32i a0, sp, 268 > movi a9, 0x110 > add.n sp, sp, a9 > ret.n > > ;; H8/300 (-mh -mint32) > .LC0: > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .string "" > .zero 246 > _test: > sub.l #256,er7 > sub.l er2,er2 > add.b #10,r2l > mov.l #.LC0,er1 > mov.l er7,er0 > jsr @_memcpy > sub.l er2,er2 > add.b #246,r2l > sub.l er1,er1 > sub.l er0,er0 > add.b #10,r0l > add.l er7,er0 > jsr @_memset > mov.l er7,er0 > jsr @_foo > add.l #256,er7 > rts > > i386 target (both 32 and 64bit) does not show such behavior. > > gcc/ChangeLog: > > * expr.cc (store_expr): Add check if the initialization content > consists of all zeros. > --- > gcc/expr.cc | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/gcc/expr.cc b/gcc/expr.cc > index 7197996cec7..f94310dc7b9 100644 > --- a/gcc/expr.cc > +++ b/gcc/expr.cc > @@ -6015,6 +6015,7 @@ store_expr (tree exp, rtx target, int call_param_p, > rtx dest_mem; > tree str = TREE_CODE (exp) == STRING_CST > ? exp : TREE_OPERAND (TREE_OPERAND (exp, 0), 0); > + char ch; > > exp_len = int_expr_size (exp); > if (exp_len <= 0) > @@ -6032,6 +6033,12 @@ store_expr (tree exp, rtx target, int call_param_p, > } > > str_copy_len = TREE_STRING_LENGTH (str); > + /* If str contains only zeroes, no need to store to target. */ > + ch = 0; > + for (HOST_WIDE_INT i = 0; i < str_copy_len; ++i) > + ch |= TREE_STRING_POINTER (str)[i]; > + if (ch == 0) > + str_copy_len = 0;
Not sure if I decipher the current code correctly but maybe we instead want to prune str_copy_len from the end for trailing \0 bytes instead of just special-casing all-zero initializers? > if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0) > { > str_copy_len += STORE_MAX_PIECES - 1; > -- > 2.20.1