jump buglet

Jeffrey A Law law@cygnus.com
Mon Nov 1 23:23:00 GMT 1999


Mark's change to use xmalloc instead of alloca exposed a latent bug in the
jump optimizer.

Compiling compile/950124-1.c on the PA with -O2 would get a segfault.

The problem was we stored out of the bounds of loop_number_loop_cont
in find_and_verify_loops because the loop notes were scrogged by the jump
optimizer.  The out of bounds store stomped on malloc's data structures
causing a segfault when we tried to free loop_number_loop_ends.

loop.c assumes that we'll have

  LOOP_BEG
  LOOP_CONT [optional ]
  LOOP_END


jump presented us with

  LOOP_BEG
  LOOP_END
  LOOP_CONT
  
The solution (of course) is to not muck up the note order.

	* jump.c (jump_optimize_1): Also move LOOP_VTOP and LOOP_CONT
	notes when presented with "if (foo) break; end_of_loop" and
	the break sequence gets moved out of the loop.

Index: jump.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/jump.c,v
retrieving revision 1.87
diff -c -3 -p -r1.87 jump.c
*** jump.c	1999/11/01 23:19:44	1.87
--- jump.c	1999/11/02 07:14:24
*************** jump_optimize_1 (f, cross_jump, noop_mov
*** 2084,2106 ****
  			NEXT_INSN (range1end) = range2after;
  			PREV_INSN (range2after) = range1end;
  
! 			/* Check for a loop end note between the end of
  			   range2, and the next code label.  If there is one,
  			   then what we have really seen is
  			   if (foo) break; end_of_loop;
  			   and moved the break sequence outside the loop.
! 			   We must move the LOOP_END note to where the
! 			   loop really ends now, or we will confuse loop
! 			   optimization.  Stop if we find a LOOP_BEG note
! 			   first, since we don't want to move the LOOP_END
! 			   note in that case.  */
  			for (;range2after != label2; range2after = rangenext)
  			  {
  			    rangenext = NEXT_INSN (range2after);
  			    if (GET_CODE (range2after) == NOTE)
  			      {
! 				if (NOTE_LINE_NUMBER (range2after)
! 				    == NOTE_INSN_LOOP_END)
  				  {
  				    NEXT_INSN (PREV_INSN (range2after))
  				      = rangenext;
--- 2084,2108 ----
  			NEXT_INSN (range1end) = range2after;
  			PREV_INSN (range2after) = range1end;
  
! 			/* Check for loop notes between the end of
  			   range2, and the next code label.  If there is one,
  			   then what we have really seen is
  			   if (foo) break; end_of_loop;
  			   and moved the break sequence outside the loop.
! 			   We must move LOOP_END, LOOP_VTOP and LOOP_CONT
! 			   notes (in order) to where the loop really ends now,
! 			   or we will confuse loop optimization.  Stop if we
! 			   find a LOOP_BEG note first, since we don't want to
! 			   move the notes in that case.  */
  			for (;range2after != label2; range2after = rangenext)
  			  {
  			    rangenext = NEXT_INSN (range2after);
  			    if (GET_CODE (range2after) == NOTE)
  			      {
! 				int kind = NOTE_LINE_NUMBER (range2after);
! 				if (kind == NOTE_INSN_LOOP_END
! 				    || kind == NOTE_INSN_LOOP_VTOP
! 				    || kind == NOTE_INSN_LOOP_CONT)
  				  {
  				    NEXT_INSN (PREV_INSN (range2after))
  				      = rangenext;




More information about the Gcc-patches mailing list