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]

Fix for latent twolf spec2000 test failures


Hi,
this was tricky bug to hunt down. It has shown as misscompilation of twolf
spec2000 benchmark with -funroll-all-loops.  The function in question is large,
BASIC-like code, containing many fors iterating over global variables.  The
GCSE introduces many dumy copies.  (like:

(set (reg) (expr))
(set (reg2) (reg))  <- reg dies here

that comes from originally memory references (where caching expression in register makes sense).
No one cleans them up and try_swap_copy_prop reach sequence
(set (reg A) (plus (reg B) (const_int 1))
(set (reg B) (reg A)
  (REG_EQUAL (plus (reg B) (const_int 1))

Note that the code is already wrong, as it says B == B+1, but I am
sending another patch, as there is still (reproducible) bug in loop.
The code in question attempts to do transformation:

	  We have:
	     (set (reg regno) (expr))
	     (set (reg new_regno) (reg regno))

	     so try converting this to:
	     (set (reg new_regno) (expr))
	     (set (reg regno) (reg new_regno))

But after converting it keeps the notes at place. It should move the
notes to first place, as and REG_EQUAL mentioning REGNO or NEW_REGNO is
wrong.

As I've mentioned we still can create such reg_equal notes, that basically
says reg == reg, but in a way like reg == reg + 0, as the effect of constant
propagation.

With some luck I was able to construct testcase, so we must kill the notes
here.  The patch also re-distributes them to the first set.

Honza

Pá srp  3 16:07:14 CEST 2001  Jan Hubicka  <jh@suse.cz>
	* loop.c  (try_swap_copy_prop): Take care to update loop notes
	and REGNO_LAST_UID.
*** loop.c.old	Fri Aug  3 14:31:40 2001
--- loop.c	Fri Aug  3 16:06:49 2001
*************** try_swap_copy_prop (loop, replacement, r
*** 9432,9437 ****
--- 9435,9441 ----
  
  	  if (apply_change_group ())
  	    {
+ 	      rtx *pnote = &REG_NOTES (insn);
  	      if (loop_dump_stream)
  		fprintf (loop_dump_stream,
  			 "  Swapped set of reg %d at %d with reg %d at %d.\n",
*************** try_swap_copy_prop (loop, replacement, r
*** 9440,9446 ****
  
  	      /* Update first use of REGNO.  */
  	      if (REGNO_FIRST_UID (regno) == INSN_UID (prev_insn))
! 		REGNO_FIRST_UID (regno) = INSN_UID (insn);
  
  	      /* Now perform copy propagation to hopefully
  		 remove all uses of REGNO within the loop.  */
--- 9444,9476 ----
  
  	      /* Update first use of REGNO.  */
  	      if (REGNO_FIRST_UID (regno) == INSN_UID (prev_insn))
! 		{
! 		  REGNO_FIRST_UID (regno) = INSN_UID (insn);
! 		  /* In case register appears to be used only as an temporary
! 		     for computation above, kill it.  */
! 		  if (REGNO_LAST_UID (regno) == INSN_UID (insn))
! 		    delete_insn (insn);
! 		}
! 	      if (REGNO_LAST_UID (regno) == INSN_UID (insn))
! 		REGNO_LAST_UID (regno) = INSN_UID (insn);
! 
! 	      /* Move the REG_EQUIV notes.  Take care to avoid notes mentioning
! 	         original values of the registers.  Such notes are no longer
! 	         valid.  */
! 	      while (*pnote)
! 		{
! 		  if (REG_NOTE_KIND (*pnote) == REG_EQUAL)
! 		    {
! 		      if (!reg_mentioned_p (SET_DEST (set), XEXP (*pnote, 0))
! 			  && !reg_mentioned_p (replacement, XEXP (*pnote, 0)))
! 			REG_NOTES (prev_insn)
! 			  = gen_rtx_EXPR_LIST (REG_EQUAL,
! 					       XEXP (*pnote, 0), REG_NOTES (prev_insn));
! 		      *pnote = XEXP (*pnote, 1);
! 		    }
! 		  else
! 		    pnote = &XEXP (*pnote, 1);
! 		}
  
  	      /* Now perform copy propagation to hopefully
  		 remove all uses of REGNO within the loop.  */


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