[new-regalloc] web_class bugfix

Denis Chertykov denisc@overta.ru
Fri Apr 19 08:32:00 GMT 2002


Hi Michael.

In addition to the following patch I have a patch against ra.c which
realise the following things:
1. Substitute regclass() to web_class();
2. Substitute reg_preferred_class() to web_preferred_class();
3. Use strict register classes (don't use something like reg_alternate_class);
4. Use DF2RA to support earlyclobber ('&') constraints - add conflicts
   between any earlyclobbered operands and all uses of his insn.

With these changes I have only about 250-300 reloads (real reloads which
produced by reload pass) while `make restage2'. It's about 1.5 - 2
reloads for one compiled file.

Produced reloads are:
1. My stupid version of web_class can't split web if it can't have one
   register class. (Few mails ago we have discussed this problem.);
2. Current new-allocator can't eliminate `argp' register (i386 port);
3. Problem with the '=&1' constraint from `fix_truncdi_nomemory'.

What do you think about these ?
Can I commit changes described above ?
(I have bootstrapped C,C++. But, usage of DF2RA seems ugly, but
results seems interesting.)

Also I have changed the following fragment because allocator can't
find webs for spilling.

	  /* CALL_INSNs are not really deaths, but still more registers
	     are free after a call, than before.
	     XXX Note, that sometimes reload barfs when we emit insns between
	     a call and the insn which copies the return register into a 
	     pseudo.  */
	  if (GET_CODE (insn) == CALL_INSN)
	    ri.need_load = 1;
	  else if (INSN_P (insn))
	    for (n = 0; n < info.num_uses; n++)
	      {
		struct web *web = use2web[DF_REF_ID (info.uses[n])];
		struct web *supweb = find_web_for_subweb (web);
		int is_death;
		if (supweb->type == PRECOLORED
		    && TEST_HARD_REG_BIT (never_use_colors, supweb->color))
		  continue;
		is_death = !TEST_BIT (ri.live, supweb->id);
		is_death &= !TEST_BIT (ri.live, web->id);
		if (is_death ||  supweb->type == SPILLED)
---------------------- added ^^^^^^^^^^^^^^^^^^^^^^^^^^^
		  {
		    ri.need_load = 1;
		    bitmap_set_bit (new_deaths, INSN_UID (insn));
		    break;
		  }
	      }
	  



Thu Apr 18 22:36:48 2002  Denis Chertykov  <denisc@overta.ru>

	* pre-reload.h (DF2RA): Remaining parameter added.

	* pre-reload.c (df_link2ra_link): New function. Build array
          for translation df refs to ra_refs.
	(build_df2ra): Use df_link2ra_link.

	* ra.c (web_class): Changed use of DF2RA.

Index: pre-reload.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Attic/pre-reload.h,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 pre-reload.h
*** pre-reload.h	11 Apr 2002 20:31:31 -0000	1.1.2.3
--- pre-reload.h	18 Apr 2002 19:32:30 -0000
*************** struct df2ra
*** 219,224 ****
    ra_ref **use2use;
  };
  extern struct df2ra df2ra;
! #define DF2RA(DF_REF) (*(DF_REF_REG_DEF_P (DF_REF)		\
! 		         ? &df2ra.def2def[DF_REF_ID (DF_REF)]	\
! 		         : &df2ra.use2use[DF_REF_ID (DF_REF)]))
--- 219,224 ----
    ra_ref **use2use;
  };
  extern struct df2ra df2ra;
! #define DF2RA(DF2RA, DF_REF) (*(DF_REF_REG_DEF_P (DF_REF)		\
! 		         ? &(DF2RA).def2def[DF_REF_ID (DF_REF)]	\
! 		         : &(DF2RA).use2use[DF_REF_ID (DF_REF)]))
Index: pre-reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Attic/pre-reload.c,v
retrieving revision 1.1.2.5
diff -c -3 -p -r1.1.2.5 pre-reload.c
*** pre-reload.c	11 Apr 2002 20:31:31 -0000	1.1.2.5
--- pre-reload.c	18 Apr 2002 19:32:49 -0000
*************** build_ra_refs_for_insn (ra_info, def_ref
*** 3739,3744 ****
--- 3739,3816 ----
    return ra_refs;
  }
  
+ 
+ /* Build array for translation all df refs from dlink to ra_refs from
+    ra_link.
+    Return zero if error.  */
+ 
+ static int
+ df_link2ra_link (df2ra, insn, dlink, rlink)
+      struct df2ra df2ra;
+      rtx insn;
+      struct df_link *dlink;
+      struct ra_link *rlink;
+ {
+   unsigned int regno;
+   int bad = 0;
+   
+   if (!link)
+     return 0;
+   
+   for (; dlink; dlink = dlink->next)
+     /* This condition shows which df ref's can't be reached by
+        ra_ref's.  */
+     if (dlink->ref
+ 	&& GET_MODE_CLASS (GET_MODE (DF_REF_REG (dlink->ref))) != MODE_CC
+ 	&& GET_CODE (PATTERN (insn)) != ASM_INPUT
+ 	&& GET_CODE (insn) != CALL_INSN
+ 	&& (DF_REF_REGNO (dlink->ref) < FIRST_PSEUDO_REGISTER
+ 	    ? !fixed_regs[DF_REF_REGNO (dlink->ref)]
+ 	    : 1))
+       {
+ 	struct ra_link *link;
+ 	struct ref *dref = dlink->ref;
+ 	int founded = 0;
+ 	regno = DF_REF_REGNO (dlink->ref);
+ 	
+ 	if (regno < FIRST_PSEUDO_REGISTER)
+ 	  for (link = rlink; link; link = link->next)
+ 	    {
+ 	      ra_ref *ref = link->ref;
+ 	      unsigned int ref_regno = RA_REF_REGNO (ref);
+ 		      
+ 	      if (ref_regno < FIRST_PSEUDO_REGISTER)
+ 		{
+ 		  int i;
+ 		  int nregs = HARD_REGNO_NREGS (ref_regno,
+ 						GET_MODE (ref->reg));
+ 			  
+ 		  for (i = 0; i < nregs; ++i)
+ 		    if (regno == ref_regno + i)
+ 		      {
+ 			founded = 1;
+ 			DF2RA (df2ra, dref) = ref;
+ 			break;
+ 		      }
+ 		}
+ 	    }
+ 	else
+ 	  for (link = rlink;link; link = link->next)
+ 	    {
+ 	      ra_ref *ref = link->ref;
+ 	      if (regno == REGNO (ref->reg))
+ 		{
+ 		  founded = 1;
+ 		  DF2RA (df2ra, dref) = ref;
+ 		  break;
+ 		}
+ 	    }
+ 	if (!founded)
+ 	  bad = 1;
+       }
+   return bad;
+ }
+ 
  struct df2ra
  build_df2ra (df, ra_info)
       struct df *df;
*************** build_df2ra (df, ra_info)
*** 3746,3752 ****
  {
    struct df2ra df2ra;
    rtx insn;
-   unsigned int regno;
      
    df2ra.def2def = xcalloc (df->def_id, sizeof (ra_ref *));
    df2ra.use2use = xcalloc (df->use_id, sizeof (ra_ref *));
--- 3818,3823 ----
*************** build_df2ra (df, ra_info)
*** 3755,3829 ****
       for translation df ref to ra_ref.  */
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
-       int n;
        int bad = 0;
-       struct df_link *dlink = DF_INSN_DEFS (df, insn);
- 
-       for (n = 0; dlink; dlink = dlink->next)
- 	/* This condition shows which df ref's can't be reached by
- 	   ra_ref's.  */
-         if (dlink->ref
- 	    && GET_MODE_CLASS (GET_MODE (DF_REF_REG (dlink->ref))) != MODE_CC
- 	    && GET_CODE (PATTERN (insn)) != ASM_INPUT
- 	    && GET_CODE (insn) != CALL_INSN
- 	    && (DF_REF_REGNO (dlink->ref) < FIRST_PSEUDO_REGISTER
- 		? !fixed_regs[DF_REF_REGNO (dlink->ref)]
- 		: 1))
- 	  {
- 	    struct ref *dref = dlink->ref;
- 	    int founded = 0;
- 	    regno = DF_REF_REGNO (dlink->ref);
  
! 	    if (RA_INSN_REFS (ra_info, insn))
! 	      {
! 		struct ra_link *link;
! 		
! 		if (regno < FIRST_PSEUDO_REGISTER)
! 		  for (link = RA_INSN_DEFS (ra_info, insn);
! 		       link && !founded;
! 		       link = link->next)
! 		    {
! 		      ra_ref *ref = link->ref;
! 		      unsigned int ref_regno = RA_REF_REGNO (ref);
! 		      
! 		      if (ref_regno < FIRST_PSEUDO_REGISTER)
! 			{
! 			  int i;
! 			  int nregs = HARD_REGNO_NREGS (ref_regno,
! 							GET_MODE (ref->reg));
! 			  
! 			  for (i = 0; i < nregs; ++i)
! 			    if (regno == ref_regno + i)
! 			      {
! 				founded = 1;
! 				DF2RA (dref) = ref;
! 				break;
! 			      }
! 			}
! 		    }
! 		else
! 		  for (link = RA_INSN_DEFS (ra_info, insn);
! 		       link && !founded;
! 		       link = link->next)
! 		    {
! 		      ra_ref *ref = link->ref;
! 		      if (regno == REGNO (ref->reg))
! 			{
! 			  founded = 1;
! 			  DF2RA (dref) = ref;
! 			  break;
! 			}
! 		    }
! 	      }
! 	    if (!founded)
! 	      {
! 		bad = 1;
! 	      }
! 	  }
!       /* FIXME denisc@overta.ru  Spilling must be here.
        if (bad)
  	{
! 	  fprintf (stderr, "NONEQUAL: %d\n", regno);
  	  debug_df_insn (insn);
  	  debug_ra_insn_refs (ra_info, insn);
  	}
--- 3826,3844 ----
       for translation df ref to ra_ref.  */
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        int bad = 0;
  
!       if (RA_INSN_REFS (ra_info, insn))
! 	{
! 	  bad = df_link2ra_link (df2ra, insn, DF_INSN_DEFS (df, insn),
! 				 RA_INSN_DEFS (ra_info, insn));
! 	  bad |= df_link2ra_link (df2ra, insn, DF_INSN_USES (df, insn),
! 				  RA_INSN_USES (ra_info, insn));
! 	}
!       /* FIXME denisc@overta.ru
        if (bad)
  	{
! 	  fprintf (stderr, "NONEQUAL: ");
  	  debug_df_insn (insn);
  	  debug_ra_insn_refs (ra_info, insn);
  	}
Index: ra.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Attic/ra.c,v
retrieving revision 1.1.2.52
diff -c -3 -p -r1.1.2.52 ra.c
*** ra.c	10 Apr 2002 16:44:39 -0000	1.1.2.52
--- ra.c	18 Apr 2002 19:33:33 -0000
*************** dump_web_conflicts (web)
*** 9643,9649 ****
  }
  
  void debug_hard_reg_set PARAMS ((HARD_REG_SET));
! /* Output SET to stderr.  */
  void
  debug_hard_reg_set (set)
       HARD_REG_SET set;
--- 9643,9649 ----
  }
  
  void debug_hard_reg_set PARAMS ((HARD_REG_SET));
! /* Output HARD_REG_SET to stderr.  */
  void
  debug_hard_reg_set (set)
       HARD_REG_SET set;
*************** web_class ()
*** 9705,9711 ****
        for (i = 0; i < web->num_defs; ++i)
  	{
  	  dref = web->defs[i];
! 	  rref = DF2RA (dref);
  	  if (rref)
  	    ++class[rref->class];
  	}
--- 9705,9711 ----
        for (i = 0; i < web->num_defs; ++i)
  	{
  	  dref = web->defs[i];
! 	  rref = DF2RA (df2ra, dref);
  	  if (rref)
  	    ++class[rref->class];
  	}
*************** web_class ()
*** 9713,9719 ****
        for (i = 0; i < web->num_uses; ++i)
  	{
  	  dref = web->uses[i];
! 	  rref = DF2RA (dref);
  	  if (rref)
  	    ++class[rref->class];
  	}
--- 9713,9719 ----
        for (i = 0; i < web->num_uses; ++i)
  	{
  	  dref = web->uses[i];
! 	  rref = DF2RA (df2ra, dref);
  	  if (rref)
  	    ++class[rref->class];
  	}
*************** web_class ()
*** 9730,9741 ****
  	      }
  	    else if (!reg_class_subset_p (best, i))
  	      best = NO_REGS;
! /*  	    fprintf (stderr, "%s: %d ", reg_class_names[i], class[i]); */
  	  }
!       /*  fprintf (stderr, " BEST: %s\n", reg_class_names[best]); */
        if (best == NO_REGS)
  	{
! 	  fprintf (stderr, "Web: %d NO_REGS\n", web->id);
  	  best = GENERAL_REGS;
  	}
        reg_class_of_web[n] = best;
--- 9730,9741 ----
  	      }
  	    else if (!reg_class_subset_p (best, i))
  	      best = NO_REGS;
! /*    	    fprintf (stderr, "%s: %d ", reg_class_names[i], class[i]);  */
  	  }
! /*        fprintf (stderr, " BEST: %s\n", reg_class_names[best]); */
        if (best == NO_REGS)
  	{
!     	  fprintf (stderr, "Web: %d (%d) NO_REGS\n", web->id, web->regno);
  	  best = GENERAL_REGS;
  	}
        reg_class_of_web[n] = best;



More information about the Gcc-patches mailing list