https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89226
--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> --- That is because in copy1 it is a normal memcpy expansion. And, the generic move_by_pieces case is done in preference to target specific one. In i386.h we have: /* Max number of bytes we can move from memory to memory in one reasonably fast instruction. */ #define MOVE_MAX 16 /* MOVE_MAX_PIECES is the number of bytes at a time which we can move efficiently, as opposed to MOVE_MAX which is the maximum number of bytes we can move with a single instruction. ??? We should use TImode in 32-bit mode and use OImode or XImode if they are available. But since by_pieces_ninsns determines the widest mode with MAX_FIXED_MODE_SIZE, we can only use TImode in 64-bit mode. */ #define MOVE_MAX_PIECES \ ((TARGET_64BIT \ && TARGET_SSE2 \ && TARGET_SSE_UNALIGNED_LOAD_OPTIMAL \ && TARGET_SSE_UNALIGNED_STORE_OPTIMAL) \ ? GET_MODE_SIZE (TImode) : UNITS_PER_WORD) and in defaults.h /* MOVE_MAX_PIECES is the number of bytes at a time which we can move efficiently, as opposed to MOVE_MAX which is the maximum number of bytes we can move with a single instruction. */ #ifndef MOVE_MAX_PIECES #define MOVE_MAX_PIECES MOVE_MAX #endif /* STORE_MAX_PIECES is the number of bytes at a time that we can store efficiently. Due to internal GCC limitations, this is MOVE_MAX_PIECES limited by the number of bytes GCC can represent for an immediate constant. */ #ifndef STORE_MAX_PIECES #define STORE_MAX_PIECES MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT)) #endif /* Likewise for block comparisons. */ #ifndef COMPARE_MAX_PIECES #define COMPARE_MAX_PIECES MOVE_MAX_PIECES #endif #ifndef MAX_MOVE_MAX #define MAX_MOVE_MAX MOVE_MAX #endif