This is the mail archive of the gcc-patches@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]

BB boundary problem in regmove.c


In quite a few places, regmove.c tries to determine if it is going outside
of a basic block.  However, the test in the CALL_INSN case is not correct
since it ignores nonlocal_goto_handler_labels.

I made a function to test for this, added the missing test, and changed
all the code that tests to use the function.

This test is conservative, and necessarily so.  Therefore, it would be nice
if somebody would rewrite this to use the BB data structures sometime.

In the meantime, I checked in the following:

Fri Aug 18 14:23:18 2000  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>

	* regmove.c (perhaps_ends_bb_p): New function.
	(optimize_reg_copy_1, optimize_reg_copy_2): Call it.
	(optimize_reg_copy_3, fixup_match_2, regmove_optimize): Likewise.
	(fixup_match_1): Likewise.
	(fixup_match_1, combine_stack_adjustments_for_block): Add casts to
	avoid signed/unsigned warnings.
	
*** regmove.c	2000/08/04 20:28:05	1.89
--- regmove.c	2000/08/18 17:57:17
*************** Boston, MA 02111-1307, USA.  */
*** 42,45 ****
--- 42,46 ----
  #include "toplev.h"
  
+ static int perhaps_ends_bb_p	PARAMS ((rtx));
  static int optimize_reg_copy_1	PARAMS ((rtx, rtx, rtx));
  static void optimize_reg_copy_2	PARAMS ((rtx, rtx, rtx));
*************** replacement_quality(reg)
*** 368,372 ****
--- 369,397 ----
    return 2;
  }
+ 
+ /* Return 1 if INSN might end a basic block.  */
+ 
+ static int perhaps_ends_bb_p (insn)
+      rtx insn;
+ {
+   switch (GET_CODE (insn))
+     {
+     case CODE_LABEL:
+     case JUMP_INSN:
+       /* These always end a basic block.  */
+       return 1;
  
+     case CALL_INSN:
+       /* A CALL_INSN might be the last insn of a basic block, if it is inside
+ 	 an EH region or if there are nonlocal gotos.  Note that this test is
+ 	 very conservative.  */
+       return flag_exceptions || nonlocal_goto_handler_labels;
+ 
+     default:
+       /* All others never end a basic block.  */
+       return 0;
+     }
+ }
+ 
  /* INSN is a copy from SRC to DEST, both registers, and SRC does not die
     in INSN.
*************** optimize_reg_copy_1 (insn, dest, src)
*** 404,419 ****
    for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
      {
-       if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN)
- 	break;
- 
        /* ??? We can't scan past the end of a basic block without updating
! 	 the register lifetime info (REG_DEAD/basic_block_live_at_start).
! 	 A CALL_INSN might be the last insn of a basic block, if it is inside
! 	 an EH region.  There is no easy way to tell, so we just always break
! 	 when we see a CALL_INSN if flag_exceptions is nonzero.  */
!       if (flag_exceptions && GET_CODE (p) == CALL_INSN)
  	break;
! 
!       if (! INSN_P (p))
  	continue;
  
