Patchwork Stop looping in move_by_pieces loops when there's no more data to process

login
register
mail settings
Submitter Tom de Vries
Date Oct. 16, 2012, 6:40 a.m.
Message ID <507D0155.6090008@mentor.com>
Download mbox | patch
Permalink /patch/191729/
State New
Headers show

Comments

Tom de Vries - Oct. 16, 2012, 6:40 a.m.
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:
...
...

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  <tom@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.
Jakub Jelinek - Oct. 16, 2012, 8:03 a.m.
On Tue, Oct 16, 2012 at 08:40:21AM +0200, Tom de Vries wrote:
> 2012-10-16  Tom de Vries  <tom@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.

Okay.

	Jakub

Patch

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);