Jakub, I've noticed that the move_by_pieces loops keep iterating after there's no more data to process.
I've added this assert to trigger an example in a gcc build: ... Index: src/gcc/expr.c =================================================================== --- src/gcc/expr.c (revision 191792) +++ src/gcc/expr.c (working copy) @@ -1031,6 +1031,8 @@ move_by_pieces_ninsns (unsigned HOST_WID enum machine_mode mode; enum insn_code icode; + gcc_assert (l > 0); + mode = widest_int_mode_for_size (max_size); if (mode == VOIDmode) ... It triggers while compiling __gcov_execle. After l is 0, we still enter the loop until we run out of modes to try: ... Breakpoint 2, move_by_pieces_ninsns (l=24, align=64, max_size=9) at expr.c:1025 1025 unsigned HOST_WIDE_INT n_insns = 0; (gdb) n 1027 align = alignment_for_piecewise_move (MOVE_MAX_PIECES, align); (gdb) 1029 while (max_size > 1) (gdb) 1034 gcc_assert (l > 0); (gdb) 1036 mode = widest_int_mode_for_size (max_size); (gdb) 1038 if (mode == VOIDmode) (gdb) 1041 icode = optab_handler (mov_optab, mode); (gdb) 1042 if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode)) (gdb) 1043 n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode); (gdb) 1045 max_size = GET_MODE_SIZE (mode); (gdb) 1029 while (max_size > 1) (gdb) p l $3 = 0 (gdb) p max_size $4 = 8 (gdb) n 1034 gcc_assert (l > 0); (gdb) ... This patch fixes that in this loop, and other move_by_pieces loops. Bootstrapped and reg-tested on x86_64. OK for trunk? Thanks, - Tom 2012-10-16 Tom de Vries <t...@codesourcery.com> * expr.c (move_by_pieces, move_by_pieces_ninsns, can_store_by_pieces) (store_by_pieces_1): Don't enter loop when no more data is left.
Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 191792) +++ gcc/expr.c (working copy) @@ -966,7 +966,7 @@ move_by_pieces (rtx to, rtx from, unsign /* First move what we can in the largest integer mode, then go to successively smaller modes. */ - while (max_size > 1) + while (max_size > 1 && data.len > 0) { enum machine_mode mode = widest_int_mode_for_size (max_size); @@ -1026,7 +1026,7 @@ move_by_pieces_ninsns (unsigned HOST_WID align = alignment_for_piecewise_move (MOVE_MAX_PIECES, align); - while (max_size > 1) + while (max_size > 1 && l > 0) { enum machine_mode mode; enum insn_code icode; @@ -2417,7 +2417,7 @@ can_store_by_pieces (unsigned HOST_WIDE_ { l = len; max_size = STORE_MAX_PIECES + 1; - while (max_size > 1) + while (max_size > 1 && l > 0) { mode = widest_int_mode_for_size (max_size); @@ -2612,7 +2612,7 @@ store_by_pieces_1 (struct store_by_piece /* First store what we can in the largest integer mode, then go to successively smaller modes. */ - while (max_size > 1) + while (max_size > 1 && data->len > 0) { enum machine_mode mode = widest_int_mode_for_size (max_size);