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