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: purge SETs of hard subregs


At present, flow generates incorrect information for SETs of hard
subregs; these can occur when a function's return value has complex
type.  What tends to happen is that we end up with spurious death
notes.  This is because dead_or_set_regno_p () returns 0 for this
case.

We could modify flow (and/or dead_or_set_regno_p ()) to handle this
better, but as the only reason these hard subregs are here is
integrate.c, once integration is done we may as well get rid rid of
these hard subregs so that we aren't bothered by them any longer.
That's what this patch does.

Andrew.

2000-09-15  Andrew Haley  <aph@redhat.com>


	* toplev.c (rest_of_compilation): Call purge_hard_subreg_sets to
	remove all SETs of SUBREGs of hard registers.
 	* function.c (purge_hard_subreg_sets): New function.
	(purge_single_hard_subreg_set): New function.
	* rtl.h: (purge_hard_subreg_sets): New function.

Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.377
diff -p -2 -c -r1.377 toplev.c
*** toplev.c	2000/09/11 21:42:07	1.377
--- toplev.c	2000/09/15 18:30:09
*************** rest_of_compilation (decl)
*** 2824,2832 ****
      TREE_ASM_WRITTEN (decl) = 1;
  
!   /* Now that integrate will no longer see our rtl, we need not distinguish
!      between the return value of this function and the return value of called
!      functions.  */
    rtx_equal_function_value_matters = 0;
! 
    /* Don't return yet if -Wreturn-type; we need to do jump_optimize.  */
    if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
--- 2824,2835 ----
      TREE_ASM_WRITTEN (decl) = 1;
  
!   /* Now that integrate will no longer see our rtl, we need not
!      distinguish between the return value of this function and the
!      return value of called functions.  Also, we can remove all SETs
!      of subregs of hard registers; they are only here because of
!      integrate.*/
    rtx_equal_function_value_matters = 0;
!   purge_hard_subreg_sets (get_insns ());
!   
    /* Don't return yet if -Wreturn-type; we need to do jump_optimize.  */
    if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
Index: function.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/function.c,v
retrieving revision 1.217
diff -p -2 -c -r1.217 function.c
*** function.c	2000/09/01 01:03:29	1.217
--- function.c	2000/09/15 18:30:11
*************** purge_addressof (insns)
*** 3393,3396 ****
--- 3393,3462 ----
    unshare_all_rtl_again (get_insns ());
  }
+ 
+ /* Convert a SET of a hard subreg to a set of the appropriet hard
+    register.  A subroutine of purge_hard_subreg_sets.  */
+ 
+ static void
+ purge_single_hard_subreg_set (pattern)
+      rtx pattern;
+ {
+   rtx reg = SET_DEST (pattern);
+   enum machine_mode mode = GET_MODE (SET_DEST (pattern));
+   int word = 0;
+ 		  
+   while (GET_CODE (reg) == SUBREG)
+     {
+       word += SUBREG_WORD (reg);
+       reg = SUBREG_REG (reg);
+     }
+ 	      
+   if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
+     {
+       reg = gen_rtx_REG (mode, REGNO (reg) + word);
+       SET_DEST (pattern) = reg;
+     }
+ }
+ 
+ /* Eliminate all occurrences of SETs of hard subregs from INSNS.  The
+    only such SETs that we expect to see are those left in because
+    integrate can't handle sets of parts of a return value register.
+ 
+    We don't use alter_subreg because we only want to eliminate subregs
+    of hard registers.  */
+ 
+ void
+ purge_hard_subreg_sets (insn)
+      rtx insn;
+ {
+   for (; insn; insn = NEXT_INSN (insn))
+     {
+       if (INSN_P (insn))
+ 	{
+ 	  rtx pattern = PATTERN (insn);
+ 	  switch (GET_CODE (pattern))
+ 	    {
+ 	    case SET:
+ 	      if (GET_CODE (SET_DEST (pattern)) == SUBREG)
+ 		purge_single_hard_subreg_set (pattern);
+ 	      break;	      
+ 	    case PARALLEL:
+ 	      {
+ 		int j;
+ 		for (j = XVECLEN (pattern, 0) - 1; j >= 0; j--)
+ 		  {
+ 		    rtx inner_pattern = XVECEXP (pattern, 0, j);
+ 		    if (GET_CODE (inner_pattern) == SET
+ 			&& GET_CODE (SET_DEST (inner_pattern)) == SUBREG)
+ 		      purge_single_hard_subreg_set (inner_pattern);
+ 		  }
+ 	      }
+ 	      break;
+ 	    default:
+ 	      break;
+ 	    }
+ 	}
+     }
+ }
  
  /* Pass through the INSNS of function FNDECL and convert virtual register
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.h,v
retrieving revision 1.222
diff -p -2 -c -r1.222 rtl.h
*** rtl.h	2000/09/12 08:39:36	1.222
--- rtl.h	2000/09/15 18:30:11
*************** extern void mark_temp_addr_taken			PARAM
*** 1776,1779 ****
--- 1776,1780 ----
  extern void update_temp_slot_address			PARAMS ((rtx, rtx));
  extern void purge_addressof				PARAMS ((rtx));
+ extern void purge_hard_subreg_sets			PARAMS ((rtx));
  
  /* In reload.c */


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