--- 429,437 ----
    for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
      {
        /* ??? We can't scan past the end of a basic block without updating
! 	 the register lifetime info (REG_DEAD/basic_block_live_at_start).  */
!       if (perhaps_ends_bb_p (p))
  	break;
!       else if (! INSN_P (p))
  	continue;
  
*************** optimize_reg_copy_2 (insn, dest, src)
*** 589,604 ****
    for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
      {
-       if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN)
- 	break;
- 
        /* ??? We can't scan past the end of a basic block without updating
! 	 the register lifetime info (REG_DEAD/basic_block_live_at_start).
! 	 A CALL_INSN might be the last insn of a basic block, if it is inside
! 	 an EH region.  There is no easy way to tell, so we just always break
! 	 when we see a CALL_INSN if flag_exceptions is nonzero.  */
!       if (flag_exceptions && GET_CODE (p) == CALL_INSN)
  	break;
! 
!       if (! INSN_P (p))
  	continue;
  
--- 607,615 ----
    for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
      {
        /* ??? We can't scan past the end of a basic block without updating
! 	 the register lifetime info (REG_DEAD/basic_block_live_at_start).  */
!       if (perhaps_ends_bb_p (p))
  	break;
!       else if (! INSN_P (p))
  	continue;
  
*************** optimize_reg_copy_3 (insn, dest, src)
*** 662,680 ****
      return;
    for (p = PREV_INSN (insn); p && ! reg_set_p (src_reg, p); p = PREV_INSN (p))
!     {
!       if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN)
! 	return;
! 
!       /* ??? We can't scan past the end of a basic block without updating
! 	 the register lifetime info (REG_DEAD/basic_block_live_at_start).
! 	 A CALL_INSN might be the last insn of a basic block, if it is inside
! 	 an EH region.  There is no easy way to tell, so we just always break
! 	 when we see a CALL_INSN if flag_exceptions is nonzero.  */
!       if (flag_exceptions && GET_CODE (p) == CALL_INSN)
! 	return;
  
-       if (! INSN_P (p))
- 	continue;
-     }
    if (! p)
      return;
--- 673,681 ----
      return;
    for (p = PREV_INSN (insn); p && ! reg_set_p (src_reg, p); p = PREV_INSN (p))
!     /* ??? We can't scan past the end of a basic block without updating
!        the register lifetime info (REG_DEAD/basic_block_live_at_start).  */
!     if (perhaps_ends_bb_p (p))
!       break;
  
    if (! p)
      return;
*************** fixup_match_2 (insn, dst, src, offset, r
*** 941,957 ****
        rtx pset;
  
-       if (GET_CODE (p) == CODE_LABEL
-           || GET_CODE (p) == JUMP_INSN)
-         break;
- 
        /* ??? We can't scan past the end of a basic block without updating
! 	 the register lifetime info (REG_DEAD/basic_block_live_at_start).
! 	 A CALL_INSN might be the last insn of a basic block, if it is inside
! 	 an EH region.  There is no easy way to tell, so we just always break
! 	 when we see a CALL_INSN if flag_exceptions is nonzero.  */
!       if (flag_exceptions && GET_CODE (p) == CALL_INSN)
  	break;
! 
!       if (! INSN_P (p))
          continue;
  
--- 942,950 ----
        rtx pset;
  
        /* ??? We can't scan past the end of a basic block without updating
! 	 the register lifetime info (REG_DEAD/basic_block_live_at_start).  */
!       if (perhaps_ends_bb_p (p))
  	break;
!       else if (! INSN_P (p))
          continue;
  
*************** regmove_optimize (f, nregs, regmove_dump
*** 1371,1389 ****
  		  rtx pset;
  
- 		  if (GET_CODE (p) == CODE_LABEL
- 		      || GET_CODE (p) == JUMP_INSN)
- 		    break;
- 
  		  /* ??? We can't scan past the end of a basic block without
  		     updating the register lifetime info
! 		     (REG_DEAD/basic_block_live_at_start).
! 		     A CALL_INSN might be the last insn of a basic block, if
! 		     it is inside an EH region.  There is no easy way to tell,
! 		     so we just always break when we see a CALL_INSN if
! 		     flag_exceptions is nonzero.  */
! 		  if (flag_exceptions && GET_CODE (p) == CALL_INSN)
  		    break;
! 
! 		  if (! INSN_P (p))
  		    continue;
  
--- 1364,1373 ----
  		  rtx pset;
  
  		  /* ??? We can't scan past the end of a basic block without
  		     updating the register lifetime info
! 		     (REG_DEAD/basic_block_live_at_start).  */
! 		  if (perhaps_ends_bb_p (p))
  		    break;
! 		  else if (! INSN_P (p))
  		    continue;
  
*************** find_matches (insn, matchp)
*** 1594,1597 ****
--- 1578,1582 ----
     If BACKWARD is nonzero, we have been called in a backward pass.
     Return nonzero for success.  */
+ 
  static int
  fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
*************** fixup_match_1 (insn, set, src, src_subre
*** 1659,1674 ****
    for (length = s_length = 0, p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
      {
-       if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN)
- 	break;
- 
        /* ??? We can't scan past the end of a basic block without updating
! 	 the register lifetime info (REG_DEAD/basic_block_live_at_start).
! 	 A CALL_INSN might be the last insn of a basic block, if it is
! 	 inside an EH region.  There is no easy way to tell, so we just
! 	 always break when we see a CALL_INSN if flag_exceptions is nonzero.  */
!       if (flag_exceptions && GET_CODE (p) == CALL_INSN)
  	break;
! 
!       if (! INSN_P (p))
  	continue;
  
--- 1644,1652 ----
    for (length = s_length = 0, p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
      {
        /* ??? We can't scan past the end of a basic block without updating
! 	 the register lifetime info (REG_DEAD/basic_block_live_at_start).  */
!       if (perhaps_ends_bb_p (p))
  	break;
!       else if (! INSN_P (p))
  	continue;
  
*************** fixup_match_1 (insn, set, src, src_subre
*** 1705,1731 ****
  	      for (q = p; q; q = NEXT_INSN (q))
  		{
- 		  if (GET_CODE (q) == CODE_LABEL || GET_CODE (q) == JUMP_INSN)
- 		    {
- 		      q = 0;
- 		      break;
- 		    }
- 
  		  /* ??? We can't scan past the end of a basic block without
  		     updating the register lifetime info
! 		     (REG_DEAD/basic_block_live_at_start).
! 		     A CALL_INSN might be the last insn of a basic block, if
! 		     it is inside an EH region.  There is no easy way to tell,
! 		     so we just always break when we see a CALL_INSN if
! 		     flag_exceptions is nonzero.  */
! 		  if (flag_exceptions && GET_CODE (q) == CALL_INSN)
  		    {
  		      q = 0;
  		      break;
  		    }
! 
! 		  if (! INSN_P (q))
  		    continue;
! 		  if (reg_overlap_mentioned_p (src, PATTERN (q))
! 		      || reg_set_p (src, q))
  		    break;
  		}
--- 1683,1698 ----
  	      for (q = p; q; q = NEXT_INSN (q))
  		{
  		  /* ??? We can't scan past the end of a basic block without
  		     updating the register lifetime info
! 		     (REG_DEAD/basic_block_live_at_start).  */
! 		  if (perhaps_ends_bb_p (q))
  		    {
  		      q = 0;
  		      break;
  		    }
! 		  else if (! INSN_P (q))
  		    continue;
! 		  else if (reg_overlap_mentioned_p (src, PATTERN (q))
! 			   || reg_set_p (src, q))
  		    break;
  		}
*************** fixup_match_1 (insn, set, src, src_subre
*** 1772,1777 ****
  		  if (code != PLUS
  		      && (newconst < 0
! 			  || (newconst
! 			      >= GET_MODE_BITSIZE (GET_MODE (SET_SRC (set2))))))
  		    break;
  		  if (code == PLUS)
--- 1739,1745 ----
  		  if (code != PLUS
  		      && (newconst < 0
! 			  || ((unsigned HOST_WIDE_INT) newconst
! 			      >= (GET_MODE_BITSIZE (GET_MODE
! 						    (SET_SRC (set2)))))))
  		    break;
  		  if (code == PLUS)
*************** fixup_match_1 (insn, set, src, src_subre
*** 1880,1904 ****
  	  for (q = PREV_INSN (insn); q; q = PREV_INSN(q))
  	    {
- 	      if (GET_CODE (q) == CODE_LABEL || GET_CODE (q) == JUMP_INSN)
- 		{
- 		  q = 0;
- 		  break;
- 		}
- 
  	      /* ??? We can't scan past the end of a basic block without
  		 updating the register lifetime info
! 		 (REG_DEAD/basic_block_live_at_start).
! 		 A CALL_INSN might be the last insn of a basic block, if
! 		 it is inside an EH region.  There is no easy way to tell,
! 		 so we just always break when we see a CALL_INSN if
! 		 flag_exceptions is nonzero.  */
! 	      if (flag_exceptions && GET_CODE (q) == CALL_INSN)
  		{
  		  q = 0;
  		  break;
  		}
! 
! 	      if (! INSN_P (q))
  		continue;
  	      s_length2++;
  	      if (reg_set_p (src, q))
--- 1848,1862 ----
  	  for (q = PREV_INSN (insn); q; q = PREV_INSN(q))
  	    {
  	      /* ??? We can't scan past the end of a basic block without
  		 updating the register lifetime info
! 		 (REG_DEAD/basic_block_live_at_start).  */
! 	      if (perhaps_ends_bb_p (q))
  		{
  		  q = 0;
  		  break;
  		}
! 	      else if (! INSN_P (q))
  		continue;
+ 
  	      s_length2++;
  	      if (reg_set_p (src, q))
*************** fixup_match_1 (insn, set, src, src_subre
*** 1952,1975 ****
        for (q = post_inc; (q = NEXT_INSN (q)); )
  	{
- 	  if (GET_CODE (q) == CODE_LABEL || GET_CODE (q) == JUMP_INSN)
- 	    break;
- 
  	  /* ??? We can't scan past the end of a basic block without updating
! 	     the register lifetime info (REG_DEAD/basic_block_live_at_start).
! 	     A CALL_INSN might be the last insn of a basic block, if it
! 	     is inside an EH region.  There is no easy way to tell so we
! 	     just always break when we see a CALL_INSN if flag_exceptions
! 	     is nonzero.  */
! 	  if (flag_exceptions && GET_CODE (q) == CALL_INSN)
  	    break;
! 
! 	  if (! INSN_P (q))
  	    continue;
! 	  if (src != inc_dest && (reg_overlap_mentioned_p (src, PATTERN (q))
! 				  || reg_set_p (src, q)))
  	    break;
! 	  if (reg_set_p (inc_dest, q))
  	    break;
! 	  if (reg_overlap_mentioned_p (inc_dest, PATTERN (q)))
  	    {
  	      try_auto_increment (q, post_inc,
--- 1910,1927 ----
        for (q = post_inc; (q = NEXT_INSN (q)); )
  	{
  	  /* ??? We can't scan past the end of a basic block without updating
! 	     the register lifetime info
! 	     (REG_DEAD/basic_block_live_at_start). */
! 	  if (perhaps_ends_bb_p (q))
  	    break;
! 	  else if (! INSN_P (q))
  	    continue;
! 	  else if (src != inc_dest
! 		   && (reg_overlap_mentioned_p (src, PATTERN (q))
! 		       || reg_set_p (src, q)))
  	    break;
! 	  else if (reg_set_p (inc_dest, q))
  	    break;
! 	  else if (reg_overlap_mentioned_p (inc_dest, PATTERN (q)))
  	    {
  	      try_auto_increment (q, post_inc,
*************** fixup_match_1 (insn, set, src, src_subre
*** 1979,1982 ****
--- 1931,1935 ----
  	}
      }
+ 
    /* Move the death note for DST to INSN if it is used
       there.  */
*************** combine_stack_adjustments_for_block (bb)
*** 2388,2392 ****
  	     there were any intervening uses of the stack pointer.  */
  	  if (memlist == NULL
! 	      && last_sp_adjust == GET_MODE_SIZE (GET_MODE (dest))
  	      && GET_CODE (dest) == MEM
  	      && GET_CODE (XEXP (dest, 0)) == PRE_DEC
--- 2341,2346 ----
  	     there were any intervening uses of the stack pointer.  */
  	  if (memlist == NULL
! 	      && (last_sp_adjust
! 		  == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest)))
  	      && GET_CODE (dest) == MEM
  	      && GET_CODE (XEXP (dest, 0)) == PRE_DEC

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