This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Use-and-clobber insns and REG_DEAD notes (fwd)


Richard Henderson wrote:
> On Wed, Jul 16, 2003 at 03:20:06AM +0200, Michael Matz wrote:
> > Adding a REG_DEAD for a clobber doesn't make sense IMO.
> 
> Not because of the clobber per-se, but because that's
> where the register dies.
> 
> The problem is sure to be bad interaction with other code
> that correctly tries to prevent a REG_DEAD note for a register
> that is both used and SET (not clobbered) in the same insn.

OK, I've tried to come up with a patch to implement this
behaviour (use-and-set omits REG_DEAD note, use-and-clobber
doesn't) in combine.

However, there appears to be confusion as to this question
even in flow itself: in the case of partial deaths of 
multi-work registers, mark_used_reg uses 'pbi->new_set' 
(where clobbers don't count) to check whether a dead note 
is required at all, but dead_or_set_p (where clobbers *do*
count) to check for which subregs it is required ...

Is there a reason for this behaviour?  I'm assuming that
this is just an oversight, and have changed it in the
patch below to use pbi->new_set as well; likewise in 
the corresponding part of distribute_note.

(I am not completely convinced that distribute_note
handles partial deaths correctly; seeing as this is
supposed to be a rather rare occasion anyway, maybe
we could just fall back to regenerating flow info 
in that case anyway?)

The patch below fixes the ICE in my testcase, and survives
bootstrap and regtest on s390-ibm-linux and s390x-ibm-linux.
What do you think?


ChangeLog:

	* combine.c (reg_bitfield_target_p): Remove.
	(reg_new_set_p): New function.
	(distribute_notes): Align handling of REG_DEAD notes
	with what flow would do.
	* flow.c (mark_used_reg): Do not omit a REG_DEAD note
	for a partial register that is clobbered (not set).

Index: gcc/combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.369
diff -c -p -r1.369 combine.c
*** gcc/combine.c	13 Jul 2003 19:03:28 -0000	1.369
--- gcc/combine.c	17 Jul 2003 01:00:58 -0000
*************** static int use_crosses_set_p (rtx, int);
*** 402,408 ****
  static void reg_dead_at_p_1 (rtx, rtx, void *);
  static int reg_dead_at_p (rtx, rtx);
  static void move_deaths (rtx, rtx, int, rtx, rtx *);
! static int reg_bitfield_target_p (rtx, rtx);
  static void distribute_notes (rtx, rtx, rtx, rtx);
  static void distribute_links (rtx);
  static void mark_used_regs_combine (rtx);
--- 402,408 ----
  static void reg_dead_at_p_1 (rtx, rtx, void *);
  static int reg_dead_at_p (rtx, rtx);
  static void move_deaths (rtx, rtx, int, rtx, rtx *);
! static bool reg_new_set_p (rtx, rtx);
  static void distribute_notes (rtx, rtx, rtx, rtx);
  static void distribute_links (rtx);
  static void mark_used_regs_combine (rtx);
*************** move_deaths (rtx x, rtx maybe_kill_insn,
*** 12375,12423 ****
      }
  }
  
! /* Return 1 if X is the target of a bit-field assignment in BODY, the
!    pattern of an insn.  X must be a REG.  */
  
! static int
! reg_bitfield_target_p (rtx x, rtx body)
  {
!   int i;
! 
!   if (GET_CODE (body) == SET)
!     {
!       rtx dest = SET_DEST (body);
!       rtx target;
!       unsigned int regno, tregno, endregno, endtregno;
! 
!       if (GET_CODE (dest) == ZERO_EXTRACT)
! 	target = XEXP (dest, 0);
!       else if (GET_CODE (dest) == STRICT_LOW_PART)
! 	target = SUBREG_REG (XEXP (dest, 0));
!       else
! 	return 0;
! 
!       if (GET_CODE (target) == SUBREG)
! 	target = SUBREG_REG (target);
! 
!       if (GET_CODE (target) != REG)
! 	return 0;
! 
!       tregno = REGNO (target), regno = REGNO (x);
!       if (tregno >= FIRST_PSEUDO_REGISTER || regno >= FIRST_PSEUDO_REGISTER)
! 	return target == x;
! 
!       endtregno = tregno + HARD_REGNO_NREGS (tregno, GET_MODE (target));
!       endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
! 
!       return endregno > tregno && regno < endtregno;
!     }
! 
!   else if (GET_CODE (body) == PARALLEL)
!     for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
!       if (reg_bitfield_target_p (x, XVECEXP (body, 0, i)))
! 	return 1;
! 
!   return 0;
  }
  
  /* Given a chain of REG_NOTES originally from FROM_INSN, try to place them
--- 12375,12387 ----
      }
  }
  
! /* Return true if X is set (not clobbered) in INSN.  */
  
! static bool
! reg_new_set_p (rtx x, rtx insn)
  {
!   rtx set = set_of (x, insn);
!   return set && GET_CODE (set) == SET;
  }
  
  /* Given a chain of REG_NOTES originally from FROM_INSN, try to place them
*************** distribute_notes (rtx notes, rtx from_in
*** 12853,12860 ****
  	      if (noop_move_p (place))
  		SET_BIT (refresh_blocks, this_basic_block->index);
  
! 	      if (dead_or_set_p (place, XEXP (note, 0))
! 		  || reg_bitfield_target_p (XEXP (note, 0), PATTERN (place)))
  		{
  		  /* Unless the register previously died in PLACE, clear
  		     reg_last_death.  [I no longer understand why this is
--- 12817,12824 ----
  	      if (noop_move_p (place))
  		SET_BIT (refresh_blocks, this_basic_block->index);
  
! 	      if (find_regno_note (place, REG_DEAD, regno)
! 		  || reg_new_set_p (XEXP (note, 0), place))
  		{
  		  /* Unless the register previously died in PLACE, clear
  		     reg_last_death.  [I no longer understand why this is
*************** distribute_notes (rtx notes, rtx from_in
*** 12887,12893 ****
  		  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)
--- 12851,12857 ----
  		  for (i = regno; i < endregno; i++)
  		    if ((! refers_to_regno_p (i, i + 1, PATTERN (place), 0)
  			 && ! find_regno_fusage (place, USE, i))
! 			|| reg_new_set_p (regno_reg_rtx[i], place))
  		      all_used = 0;
  
  		  if (! all_used)
*************** distribute_notes (rtx notes, rtx from_in
*** 12901,12909 ****
  			  rtx piece = regno_reg_rtx[i];
  			  basic_block bb = this_basic_block;
  
! 			  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);
--- 12865,12872 ----
  			  rtx piece = regno_reg_rtx[i];
  			  basic_block bb = this_basic_block;
  
! 			  if (! find_regno_note (place, REG_DEAD, i)
! 			      && ! reg_new_set_p (piece, place))
  			    {
  			      rtx new_note
  				= gen_rtx_EXPR_LIST (REG_DEAD, piece, NULL_RTX);
*************** distribute_notes (rtx notes, rtx from_in
*** 12927,12935 ****
  				      }
  				    continue;
  				  }
! 				if (dead_or_set_p (tem, piece)
! 				    || reg_bitfield_target_p (piece,
! 							      PATTERN (tem)))
  				  {
  				    REG_NOTES (tem)
  				      = gen_rtx_EXPR_LIST (REG_UNUSED, piece,
--- 12890,12896 ----
  				      }
  				    continue;
  				  }
! 				if (reg_set_p (piece, tem))
  				  {
  				    REG_NOTES (tem)
  				      = gen_rtx_EXPR_LIST (REG_UNUSED, piece,
Index: gcc/flow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flow.c,v
retrieving revision 1.560
diff -c -p -r1.560 flow.c
*** gcc/flow.c	3 Jul 2003 18:40:27 -0000	1.560
--- gcc/flow.c	17 Jul 2003 01:00:59 -0000
*************** mark_used_reg (struct propagate_block_in
*** 3586,3592 ****
  	     that is set in the insn.  */
  	  for (i = regno_first; i <= regno_last; ++i)
  	    if (! REGNO_REG_SET_P (pbi->reg_live, i)
! 		&& ! dead_or_set_regno_p (insn, i))
  	      REG_NOTES (insn)
  		= alloc_EXPR_LIST (REG_DEAD,
  				   regno_reg_rtx[i],
--- 3586,3593 ----
  	     that is set in the insn.  */
  	  for (i = regno_first; i <= regno_last; ++i)
  	    if (! REGNO_REG_SET_P (pbi->reg_live, i)
! 		&& ! REGNO_REG_SET_P (pbi->new_set, i)
! 		&& ! find_regno_note (insn, REG_DEAD, i))
  	      REG_NOTES (insn)
  		= alloc_EXPR_LIST (REG_DEAD,
  				   regno_reg_rtx[i],


-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]