loop bug

Jeffrey A Law law@cygnus.com
Mon Feb 15 10:44:00 GMT 1999


Whee.  It's been a long time since I had to clean up a bogon from haifa.


mark_loop_jump would (in rare cases) stomp on important hunks of RTL found
in jump instructions.  Consider this beauty I found:

(jump_insn 89 88 90 (set (pc)
        (lo_sum/s:SI (reg:SI 128)
            (nil))) -1 (nil)

The "(nil)" was actually a SYMBOL_REF at one time until mark_loop_jump
pretended it could set LABEL_NEXT_REF and LABEL_OUTSIDE_LOOP_P for the
LO_SUM.

It is never valid to set those macros for anything except a LABEL_REF,
and LABEL_REFs are already handled by mark_loop_jump.

Worse yet the code would put the LO_SUM on the loop_number_exit_labels list
which other parts of loop assume is a list of LABEL_REFs linked through the
LABEL_NEXT_REF chain.  Putting a LO_SUM (or anything except a LABEL_REF) on
that list is just as wrong set setting LABEL_NEXT_REF.

As far as I can tell mark_loop_jump already handles all the important stuff,
so when presented with something it does not understand it should just mark
the loop as invalid.  If this turns out to be too pessimistic we can enhance
mark_loop_jump and our method for tracking exit points in the future.




        * loop.c (mark_loop_jump): Handle LO_SUM.  If we encounter something
        we do not understand, mark the loop and containing loops as invalid.

Index: loop.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/loop.c,v
retrieving revision 1.137
diff -c -3 -p -r1.137 loop.c
*** loop.c	1999/02/13 23:47:23	1.137
--- loop.c	1999/02/15 18:36:20
*************** mark_loop_jump (x, loop_num)
*** 2981,2986 ****
--- 2981,2991 ----
        mark_loop_jump (XEXP (x, 1), loop_num);
        return;
  
+     case LO_SUM:
+       /* This may refer to a LABEL_REF or SYMBOL_REF.  */
+       mark_loop_jump (XEXP (x, 1), loop_num);
+       return;
+ 
      case SIGN_EXTEND:
      case ZERO_EXTEND:
        mark_loop_jump (XEXP (x, 0), loop_num);
*************** mark_loop_jump (x, loop_num)
*** 3068,3088 ****
        return;
  
      default:
!       /* Treat anything else (such as a symbol_ref)
! 	 as a branch out of this loop, but not into any loop.  */
! 
        if (loop_num != -1)
  	{
- #ifdef HAVE_decrement_and_branch_on_count
- 	  LABEL_OUTSIDE_LOOP_P (x) = 1;
- 	  LABEL_NEXTREF (x) = loop_number_exit_labels[loop_num];
- #endif  /* HAVE_decrement_and_branch_on_count */
- 
- 	  loop_number_exit_labels[loop_num] = x;
- 
  	  for (outer_loop = loop_num; outer_loop != -1;
  	       outer_loop = loop_outer_loop[outer_loop])
! 	    loop_number_exit_count[outer_loop]++;
  	}
        return;
      }
--- 3073,3093 ----
        return;
  
      default:
!       /* Strictly speaking this is not a jump into the loop, only a possible
! 	 jump out of the loop.  However, we have no way to link the destination
! 	 of this jump onto the list of exit labels.  To be safe we mark this
! 	 loop and any containing loops as invalid.  */
        if (loop_num != -1)
  	{
  	  for (outer_loop = loop_num; outer_loop != -1;
  	       outer_loop = loop_outer_loop[outer_loop])
! 	    {
! 	      if (loop_dump_stream && ! loop_invalid[outer_loop])
! 		fprintf (loop_dump_stream,
! 			 "\nLoop at %d ignored due to unknown exit jump.\n",
! 			 INSN_UID (loop_number_loop_starts[outer_loop]));
! 	      loop_invalid[outer_loop] = 1;
! 	    }
  	}
        return;
      }


More information about the Gcc-patches mailing list