https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70039
--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- Confirmed. The reason is that we really represent those initializers differently, one is a STRING_CST (handled) and one is a CONSTRUCTOR (not handled). memcpy expansion does src_str = c_getstr (src); /* If SRC is a string constant and block move would be done by pieces, we can avoid loading the string from memory and only stored the computed constants. */ if (src_str && CONST_INT_P (len_rtx) && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, CONST_CAST (char *, src_str), dest_align, false)) { dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), builtin_memcpy_read_str, CONST_CAST (char *, src_str), dest_align, false, 0); dest_mem = force_operand (XEXP (dest_mem, 0), target); dest_mem = convert_memory_address (ptr_mode, dest_mem); return dest_mem; which doesn't apply to the constructor case or any other non-string static constant.