Message ID | 8f71494f-c3c7-e782-6e57-281eb4c8a393@yahoo.co.jp |
---|---|
State | New |
Headers | show |
Series | expr.cc: Optimize if char array initialization consists of all zeros | expand |
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
On 5/30/2022 9:35 PM, Takayuki 'January June' Suwa via Gcc-patches 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. It's not entirely clear what you're trying to accomplish. Is it the .zero which allocates space in the .rodata you're trying to remove? If so, it looks like that is already addressed on the trunk to me (I checked H8 with and without optimization). jeff
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; if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0) { str_copy_len += STORE_MAX_PIECES - 1;