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;
       if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0)
        {
          str_copy_len += STORE_MAX_PIECES - 1;
--
2.20.1

Reply via email to