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]

patch for killing cc0 users


On the x86, the following program will segv all versions of cc1:

int foo(double x, double y)
{
  return x < y <= 1;
}

The segv is the result of reg-stack trying to find the cc0 user
of the first compare, and coming up with a null.  The slt in
question was removed by combine because the second comparison 
is clearly always true.

My proposed solution is to have combine remove both the cc0 
setter and the cc0 user when possible.  If we cannot remove
the cc0 setter (due to side effects) the cc0 user will have
its result marked REG_UNUSED.  This is, I believe, is in 
keeping with the way the rest of the compiler expects to 
have the cc0 setter and user stay together.


r~


Tue Sep 15 18:24:45 1998  Richard Henderson  <rth@cygnus.com>

        * combine.c (distribute_notes): If an insn is a cc0 user, only
        delete it if we can also delete the cc0 setter.

Index: combine.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/combine.c,v
retrieving revision 1.42
diff -c -p -d -r1.42 combine.c
*** combine.c	1998/08/26 08:11:12	1.42
--- combine.c	1998/09/16 21:10:21
*************** distribute_notes (notes, from_insn, i3, 
*** 11520,11525 ****
--- 11520,11526 ----
  		    {
  		      rtx set = single_set (tem);
  		      rtx inner_dest = 0;
+ 		      rtx cc0_setter = NULL_RTX;
  
  		      if (set != 0)
  			for (inner_dest = SET_DEST (set);
*************** distribute_notes (notes, from_insn, i3, 
*** 11530,11539 ****
  			  ;
  
  		      /* Verify that it was the set, and not a clobber that
! 			 modified the register.  */
  
  		      if (set != 0 && ! side_effects_p (SET_SRC (set))
! 			  && rtx_equal_p (XEXP (note, 0), inner_dest))
  			{
  			  /* Move the notes and links of TEM elsewhere.
  			     This might delete other dead insns recursively. 
--- 11531,11551 ----
  			  ;
  
  		      /* Verify that it was the set, and not a clobber that
! 			 modified the register. 
  
+ 			 CC0 targets must be careful to maintain setter/user
+ 			 pairs.  If we cannot delete the setter due to side
+ 			 effects, mark the user with an UNUSED note instead
+ 			 of deleting it.  */
+ 
  		      if (set != 0 && ! side_effects_p (SET_SRC (set))
! 			  && rtx_equal_p (XEXP (note, 0), inner_dest)
! #ifdef HAVE_cc0
! 			  && (! reg_mentioned_p (cc0_rtx, SET_SRC (set))
! 			      || ((cc0_setter = prev_cc0_setter (tem)) != NULL
! 				  && sets_cc0_p (PATTERN (cc0_setter)) > 0))
! #endif
! 			  )
  			{
  			  /* Move the notes and links of TEM elsewhere.
  			     This might delete other dead insns recursively. 
*************** distribute_notes (notes, from_insn, i3, 
*** 11549,11554 ****
--- 11561,11583 ----
  			  PUT_CODE (tem, NOTE);
  			  NOTE_LINE_NUMBER (tem) = NOTE_INSN_DELETED;
  			  NOTE_SOURCE_FILE (tem) = 0;
+ 
+ #ifdef HAVE_cc0
+ 			  /* Delete the setter too.  */
+ 			  if (cc0_setter)
+ 			    {
+ 			      PATTERN (cc0_setter) = pc_rtx;
+ 
+ 			      distribute_notes (REG_NOTES (cc0_setter),
+ 						cc0_setter, cc0_setter,
+ 						NULL_RTX, NULL_RTX, NULL_RTX);
+ 			      distribute_links (LOG_LINKS (cc0_setter));
+ 
+ 			      PUT_CODE (cc0_setter, NOTE);
+ 			      NOTE_LINE_NUMBER (cc0_setter) = NOTE_INSN_DELETED;
+ 			      NOTE_SOURCE_FILE (cc0_setter) = 0;
+ 			    }
+ #endif
  			}
  		      /* If the register is both set and used here, put the
  			 REG_DEAD note here, but place a REG_UNUSED note


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