distribute_notes bug fix

Joern Rennecke amylaar@redhat.com
Wed Oct 25 10:51:00 GMT 2000


I saw an abort in haifa-sched.c because there was one more death note
before scheduling than after.  This was because a spurious USE with a
REG_DEAD note had been inserted by combine.
Combine had combined two insns where the first set a multi-hard-reg hard
register, and the second used it and set it again.  
In distribute_notes, the check against elim_i2 failed because it uses
a pointer equality test, which doesn't work for hard registers.
So eventually distribute_notes searched backwards for an insn that used
the hard reg, and found one that used just a part of it.  It then placed
a USE with a REG_DEAD note for the unused part in front of that insn.
However, at that point the unused part was already dead, so the
USE / REG_DEAD was incorrect.

Wed Oct 25 18:18:49 2000  J"orn Rennecke <amylaar@redhat.co.uk>

	* combine.c (distribute_notes): Use rtx_equal_p to check elim_i2 /
	elim_i1.
	In REG_DEAD handling: When handling parts of multi-hard-reg hard
	registers, increment the loop counter by the size of the parts;
	use recursion to handle individual parts.

Index: combine.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/combine.c,v
retrieving revision 1.239
diff -p -r1.239 combine.c
*** combine.c	2000/10/24 20:20:15	1.239
--- combine.c	2000/10/25 17:16:20
*************** distribute_notes (notes, from_insn, i3, 
*** 12293,12299 ****
  		   && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
  	    place = i2;
  
! 	  if (XEXP (note, 0) == elim_i2 || XEXP (note, 0) == elim_i1)
  	    break;
  
  	  if (place == 0)
--- 12293,12300 ----
  		   && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
  	    place = i2;
  
! 	  if (rtx_equal_p (XEXP (note, 0), elim_i2)
! 	      || rtx_equal_p (XEXP (note, 0), elim_i1))
  	    break;
  
  	  if (place == 0)
*************** distribute_notes (notes, from_insn, i3, 
*** 12473,12486 ****
  	      /* If this is a death note for a hard reg that is occupying
  		 multiple registers, ensure that we are still using all
  		 parts of the object.  If we find a piece of the object
! 		 that is unused, we must add a USE for that piece before
! 		 PLACE and put the appropriate REG_DEAD note on it.
  
- 		 An alternative would be to put a REG_UNUSED for the pieces
- 		 on the insn that set the register, but that can't be done if
- 		 it is not in the same block.  It is simpler, though less
- 		 efficient, to add the USE insns.  */
- 
  	      if (place && regno < FIRST_PSEUDO_REGISTER
  		  && HARD_REGNO_NREGS (regno, GET_MODE (XEXP (note, 0))) > 1)
  		{
--- 12474,12485 ----
  	      /* If this is a death note for a hard reg that is occupying
  		 multiple registers, ensure that we are still using all
  		 parts of the object.  If we find a piece of the object
! 		 that is unused, we must arrange for an appropriate REG_DEAD
! 		 note to be added for it.  However, we can't just emit a USE
! 		 and tag the note to it, since the register might actually
! 		 be dead; so we recourse, and the recursive call then finds
! 		 the previous insn that used this register.  */
  
  	      if (place && regno < FIRST_PSEUDO_REGISTER
  		  && HARD_REGNO_NREGS (regno, GET_MODE (XEXP (note, 0))) > 1)
  		{
*************** distribute_notes (notes, from_insn, i3, 
*** 12491,12557 ****
  		  unsigned int i;
  
  		  for (i = regno; i < endregno; i++)
! 		    if (! refers_to_regno_p (i, i + 1, PATTERN (place), 0)
! 			&& ! find_regno_fusage (place, USE, i))
! 		      {
! 			rtx piece = gen_rtx_REG (reg_raw_mode[i], i);
! 			rtx p;
! 
! 			/* See if we already placed a USE note for this
! 			   register in front of PLACE.  */
! 			for (p = place;
! 			     GET_CODE (PREV_INSN (p)) == INSN
! 			     && GET_CODE (PATTERN (PREV_INSN (p))) == USE;
! 			     p = PREV_INSN (p))
! 			  if (rtx_equal_p (piece,
! 					   XEXP (PATTERN (PREV_INSN (p)), 0)))
! 			    {
! 			      p = 0;
! 			      break;
! 			    }
  
- 			if (p)
- 			  {
- 			    rtx use_insn
- 			      = emit_insn_before (gen_rtx_USE (VOIDmode,
- 							       piece),
- 						  p);
- 			    REG_NOTES (use_insn)
- 			      = gen_rtx_EXPR_LIST (REG_DEAD, piece,
- 						   REG_NOTES (use_insn));
- 			  }
- 
- 			all_used = 0;
- 		      }
- 
- 		  /* Check for the case where the register dying partially
- 		     overlaps the register set by this insn.  */
- 		  if (all_used)
- 		    for (i = regno; i < endregno; i++)
- 		      if (dead_or_set_regno_p (place, i))
- 			{
- 			  all_used = 0;
- 			  break;
- 			}
- 
  		  if (! all_used)
  		    {
  		      /* Put only REG_DEAD notes for pieces that are
! 			 still used and that are not already dead or set.  */
  
! 		      for (i = regno; i < endregno; i++)
  			{
  			  rtx piece = gen_rtx_REG (reg_raw_mode[i], i);
  
! 			  if ((reg_referenced_p (piece, PATTERN (place))
! 			       || (GET_CODE (place) == CALL_INSN
! 				   && find_reg_fusage (place, USE, piece)))
! 			      && ! dead_or_set_p (place, piece)
  			      && ! reg_bitfield_target_p (piece,
  							  PATTERN (place)))
! 			    REG_NOTES (place)
! 			      = gen_rtx_EXPR_LIST (REG_DEAD, piece,
! 						   REG_NOTES (place));
  			}
  
  		      place = 0;
--- 12490,12520 ----
  		  unsigned int i;
  
  		  for (i = regno; i < endregno; i++)
! 		    if ((! refers_to_regno_p (i, i + 1, PATTERN (place), 0)
! 			 && ! find_regno_fusage (place, USE, i))
! 			|| dead_or_set_regno_p (place, i))
! 		      all_used = 0;
  
  		  if (! all_used)
  		    {
  		      /* Put only REG_DEAD notes for pieces that are
! 			 not already dead or set.  */
  
! 		      for (i = regno; i < endregno;
! 			   i += HARD_REGNO_NREGS (i, reg_raw_mode[i]))
  			{
  			  rtx piece = gen_rtx_REG (reg_raw_mode[i], i);
  
! 			  if (! dead_or_set_p (place, piece)
  			      && ! reg_bitfield_target_p (piece,
  							  PATTERN (place)))
! 			    {
! 			      rtx new_note
! 				= gen_rtx_EXPR_LIST (REG_DEAD, piece, NULL_RTX);
! 
! 			      distribute_notes (new_note, place, place,
! 						NULL_RTX, NULL_RTX, NULL_RTX);
! 			    }
  			}
  
  		      place = 0;


More information about the Gcc-patches mailing list