[new-regalloc]: pre-reload and new allocator

Denis Chertykov denisc@overta.ru
Thu Aug 1 13:20:00 GMT 2002


Patch for integration pre-reload and allocator.
This is a committed patch.
This patch mustn't influence on allocator without
-fnew-ra-pre-reload and -fnew-ra-spanned-deaths-pass.


2002-08-02  Denis Chertykov  <denisc@overta.ru>

	* pre-reload.c (scan_addr_func): Bugfix. Argument ra_info removed.
	(collect_insn_info): this_alternative_address_operand,
	goal_alternative_address_operand, new arrays for handling
	constraint 'p'.
	(pre_reload_collect): Debug a pre-reload process to rtl_dump_file.

	* ra.h (max_normal_pseudo, orig_max_uid): Removed.
	(emitted_by_spill, ra_modified_insns, spill_slot_regs): New bitmaps.
	(is_partly_dead, set_web_live, reset_web_live, reg_class,
	web_class): Prototypes declared.
	(SPILL_SLOT_P): New macro.
	
	* ra-build.c (copy_insn_p): Use SPILL_SLOT_P instead of
	comparision with max_normal_pseudo.
	(detect_spill_temps): Use detect_spanned_deaths if special flag.
	Use bitmap emitted_by_spill instead of orig_max_uid.
	(detect_remat_webs): Use bitmap emitted_by_spill instead of
	orig_max_uid.
	(select_regclass): Use web_class if flag_ra_pre_reload.
	(handle_asm_insn): Use web_preferred_class if flag_ra_pre_reload.
	(detect_spanned_deaths): New function. Calculate spanned deaths
	and spanned defs of webs.

	* ra.c (max_normal_pseudo, orig_max_uid): Removed.
	(emitted_by_spill, ra_modified_insns, spill_slot_regs): New
	bitmaps.
	(init_ra): Definition of orig_max_uid removed.
	Initialization of insns_with_deaths and death_insns_max_uid moved
	to reg_alloc.
	(reg_alloc): Use pre_reload if flag_ra_pre_reload.
	(web_class): New variable "debug" for better controlling of debug
	output.

	* ra-colorize.c (build_worklists): Use SPILL_SLOT_P instead of
	max_normal_pseudo.
	(combine): Likewise.
	(check_colors): Likewise.
	(extended_coalesce_2): Likewise.
	(colorize_one_web): Likewise. Handle flag_ra_pre_reload.

	* ra-debug.c (dump_igraph): Use SPILL_SLOT_P instead of
	max_normal_pseudo.
	(dump_web_insns): Renamed to debug_web_insns. All debugging output
	will be printed to stderr.
	(dump_web_conflicts): Likewise.

	* ra-rewrite.c: Set bit in ra_modified_insns for all insns handled by
	by df_insn_modify.
	Set bit in emitted_by_spill for all emitted insns.
	(allocate_spill_web): Set bit in spill_slot_regs for new spill
	slot register.
	(is_partly_live): Test web->parent_web.
	(emit_loads): Emit loads only for subwebs if super web isn't
	marked for load.
	(is_partly_dead, set_web_live, reset_web_live): New functions.
	Web liveness must be accessed only throught these functions and
	throught is_partly_live.

	(detect_deaths_in_bb): Access web liveness only throught
	is_partly_dead, set_web_live, reset_web_live and is_partly_live.
	(reloads_to_loads): Likewise.
	(rewrite_program2): Likewise.

	* toplev.c (flag_ra_pre_reload): New flag -fnew-ra-pre-reload.
	(flag_ra_spanned_deaths_from_scratch): New flag
	-fnew-ra-spanned-deaths-pass.


Index: pre-reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Attic/pre-reload.c,v
retrieving revision 1.1.2.10
diff -c -3 -p -r1.1.2.10 pre-reload.c
*** pre-reload.c	18 Jul 2002 20:26:01 -0000	1.1.2.10
--- pre-reload.c	1 Aug 2002 20:14:13 -0000
*************** struct scan_addr_state
*** 1913,1921 ****
    char *constraints;
    int modified;			/* Flag for auto modified addresses */
    enum reg_class class;		/* Register class */
  };
  
! static int scan_addr_func            PARAMS ((struct ra_info *, rtx *,
  					      struct scan_addr_state *));
  static ra_ref * scan_addr_create_ref PARAMS ((struct ra_info *, rtx *,
  					      struct scan_addr_state *,
--- 1913,1922 ----
    char *constraints;
    int modified;			/* Flag for auto modified addresses */
    enum reg_class class;		/* Register class */
+   struct ra_info *ra_info;
  };
  
! static int scan_addr_func            PARAMS ((rtx *,
  					      struct scan_addr_state *));
  static ra_ref * scan_addr_create_ref PARAMS ((struct ra_info *, rtx *,
  					      struct scan_addr_state *,
*************** static ra_ref * scan_addr_create_ref PAR
*** 1925,1932 ****
     FIXME: Must be substituted by define_address.  */
  
  static int
! scan_addr_func (ra_info, loc, scan_state)
!      struct ra_info *ra_info;
       rtx *loc;
       struct scan_addr_state *scan_state;
  {
--- 1926,1932 ----
     FIXME: Must be substituted by define_address.  */
  
  static int
! scan_addr_func (loc, scan_state)
       rtx *loc;
       struct scan_addr_state *scan_state;
  {
*************** scan_addr_func (ra_info, loc, scan_state
*** 1939,1945 ****
  	t = RA_REF_ADDRESS | RA_REF_READ;
  	if (scan_state->regs_per_addr == 1)
  	  t |= RA_REF_WRITE;
! 	ref = scan_addr_create_ref (ra_info, loc, scan_state, t);
  	scan_state->class = INDEX_REG_CLASS;
        }
        break;
--- 1939,1945 ----
  	t = RA_REF_ADDRESS | RA_REF_READ;
  	if (scan_state->regs_per_addr == 1)
  	  t |= RA_REF_WRITE;
! 	ref = scan_addr_create_ref (scan_state->ra_info, loc, scan_state, t);
  	scan_state->class = INDEX_REG_CLASS;
        }
        break;
*************** scan_addr_func (ra_info, loc, scan_state
*** 1957,1963 ****
  
  	if (REG_P (x1) && ! REG_P (x0))
  	  {
! 	    scan_addr_func (ra_info, &XEXP (*loc, 1), scan_state);
  	    for_each_rtx (&XEXP (*loc, 0), (rtx_function) scan_addr_func,
  			  scan_state);
  	    return -1;
--- 1957,1963 ----
  
  	if (REG_P (x1) && ! REG_P (x0))
  	  {
! 	    scan_addr_func (&XEXP (*loc, 1), scan_state);
  	    for_each_rtx (&XEXP (*loc, 0), (rtx_function) scan_addr_func,
  			  scan_state);
  	    return -1;
*************** scan_addr_func (ra_info, loc, scan_state
*** 1978,1984 ****
  	if (REG_P (*loc0))
  	  {
  	    ra_ref *ref;
! 	    ref = scan_addr_create_ref (ra_info, loc0, scan_state,
  					RA_REF_ADDRESS | RA_REF_RDWR);
  	    ref->class = BASE_REG_CLASS;
  	    return -1;
--- 1978,1984 ----
  	if (REG_P (*loc0))
  	  {
  	    ra_ref *ref;
! 	    ref = scan_addr_create_ref (scan_state->ra_info, loc0, scan_state,
  					RA_REF_ADDRESS | RA_REF_RDWR);
  	    ref->class = BASE_REG_CLASS;
  	    return -1;
*************** scan_addr_func (ra_info, loc, scan_state
*** 1994,2003 ****
  	if (GET_CODE (*loc0) == SUBREG)
  	  loc0 = &SUBREG_REG (*loc0);
  
! 	if (REG_P (XEXP (*loc0, 0)))
  	  {
  	    ra_ref *ref;
! 	    ref = scan_addr_create_ref (ra_info, &XEXP (*loc0, 0), scan_state,
  					RA_REF_ADDRESS | RA_REF_WRITE);
  	    scan_state->class = BASE_REG_CLASS;
  	    for_each_rtx (&XEXP (*loc, 1), (rtx_function) scan_addr_func,
--- 1994,2004 ----
  	if (GET_CODE (*loc0) == SUBREG)
  	  loc0 = &SUBREG_REG (*loc0);
  
! 	if (REG_P (*loc0))
  	  {
  	    ra_ref *ref;
! 	    ref = scan_addr_create_ref (scan_state->ra_info,
! 					loc0, scan_state,
  					RA_REF_ADDRESS | RA_REF_WRITE);
  	    scan_state->class = BASE_REG_CLASS;
  	    for_each_rtx (&XEXP (*loc, 1), (rtx_function) scan_addr_func,
*************** collect_insn_info (ra_info, insn, def_re
*** 2095,2100 ****
--- 2096,2102 ----
    rtx this_alternative_reg[MAX_RECOG_OPERANDS];
    rtx *this_alternative_reg_loc[MAX_RECOG_OPERANDS];
    char *this_alternative_constraints[MAX_RECOG_OPERANDS];
+   int this_alternative_address_operand[MAX_RECOG_OPERANDS];
    int this_alternative_number;
    int swapped;
    int goal_alternative[MAX_RECOG_OPERANDS];
*************** collect_insn_info (ra_info, insn, def_re
*** 2109,2114 ****
--- 2111,2117 ----
    rtx goal_alternative_reg[MAX_RECOG_OPERANDS];
    rtx *goal_alternative_reg_loc[MAX_RECOG_OPERANDS];
    char *goal_alternative_constraints[MAX_RECOG_OPERANDS];
+   int goal_alternative_address_operand[MAX_RECOG_OPERANDS];
    int goal_alternative_swapped;
    int best;
    int commutative;
*************** collect_insn_info (ra_info, insn, def_re
*** 2470,2475 ****
--- 2473,2479 ----
  	  this_alternative_reg[i] = NULL_RTX;
  	  this_alternative_reg_loc[i] = NULL;
  	  this_alternative_constraints[i] = p;
+ 	  this_alternative_address_operand[i] = 0;
  	  
  	  /* An empty constraint or empty alternative
  	     allows anything which matched the pattern.  */
*************** collect_insn_info (ra_info, insn, def_re
*** 2595,2600 ****
--- 2599,2605 ----
  		/* All necessary reloads for an address_operand
  		   were handled in find_reloads_address.  */
  		this_alternative[i] = (int) BASE_REG_CLASS;
+ 		this_alternative_address_operand[i] = 1;
  		win = 1;
  		break;
  
*************** collect_insn_info (ra_info, insn, def_re
*** 2970,2977 ****
  		= this_alternative_earlyclobber[i];
  	      goal_alternative_reg[i] = this_alternative_reg[i];
  	      goal_alternative_reg_loc[i] = this_alternative_reg_loc[i];
! 	      goal_alternative_constraints[i] =
! 		this_alternative_constraints[i];
  	    }
  	  goal_alternative_swapped = swapped;
  	  best = losers;
--- 2975,2984 ----
  		= this_alternative_earlyclobber[i];
  	      goal_alternative_reg[i] = this_alternative_reg[i];
  	      goal_alternative_reg_loc[i] = this_alternative_reg_loc[i];
! 	      goal_alternative_constraints[i]
! 		= this_alternative_constraints[i];
! 	      goal_alternative_address_operand[i]
! 		= this_alternative_address_operand[i]; 
  	    }
  	  goal_alternative_swapped = swapped;
  	  best = losers;
*************** collect_insn_info (ra_info, insn, def_re
*** 3318,3324 ****
        {
  	opno2ref[i] = 0;
        
! 	if (GET_CODE (recog_data.operand[i]) == MEM)
  	  {
  	    /* FIXME: Now we can only record registers inside address. */
  	    struct scan_addr_state scan_state;
--- 3325,3332 ----
        {
  	opno2ref[i] = 0;
        
! 	if (GET_CODE (recog_data.operand[i]) == MEM
! 	    || goal_alternative_address_operand[i])
  	  {
  	    /* FIXME: Now we can only record registers inside address. */
  	    struct scan_addr_state scan_state;
*************** collect_insn_info (ra_info, insn, def_re
*** 3331,3336 ****
--- 3339,3345 ----
  	    scan_state.constraints = goal_alternative_constraints[i];
  	    scan_state.modified = 0;
  	    scan_state.class = BASE_REG_CLASS;
+ 	    scan_state.ra_info = ra_info;
  	    for_each_rtx (recog_data.operand_loc[i],
  			  (rtx_function) scan_addr_func, &scan_state);
  	    def_refs = scan_state.defs;
*************** build_df2ra (df, ra_info)
*** 3817,3824 ****
    struct df2ra df2ra;
    rtx insn;
      
!   df2ra.def2def = xcalloc (df->def_id, sizeof (ra_ref *));
!   df2ra.use2use = xcalloc (df->use_id, sizeof (ra_ref *));
    
    /* Check ra_info by comparing it with the df info and build array
       for translation df ref to ra_ref.  */
--- 3826,3833 ----
    struct df2ra df2ra;
    rtx insn;
      
!   df2ra.def2def = xcalloc (df->def_id + 1, sizeof (ra_ref *));
!   df2ra.use2use = xcalloc (df->use_id + 1, sizeof (ra_ref *));
    
    /* Check ra_info by comparing it with the df info and build array
       for translation df ref to ra_ref.  */
*************** build_df2ra (df, ra_info)
*** 3833,3846 ****
  	  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);
  	}
-       */
      }
    return df2ra;
  }
--- 3842,3854 ----
  	  bad |= df_link2ra_link (df2ra, insn, DF_INSN_USES (df, insn),
  				  RA_INSN_USES (ra_info, insn));
  	}
!       /* FIXME denisc@overta.ru */
!       if (bad & 0)
  	{
  	  fprintf (stderr, "NONEQUAL: ");
  	  debug_df_insn (insn);
  	  debug_ra_insn_refs (ra_info, insn);
  	}
      }
    return df2ra;
  }
*************** pre_reload_collect (ra_info, modified)
*** 3923,3928 ****
--- 3931,3937 ----
  	  rtx prev;
  	  rtx next;
  	  rtx orig_insn;
+ 	  rtx deb_insn;
  
  	  if (modified && !bitmap_bit_p (modified, INSN_UID (insn)))
  	    continue;
*************** pre_reload_collect (ra_info, modified)
*** 3959,3966 ****
--- 3968,3996 ----
  	      if (n_reloads)
  		{
  		  rtx before = PREV_INSN (insn);
+ 		  rtx after = NEXT_INSN (insn);
+ 
+ 		  if (rtl_dump_file)
+ 		    {
+ 		      fprintf (rtl_dump_file, "Reload for insn:\n");
+ 		      print_rtl_single (rtl_dump_file, insn);
+ 		      fprintf (rtl_dump_file, "\n");
+ 		    }
+ 		  
  		  emit_pre_reload_insns (insn);
  		  subst_pre_reloads (insn);
+ 		  
+ 		  if (rtl_dump_file)
+ 		    {
+ 		      fprintf (rtl_dump_file, "Reload results:\n");
+ 		      for (deb_insn = NEXT_INSN (before); deb_insn != after;
+ 			   deb_insn = NEXT_INSN (deb_insn))
+ 			{
+ 			  print_rtl_single (rtl_dump_file, deb_insn);
+ 			  fprintf (rtl_dump_file, "\n");
+ 			}
+ 		    }
+ 		  
  		  insn = NEXT_INSN (before);
  		  continue;
  		}
Index: ra-build.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ra-build.c,v
retrieving revision 1.1.2.4
diff -c -3 -p -r1.1.2.4 ra-build.c
*** ra-build.c	24 Jul 2002 23:21:02 -0000	1.1.2.4
--- ra-build.c	1 Aug 2002 20:14:58 -0000
*************** static void init_bb_info PARAMS ((void))
*** 117,122 ****
--- 117,123 ----
  static void free_bb_info PARAMS ((void));
  static void build_web_parts_and_conflicts PARAMS ((struct df *));
  static void select_regclass PARAMS ((void));
+ static void detect_spanned_deaths PARAMS ((unsigned int *spanned_deaths));
  
  
  /* A sbitmap of DF_REF_IDs of uses, which are live over an abnormal
*************** copy_insn_p (insn, source, target)
*** 275,282 ****
    /* Copies between hardregs are useless for us, as not coalesable anyway. */
    if ((s_regno < FIRST_PSEUDO_REGISTER
         && d_regno < FIRST_PSEUDO_REGISTER)
!       || s_regno >= max_normal_pseudo
!       || d_regno >= max_normal_pseudo)
      return 0;
  
    if (source)
--- 276,283 ----
    /* Copies between hardregs are useless for us, as not coalesable anyway. */
    if ((s_regno < FIRST_PSEUDO_REGISTER
         && d_regno < FIRST_PSEUDO_REGISTER)
!       || SPILL_SLOT_P (s_regno)
!       || SPILL_SLOT_P (d_regno))
      return 0;
  
    if (source)
*************** detect_spill_temps ()
*** 2275,2281 ****
--- 2276,2289 ----
  {
    struct dlist *d;
    bitmap already = BITMAP_XMALLOC ();
+   unsigned int *spanned_deaths_from_scratch;
  
+   if (flag_ra_spanned_deaths_from_scratch)
+     {
+       spanned_deaths_from_scratch
+ 	= (unsigned  *)xcalloc (sizeof (int), num_webs);
+       detect_spanned_deaths (spanned_deaths_from_scratch);
+     }
    /* Detect webs used for spill temporaries.  */
    for (d = WEBS(INITIAL); d; d = d->next)
      {
*************** detect_spill_temps ()
*** 2312,2321 ****
  	  unsigned int i;
  	  int spill_involved = 0;
  	  for (i = 0; i < web->num_uses && !spill_involved; i++)
! 	    if (DF_REF_INSN_UID (web->uses[i]) >= orig_max_uid)
  	      spill_involved = 1;
  	  for (i = 0; i < web->num_defs && !spill_involved; i++)
! 	    if (DF_REF_INSN_UID (web->defs[i]) >= orig_max_uid)
  	      spill_involved = 1;
  
  	  if (spill_involved/* && ra_pass > 2*/)
--- 2320,2331 ----
  	  unsigned int i;
  	  int spill_involved = 0;
  	  for (i = 0; i < web->num_uses && !spill_involved; i++)
! 	    if (bitmap_bit_p (emitted_by_spill,
! 			      DF_REF_INSN_UID (web->uses[i])))
  	      spill_involved = 1;
  	  for (i = 0; i < web->num_defs && !spill_involved; i++)
! 	    if (bitmap_bit_p (emitted_by_spill,
! 			      DF_REF_INSN_UID (web->defs[i])))
  	      spill_involved = 1;
  
  	  if (spill_involved/* && ra_pass > 2*/)
*************** detect_spill_temps ()
*** 2334,2355 ****
  		 dead web), so reduce the number of spanned deaths by those
  		 insns.  Note that sometimes such deaths are _not_ counted,
  	         so negative values can result.  */
! 	      bitmap_zero (already);
! 	      for (i = 0; i < web->num_defs; i++)
  		{
! 		  rtx insn = web->defs[i]->insn;
! 		  if (TEST_BIT (insns_with_deaths, INSN_UID (insn))
! 		      && !bitmap_bit_p (already, INSN_UID (insn)))
  		    {
! 		      unsigned int j;
! 		      bitmap_set_bit (already, INSN_UID (insn));
! 		      /* Only decrement it once for each insn.  */
! 		      for (j = 0; j < web->num_uses; j++)
! 			if (web->uses[j]->insn == insn)
! 			  {
! 			    num_deaths--;
! 			    break;
! 			  }
  		    }
  		}
  	      /* But mark them specially if they could possibly be spilled,
--- 2344,2370 ----
  		 dead web), so reduce the number of spanned deaths by those
  		 insns.  Note that sometimes such deaths are _not_ counted,
  	         so negative values can result.  */
! 	      if (flag_ra_spanned_deaths_from_scratch)
! 		num_deaths = spanned_deaths_from_scratch[web->id];
! 	      else
  		{
! 		  bitmap_zero (already);
! 		  for (i = 0; i < web->num_defs; i++)
  		    {
! 		      rtx insn = web->defs[i]->insn;
! 		      if (TEST_BIT (insns_with_deaths, INSN_UID (insn))
! 			  && !bitmap_bit_p (already, INSN_UID (insn)))
! 			{
! 			  unsigned int j;
! 			  bitmap_set_bit (already, INSN_UID (insn));
! 			  /* Only decrement it once for each insn.  */
! 			  for (j = 0; j < web->num_uses; j++)
! 			    if (web->uses[j]->insn == insn)
! 			      {
! 				num_deaths--;
! 				break;
! 			      }
! 			}
  		    }
  		}
  	      /* But mark them specially if they could possibly be spilled,
*************** detect_spill_temps ()
*** 2363,2374 ****
  	     change making the graph not easier to color.  Make this also
  	     a short web.  Don't do this if it crosses calls, as these are
  	     also points of reloads.  */
! 	  else if (web->span_deaths == 0 && !web->crosses_call)
  	    web->spill_temp = 3;
  	}
        web->orig_spill_temp = web->spill_temp;
      }
    BITMAP_XFREE (already);
  }
  
  /* Returns nonzero if the rtx MEM refers somehow to a stack location.  */
--- 2378,2394 ----
  	     change making the graph not easier to color.  Make this also
  	     a short web.  Don't do this if it crosses calls, as these are
  	     also points of reloads.  */
! 	  else if ((flag_ra_spanned_deaths_from_scratch
! 		    ? spanned_deaths_from_scratch[web->id] == 0
! 		    : web->span_deaths == 0)
! 		   && !web->crosses_call)
  	    web->spill_temp = 3;
  	}
        web->orig_spill_temp = web->spill_temp;
      }
    BITMAP_XFREE (already);
+   if (flag_ra_spanned_deaths_from_scratch)
+     free (spanned_deaths_from_scratch);
  }
  
  /* Returns nonzero if the rtx MEM refers somehow to a stack location.  */
*************** detect_remat_webs ()
*** 2520,2526 ****
  		  unchanging flag set, but nevertheless they are stable across
  		  the livetime in question.  */
  	       || (GET_CODE (src) == MEM
! 		   && INSN_UID (insn) >= orig_max_uid
  		   && memref_is_stack_slot (src)))
  	      /* And we must be able to construct an insn without
  		 side-effects to actually load that value into a reg.  */
--- 2540,2546 ----
  		  unchanging flag set, but nevertheless they are stable across
  		  the livetime in question.  */
  	       || (GET_CODE (src) == MEM
! 		   && bitmap_bit_p (emitted_by_spill, INSN_UID (insn))
  		   && memref_is_stack_slot (src)))
  	      /* And we must be able to construct an insn without
  		 side-effects to actually load that value into a reg.  */
*************** static void
*** 2627,2637 ****
  select_regclass ()
  {
    struct dlist *d;
    
    for (d = WEBS(INITIAL); d; d = d->next)
      {
        int i;
-       struct web *w;
        struct web *web = DLIST_WEB (d);
        do
  	{
--- 2647,2659 ----
  select_regclass ()
  {
    struct dlist *d;
+ 
+   if (flag_ra_pre_reload)
+     web_class ();
    
    for (d = WEBS(INITIAL); d; d = d->next)
      {
        int i;
        struct web *web = DLIST_WEB (d);
        do
  	{
*************** select_regclass ()
*** 2639,2674 ****
  
  	  if (web->regno < FIRST_PSEUDO_REGISTER)
  	    continue;
! 
! 	  if ((web->spill_temp == 1 || web->spill_temp == 2)
! 	      && ! web->changed
! 	      && web->type == INITIAL)
  	    {
! 	      if (web->regno >= max_normal_pseudo)
  		{
  		  COPY_HARD_REG_SET (web->usable_regs,
! 				     reg_class_contents
! 				     [reg_preferred_class (web->regno)]);
  		  IOR_HARD_REG_SET (web->usable_regs,
  				    reg_class_contents
  				    [reg_alternate_class (web->regno)]);
  		}
- 	      else
- 		COPY_HARD_REG_SET (web->usable_regs,
- 				   reg_class_contents[(int) ALL_REGS]);
  	    }
- 	  else
- 	    {
- 	      web->regclass = reg_preferred_class (web->regno);
- 	      if (web->regclass == NO_REGS)
- 		abort ();
- 	      COPY_HARD_REG_SET (web->usable_regs,
- 				 reg_class_contents[web->regclass]);
- 	      IOR_HARD_REG_SET (web->usable_regs,
- 				reg_class_contents
- 				[reg_alternate_class (web->regno)]);
- 	    }
-       
  	  /* add_hardregs is wrong in multi-length classes, e.g.
  	     using a DFmode pseudo on x86 can result in class FLOAT_INT_REGS,
  	     where, if it finally is allocated to GENERAL_REGS it needs two,
--- 2661,2703 ----
  
  	  if (web->regno < FIRST_PSEUDO_REGISTER)
  	    continue;
! 	  
! 	  if (flag_ra_pre_reload)
! 	    {
! 	      web->regclass = web_preferred_class (web);
! 	      COPY_HARD_REG_SET (web->usable_regs,
! 				 reg_class_contents [web->regclass]);
! 	    }
! 	  else
  	    {
! 	      if ((web->spill_temp == 1 || web->spill_temp == 2)
! 		  && ! web->changed)
! 		{
! 		  if (SPILL_SLOT_P (web->regno))
! 		    {
! 		      COPY_HARD_REG_SET (web->usable_regs,
! 					 reg_class_contents
! 					 [reg_preferred_class (web->regno)]);
! 		      IOR_HARD_REG_SET (web->usable_regs,
! 					reg_class_contents
! 					[reg_alternate_class (web->regno)]);
! 		    }
! 		  else
! 		    COPY_HARD_REG_SET (web->usable_regs,
! 				       reg_class_contents[(int) ALL_REGS]);
! 		}
! 	      else
  		{
+ 		  web->regclass = reg_preferred_class (web->regno);
+ 		  if (web->regclass == NO_REGS)
+ 		    abort ();
  		  COPY_HARD_REG_SET (web->usable_regs,
! 				     reg_class_contents[web->regclass]);
  		  IOR_HARD_REG_SET (web->usable_regs,
  				    reg_class_contents
  				    [reg_alternate_class (web->regno)]);
  		}
  	    }
  	  /* add_hardregs is wrong in multi-length classes, e.g.
  	     using a DFmode pseudo on x86 can result in class FLOAT_INT_REGS,
  	     where, if it finally is allocated to GENERAL_REGS it needs two,
*************** select_regclass ()
*** 2684,2690 ****
  
  	  if ((web->spill_temp == 1 || web->spill_temp == 2)
  	      && ! web->changed
! 	      && web->type == INITIAL)
  	    {
  	      /* Now look for a class, which is subset of our constraints, to
  		 setup add_hardregs, and regclass for debug output.  */
--- 2713,2719 ----
  
  	  if ((web->spill_temp == 1 || web->spill_temp == 2)
  	      && ! web->changed
! 	      && ! flag_ra_pre_reload)
  	    {
  	      /* Now look for a class, which is subset of our constraints, to
  		 setup add_hardregs, and regclass for debug output.  */
*************** handle_asm_insn (df, insn)
*** 2976,2985 ****
  	}
        else
  	{
! 	  COPY_HARD_REG_SET (conflict, usable_regs
! 			     [reg_preferred_class (web->regno)]);
! 	  IOR_HARD_REG_SET (conflict, usable_regs
! 			    [reg_alternate_class (web->regno)]);
  	  AND_COMPL_HARD_REG_SET (conflict, allowed);
  	  /* We can't yet establish these conflicts.  Reload must go first
  	     (or better said, we must implement some functionality of reload).
--- 3005,3020 ----
  	}
        else
  	{
! 	  if (flag_ra_pre_reload)
! 	    COPY_HARD_REG_SET (conflict,
! 			       usable_regs [web_preferred_class (web)]);
! 	  else
! 	    {
! 	      COPY_HARD_REG_SET (conflict, usable_regs
! 				 [reg_preferred_class (web->regno)]);
! 	      IOR_HARD_REG_SET (conflict, usable_regs
! 				[reg_alternate_class (web->regno)]);
! 	    }
  	  AND_COMPL_HARD_REG_SET (conflict, allowed);
  	  /* We can't yet establish these conflicts.  Reload must go first
  	     (or better said, we must implement some functionality of reload).
*************** ra_build_free_all (df)
*** 3251,3256 ****
--- 3286,3507 ----
    free (def2web);
    use2web = NULL;
    def2web = NULL;
+ }
+ 
+ static void
+ detect_spanned_deaths (spanned_deaths)
+      unsigned int *spanned_deaths;
+ {
+   rtx insn, head_prev;
+   unsigned int j;
+   basic_block bb;
+   unsigned int i;
+   bitmap already ATTRIBUTE_UNUSED;
+   int debug = 0;
+   sbitmap live = sbitmap_alloc (num_webs);
+   sbitmap rmw_web = sbitmap_alloc (num_webs);
+   sbitmap defs_per_insn = sbitmap_alloc (num_webs);
+ 
+   if (debug)
+     {
+       already = BITMAP_XMALLOC ();
+       fprintf (stderr, ":::: Detect_spanned_deaths :::\n");
+     }
+   
+   FOR_ALL_BB (bb)
+     {
+       if (!bb->end)
+ 	continue;
+       
+       insn = bb->end;
+       if (!INSN_P (insn))
+ 	insn = prev_real_insn (insn);
+       
+       /* Empty block?  */
+       if (!insn || BLOCK_FOR_INSN (insn) != bb)
+ 	continue;
+ 
+       head_prev = PREV_INSN (bb->head);
+       sbitmap_zero (live);
+       
+       if(debug)
+ 	{
+ 	  fprintf (stderr, "live_at_end[%d]", bb->index); 
+ 	  bitmap_clear (already);
+ 	}
+ 
+       EXECUTE_IF_SET_IN_BITMAP
+ 	(live_at_end[bb->index], 0, j,
+ 	 { 
+ 	   struct web *web = use2web[j];
+ 	   struct web *aweb = alias (find_web_for_subweb (web));
+ 	   set_web_live (live, aweb);
+ 	   if (debug)
+ 	     if (! bitmap_bit_p (already, aweb->id))
+ 	       {
+ 		 fprintf (stderr, " %d", aweb->id);
+ 		 bitmap_set_bit (already, aweb->id);
+ 	       }
+ 	 });
+       
+       if (debug)
+ 	fprintf (stderr, "\n");
+ 
+       for (; insn != head_prev; insn = PREV_INSN (insn))
+ 	{
+ 	  struct ra_insn_info info;
+ 	  unsigned int n;
+ 
+ 	  if (!INSN_P (insn))
+ 	    continue;
+ 
+ 	  sbitmap_zero (rmw_web);
+ 	      
+ 	  info = insn_df[INSN_UID (insn)];
+ 
+ 	  if (debug > 1)
+ 	    {
+ 	      fprintf (stderr, "insn %d defs %d uses %d\n", INSN_UID (insn),
+ 		       info.num_defs, info.num_uses);
+ 	    }
+ 	  
+ 	  for (n = 0; n < info.num_defs; n++)
+ 	    {
+ 	      struct web *web;
+ 	      struct web *sweb;
+ 	      unsigned int n2;
+ 	      struct ref *ref = info.defs[n];
+ 	      struct web *subweb = def2web[DF_REF_ID (ref)];
+ 	      int is_non_def = 0;
+ 
+ 	      web = find_web_for_subweb (subweb);
+ 	      /* Detect rmw webs.  */
+ 	      for (n2 = 0; n2 < info.num_uses; n2++)
+ 		{
+ 		  struct web *web2 = use2web[DF_REF_ID (info.uses[n2])];
+ 		  if (web == find_web_for_subweb (web2))
+ 		    {
+ 		      SET_BIT (rmw_web, web->id);
+ 		      SET_BIT (rmw_web, web2->id);
+ 		      is_non_def = 1;
+ 		    }
+ 		}
+ 	      if (is_non_def)
+ 		{
+ 		  if (debug > 1)
+ 		    fprintf (stderr, "    web %d RMW\n", web->id);
+ 		  continue;
+ 		}
+ 
+ 	      reset_web_live (live, web);
+ 	      
+ 	      SET_BIT (defs_per_insn, web->id);
+ 	      if (!web->parent_web)
+ 		for (sweb = web->subreg_next; sweb;
+ 		     sweb = sweb->subreg_next)
+ 		  SET_BIT (defs_per_insn, sweb->id);
+ 	      
+ 	      if (debug > 1)
+ 		{
+ 		  struct web *sweb;
+ 		  fprintf (stderr, "    web %d dead\n", subweb->id);
+ 		  if (!web->parent_web)
+ 		    for (sweb = web->subreg_next; sweb;
+ 			 sweb = sweb->subreg_next)
+ 		      fprintf (stderr, "    sweb %d dead\n", sweb->id);
+ 		} 
+ 	    }
+ #if 1
+ 	  EXECUTE_IF_SET_IN_SBITMAP
+ 	    (defs_per_insn, 0, n,
+ 	     {
+ 	       RESET_BIT (defs_per_insn, n);
+ 	       EXECUTE_IF_SET_IN_SBITMAP
+ 		 (live, 0, i,
+ 		  {
+ 		    if (! bitmap_bit_p (emitted_by_spill, INSN_UID (insn)))
+ 		      {
+ 			struct web *supweb;
+ 			supweb = find_web_for_subweb (id2web[i]);
+ 			spanned_deaths[i]++;
+ 			if (supweb && i != supweb->id)
+ 			  spanned_deaths[supweb->id]++;
+ 			   
+ 			if (debug)
+ 			  {
+ 			    if (i != supweb->id)
+ 			      fprintf (stderr, " %d.%d", supweb->id, i);
+ 			    else
+ 			      fprintf (stderr, " %d", i);
+ 			  }
+ 		      }
+ 		  });
+ 	     });
+ 	  if (debug)
+ 	    fprintf (stderr, "\n");
+ #endif
+ 	  for (n = 0; n < info.num_uses; n++)
+ 	    {
+ 	      struct web *web = use2web[DF_REF_ID (info.uses[n])];
+ 	      if (is_partly_dead (live, web))
+ 		{
+ 		  if (debug)
+ 		    fprintf (stderr, "    Death web %d in insn: %d ++",
+ 			     web->id, INSN_UID(insn));
+ 
+ 		  EXECUTE_IF_SET_IN_SBITMAP
+ 		    (live, 0, i,
+ 		     {
+ 		       if (! bitmap_bit_p (emitted_by_spill, INSN_UID (insn))
+   			   && ! TEST_BIT (rmw_web, i))
+ 			 {
+ 			   struct web *supweb;
+ 			   supweb = find_web_for_subweb (id2web[i]);
+ 			   spanned_deaths[i]++;
+ 			   if (supweb && i != supweb->id)
+ 			     spanned_deaths[supweb->id]++;
+ 			   
+ 			   if (debug)
+ 			     {
+ 			       if (i != supweb->id)
+ 				 fprintf (stderr, " %d.%d", supweb->id, i);
+ 			       else
+ 				 fprintf (stderr, " %d", i);
+ 			     }
+ 			 }
+ 		     });
+ 		  if (debug)
+ 		    fprintf (stderr, "\n");
+ 		}
+ 	    }
+ 	  
+ 	  for (n = 0; n < info.num_uses; n++)
+ 	    {
+ 	      struct web *web = use2web[DF_REF_ID (info.uses[n])];
+ 	      if (web->regno >= FIRST_PSEUDO_REGISTER)
+ 		set_web_live (live, web);
+ 	    }
+ 	}
+     }
+ 
+   if (debug)
+     {
+       for (j = 0; j < num_webs - num_subwebs; ++j)
+ 	{
+ 	  struct web *web = id2web[j];
+ 	  if (web->type != PRECOLORED)
+ 	    fprintf (stderr, "Web: %d (%d) spanned from web: %d %s %d\n",
+ 		     j, web->regno,
+ 		     web->span_deaths,
+ 		     web->span_deaths == spanned_deaths[web->id] ? "==" : "!=",
+ 		     spanned_deaths[web->id]);
+ 	}
+       BITMAP_XFREE (already);
+       ra_print_rtl_with_bb (stderr,get_insns());
+     }
+   sbitmap_free (live);
+   sbitmap_free (rmw_web);
+   sbitmap_free (defs_per_insn);
  }
  
  #include "gt-ra-build.h"
Index: ra.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ra.c,v
retrieving revision 1.1.2.61
diff -c -3 -p -r1.1.2.61 ra.c
*** ra.c	16 Jul 2002 19:52:44 -0000	1.1.2.61
--- ra.c	1 Aug 2002 20:15:09 -0000
*************** short *ra_reg_renumber;
*** 132,138 ****
  struct df *df;
  bitmap *live_at_end;
  int ra_pass;
- unsigned int max_normal_pseudo;
  int an_unusable_color;
  
  /* The different lists on which a web can be (based on the type).  */
--- 132,137 ----
*************** int last_max_uid;
*** 145,165 ****
  sbitmap last_check_uses;
  unsigned int remember_conflicts;
  
- int orig_max_uid;
- 
  HARD_REG_SET never_use_colors;
  HARD_REG_SET usable_regs[N_REG_CLASSES];
  unsigned int num_free_regs[N_REG_CLASSES];
  HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES];
  unsigned char byte2bitcount[256];
  
! #if 0
  extern struct df2ra build_df2ra PARAMS ((struct df*, struct ra_info*));
  static struct ra_info *ra_info;
- #endif
  struct df2ra df2ra;
- static enum reg_class web_preferred_class PARAMS ((struct web *));
- void web_class PARAMS ((void));
  
  unsigned int debug_new_regalloc = -1;
  int flag_ra_dump_only_costs = 0;
--- 144,169 ----
  sbitmap last_check_uses;
  unsigned int remember_conflicts;
  
  HARD_REG_SET never_use_colors;
  HARD_REG_SET usable_regs[N_REG_CLASSES];
  unsigned int num_free_regs[N_REG_CLASSES];
  HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES];
  unsigned char byte2bitcount[256];
  
! /* Used to detect spill instructions inserted by me.  */
! bitmap emitted_by_spill;
! 
! /* Tracking pseudos generated for spill slots by rewrite.  */
! bitmap spill_slot_regs;
! 
! /* Tracking insns modified/deleted/emitted by allocator in current pass.  */
! bitmap ra_modified_insns;
! 
! static enum reg_class *reg_class_of_web;
! 
  extern struct df2ra build_df2ra PARAMS ((struct df*, struct ra_info*));
  static struct ra_info *ra_info;
  struct df2ra df2ra;
  
  unsigned int debug_new_regalloc = -1;
  int flag_ra_dump_only_costs = 0;
*************** init_ra ()
*** 574,585 ****
    if (an_unusable_color == FIRST_PSEUDO_REGISTER)
      abort ();
  
-   orig_max_uid = get_max_uid ();
    compute_bb_for_insn ();
    ra_reg_renumber = NULL;
!   insns_with_deaths = sbitmap_alloc (orig_max_uid);
!   death_insns_max_uid = orig_max_uid;
!   sbitmap_ones (insns_with_deaths);
    gcc_obstack_init (&ra_obstack);
  }
  
--- 578,588 ----
    if (an_unusable_color == FIRST_PSEUDO_REGISTER)
      abort ();
  
    compute_bb_for_insn ();
    ra_reg_renumber = NULL;
!   insns_with_deaths = NULL;
!   emitted_by_spill = BITMAP_XMALLOC ();
!   spill_slot_regs = BITMAP_XMALLOC ();
    gcc_obstack_init (&ra_obstack);
  }
  
*************** reg_alloc ()
*** 737,743 ****
    int changed;
    FILE *ra_dump_file = rtl_dump_file;
    rtx last = get_last_insn ();
! 
    if (! INSN_P (last))
      last = prev_real_insn (last);
    /* If this is an empty function we shouldn't do all the following,
--- 740,749 ----
    int changed;
    FILE *ra_dump_file = rtl_dump_file;
    rtx last = get_last_insn ();
!   /*
!   flag_ra_pre_reload = 0;
!   flag_ra_spanned_deaths_from_scratch = 0;
!   */
    if (! INSN_P (last))
      last = prev_real_insn (last);
    /* If this is an empty function we shouldn't do all the following,
*************** reg_alloc ()
*** 787,808 ****
       explicitely requested.  */
    if ((debug_new_regalloc & DUMP_REGCLASS) == 0)
      rtl_dump_file = NULL;
!   regclass (get_insns (), max_reg_num (), rtl_dump_file);
!   rtl_dump_file = ra_dump_file;
! 
! /*  ra_info = ra_info_init (max_reg_num ());
!   pre_reload (ra_info);
!   {
!     allocate_reg_info (max_reg_num (), FALSE, FALSE);
!     compute_bb_for_insn ();
!     delete_trivially_dead_insns (get_insns (), max_reg_num ());
!     reg_scan_update (get_insns (), BLOCK_END (n_basic_blocks - 1),
! 		     max_regno);
!     max_regno = max_reg_num ();
      regclass (get_insns (), max_reg_num (), rtl_dump_file);
!   }
!   ra_info_free (ra_info);
!   free (ra_info);*/
  
    /* XXX the REG_EQUIV notes currently are screwed up, when pseudos are
       coalesced, which have such notes.  In that case, the whole combined
--- 793,801 ----
       explicitely requested.  */
    if ((debug_new_regalloc & DUMP_REGCLASS) == 0)
      rtl_dump_file = NULL;
!   if (!flag_ra_pre_reload)
      regclass (get_insns (), max_reg_num (), rtl_dump_file);
!   rtl_dump_file = ra_dump_file;
  
    /* XXX the REG_EQUIV notes currently are screwed up, when pseudos are
       coalesced, which have such notes.  In that case, the whole combined
*************** reg_alloc ()
*** 819,825 ****
    /* And some global variables.  */
    ra_pass = 0;
    no_new_pseudos = 0;
-   max_normal_pseudo = (unsigned) max_reg_num ();
    ra_rewrite_init ();
    last_def_id = 0;
    last_use_id = 0;
--- 812,817 ----
*************** reg_alloc ()
*** 850,856 ****
  
    /* Allocate the global df structure.  */
    df = df_init ();
! 
    /* This is the main loop, calling one_pass as long as there are still
       some spilled webs.  */
    do
--- 842,854 ----
  
    /* Allocate the global df structure.  */
    df = df_init ();
!   ra_modified_insns = NULL;
!   if (flag_ra_pre_reload)
!     {
!       ra_info = ra_info_init (max_reg_num ());
!       reg_class_of_web = NULL;
!     }
!   
    /* This is the main loop, calling one_pass as long as there are still
       some spilled webs.  */
    do
*************** reg_alloc ()
*** 859,882 ****
        if (ra_pass++ > 40)
  	internal_error ("Didn't find a coloring.\n");
  
!       /* FIXME denisc@overta.ru
! 	 Example of usage ra_info ... routines */
! #if 0
!       ra_info = ra_info_init (max_reg_num ());
!       pre_reload (ra_info);
  
!       {
! 	allocate_reg_info (max_reg_num (), FALSE, FALSE);
! 	compute_bb_for_insn ();
! 	delete_trivially_dead_insns (get_insns (), max_reg_num ());
! 	reg_scan_update (get_insns (), BLOCK_END (n_basic_blocks - 1),
! 			 max_regno);
! 	max_regno = max_reg_num ();
! 	regclass (get_insns (), max_reg_num (), rtl_dump_file);
! 	orig_max_uid = get_max_uid ();
! 	death_insns_max_uid = orig_max_uid;
!       }
! #endif
  
        /* First collect all the register refs and put them into
  	 chains per insn, and per regno.  In later passes only update
--- 857,884 ----
        if (ra_pass++ > 40)
  	internal_error ("Didn't find a coloring.\n");
  
!       if (flag_ra_pre_reload)
! 	pre_reload (ra_info, ra_modified_insns);
  
!       if (!ra_modified_insns)
! 	ra_modified_insns = BITMAP_XMALLOC ();
!       else
! 	bitmap_clear (ra_modified_insns);
! 
!       if (!insns_with_deaths)
! 	{
! 	  death_insns_max_uid = get_max_uid ();
! 	  insns_with_deaths = sbitmap_alloc (death_insns_max_uid);
! 	  sbitmap_ones (insns_with_deaths);
! 	}
! 
!       if (flag_ra_pre_reload)
! 	{
! 	  allocate_reg_info (max_reg_num (), FALSE, FALSE);
! 	  compute_bb_for_insn ();
! 	  reg_scan_update (get_insns (), NULL, max_regno);
! 	  max_regno = max_reg_num ();
! 	}
  
        /* First collect all the register refs and put them into
  	 chains per insn, and per regno.  In later passes only update
*************** reg_alloc ()
*** 884,894 ****
        df_analyse (df, (ra_pass == 1) ? 0 : (bitmap) -1,
  		  DF_HARD_REGS | DF_RD_CHAIN | DF_RU_CHAIN);
  
!       /* FIXME denisc@overta.ru
! 	 Example of usage ra_info ... routines */
! #if 0
!       df2ra = build_df2ra (df, ra_info);
! #endif
        if ((debug_new_regalloc & DUMP_DF) != 0)
  	{
  	  rtx insn;
--- 886,894 ----
        df_analyse (df, (ra_pass == 1) ? 0 : (bitmap) -1,
  		  DF_HARD_REGS | DF_RD_CHAIN | DF_RU_CHAIN);
  
!       if (flag_ra_pre_reload)
! 	df2ra = build_df2ra (df, ra_info);
! 
        if ((debug_new_regalloc & DUMP_DF) != 0)
  	{
  	  rtx insn;
*************** reg_alloc ()
*** 914,927 ****
        if (rtl_dump_file)
          print_rtl_with_bb (rtl_dump_file, get_insns ());
        verify_flow_info ();*/
!       /* FIXME denisc@overta.ru
! 	 Example of usage ra_info ... routines */
! #if 0
!       ra_info_free (ra_info);
!       free (df2ra.def2def);
!       free (df2ra.use2use);
!       free (ra_info);
! #endif
  
        /* If that produced no changes, the graph was colorizable.  */
        if (!changed)
--- 914,925 ----
        if (rtl_dump_file)
          print_rtl_with_bb (rtl_dump_file, get_insns ());
        verify_flow_info ();*/
! 
!       if (flag_ra_pre_reload)
! 	{
! 	  free (df2ra.def2def);
! 	  free (df2ra.use2use);
! 	}
  
        /* If that produced no changes, the graph was colorizable.  */
        if (!changed)
*************** reg_alloc ()
*** 956,962 ****
  	  reg_scan_update (get_insns (), NULL, max_regno);
  	  max_regno = max_reg_num ();
  	  /* And they need usefull classes too.  */
! 	  regclass (get_insns (), max_reg_num (), rtl_dump_file);
  	  rtl_dump_file = ra_dump_file;
  
  	  /* Remember the number of defs and uses, so we can distinguish
--- 954,961 ----
  	  reg_scan_update (get_insns (), NULL, max_regno);
  	  max_regno = max_reg_num ();
  	  /* And they need usefull classes too.  */
! 	  if (!flag_ra_pre_reload)
! 	    regclass (get_insns (), max_reg_num (), rtl_dump_file);
  	  rtl_dump_file = ra_dump_file;
  
  	  /* Remember the number of defs and uses, so we can distinguish
*************** reg_alloc ()
*** 979,984 ****
--- 978,989 ----
      }
    while (changed);
  
+   if (ra_modified_insns)
+     BITMAP_XFREE (ra_modified_insns);
+ 
+   if (flag_ra_pre_reload)
+     ra_info_free (ra_info);
+ 
    /* We are done with allocation, free all memory and output some
       debug info.  */
    free_all_mem (df);
*************** reg_alloc ()
*** 1062,1073 ****
    allocate_initial_values (reg_equiv_memory_loc);
    /* And one last regclass pass just before reload.  */
    regclass (get_insns (), max_reg_num (), rtl_dump_file);
  }
  
  
! static enum reg_class *reg_class_of_web;
! 
! static enum reg_class
  web_preferred_class (web)
       struct web *web;
  {
--- 1067,1081 ----
    allocate_initial_values (reg_equiv_memory_loc);
    /* And one last regclass pass just before reload.  */
    regclass (get_insns (), max_reg_num (), rtl_dump_file);
+   if (flag_ra_pre_reload)
+     if (reg_class_of_web)
+       free (reg_class_of_web);
+   BITMAP_XFREE (emitted_by_spill);
+   BITMAP_XFREE (spill_slot_regs);
  }
  
  
! enum reg_class
  web_preferred_class (web)
       struct web *web;
  {
*************** web_preferred_class (web)
*** 1080,1085 ****
--- 1088,1094 ----
    return reg_class_of_web[find_web_for_subweb(web)->id];
  }
  
+ 
  void
  web_class ()
  {
*************** web_class ()
*** 1089,1101 ****
    ra_ref *rref;
    struct ref* dref;
    enum reg_class best;
  
    if (reg_class_of_web)
      free (reg_class_of_web);
  
    reg_class_of_web = xmalloc (sizeof (enum reg_class) * (num_webs
  							 - num_subwebs));
!   for (n = 0; n < num_webs - num_subwebs; ++n)
      {
        struct web *web = id2web[n];
        int founded = 0;
--- 1098,1112 ----
    ra_ref *rref;
    struct ref* dref;
    enum reg_class best;
+   int debug = 0;
+   static const char *const reg_class_names[] = REG_CLASS_NAMES;
  
    if (reg_class_of_web)
      free (reg_class_of_web);
  
    reg_class_of_web = xmalloc (sizeof (enum reg_class) * (num_webs
  							 - num_subwebs));
!   for (n = 0; n < (num_webs - num_subwebs); ++n)
      {
        struct web *web = id2web[n];
        int founded = 0;
*************** web_class ()
*** 1123,1130 ****
  	  if (rref)
  	    ++class[rref->class];
  	}
! 
! /*        fprintf (stderr, "Web: %d ", web->id); */
        best = ALL_REGS;
        for (i = 0; i < LIM_REG_CLASSES; ++i)
  	if (class[i])
--- 1134,1141 ----
  	  if (rref)
  	    ++class[rref->class];
  	}
!       if (debug)
! 	fprintf (stderr, "Web: %d ", web->id);
        best = ALL_REGS;
        for (i = 0; i < LIM_REG_CLASSES; ++i)
  	if (class[i])
*************** web_class ()
*** 1136,1153 ****
  	      }
  	    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;
      }
  }
- 
  /*
  vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
  */
--- 1147,1166 ----
  	      }
  	    else if (!reg_class_subset_p (best, i))
  	      best = NO_REGS;
! 	    if (debug)
! 	      fprintf (stderr, "%s: %d ", reg_class_names[i], class[i]);
  	  }
!       if (debug)
! 	fprintf (stderr, " BEST: %s\n", reg_class_names[best]); 
        if (best == NO_REGS)
  	{
! 	  if (debug)
! 	    fprintf (stderr, "Web: %d (%d) NO_REGS\n", web->id, web->regno);
  	  best = GENERAL_REGS;
  	}
        reg_class_of_web[n] = best;
      }
  }
  /*
  vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
  */
Index: ra-colorize.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ra-colorize.c,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 ra-colorize.c
*** ra-colorize.c	16 Jul 2002 19:52:44 -0000	1.1.2.3
--- ra-colorize.c	1 Aug 2002 20:15:37 -0000
*************** build_worklists (df)
*** 349,355 ****
        max_num = num_webs - num_subwebs;
        order2web = (struct web **) xmalloc (max_num * sizeof (order2web[0]));
        for (i = 0, num = 0; i < max_num; i++)
! 	if (id2web[i]->regno >= max_normal_pseudo)
  	  order2web[num++] = id2web[i];
        if (num)
  	{
--- 349,355 ----
        max_num = num_webs - num_subwebs;
        order2web = (struct web **) xmalloc (max_num * sizeof (order2web[0]));
        for (i = 0, num = 0; i < max_num; i++)
! 	if (SPILL_SLOT_P (id2web[i]->regno))
  	  order2web[num++] = id2web[i];
        if (num)
  	{
*************** combine (u, v)
*** 725,731 ****
    struct conflict_link *wl;
    if (u == v || v->type == COALESCED)
      abort ();
!   if ((u->regno >= max_normal_pseudo) != (v->regno >= max_normal_pseudo))
      abort ();
    remove_web_from_list (v);
    put_web (v, COALESCED);
--- 725,731 ----
    struct conflict_link *wl;
    if (u == v || v->type == COALESCED)
      abort ();
!   if (SPILL_SLOT_P (u->regno) != SPILL_SLOT_P (v->regno))
      abort ();
    remove_web_from_list (v);
    put_web (v, COALESCED);
*************** colorize_one_web (web, hard)
*** 1287,1293 ****
    HARD_REG_SET fat_colors;
    HARD_REG_SET bias;
  
!   if (web->regno >= max_normal_pseudo)
      hard = 0;
  
    /* First we want to know the colors at which we can't begin.  */
--- 1287,1293 ----
    HARD_REG_SET fat_colors;
    HARD_REG_SET bias;
  
!   if (SPILL_SLOT_P (web->regno))
      hard = 0;
  
    /* First we want to know the colors at which we can't begin.  */
*************** colorize_one_web (web, hard)
*** 1352,1366 ****
           alternate non-cc hardregs, and only _then_ also in preferred cc
           hardregs (and alternate ones).  Currently we don't track the number
           of calls crossed for webs.  We should.  */
!       if (web->use_my_regs)
  	{
! 	  COPY_HARD_REG_SET (colors, web->usable_regs);
! 	  AND_HARD_REG_SET (colors,
! 			    usable_regs[reg_preferred_class (web->regno)]);
  	}
-       else
- 	COPY_HARD_REG_SET (colors,
- 			   usable_regs[reg_preferred_class (web->regno)]);
  #ifdef CLASS_CANNOT_CHANGE_MODE
        if (web->mode_changed)
          AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
--- 1352,1371 ----
           alternate non-cc hardregs, and only _then_ also in preferred cc
           hardregs (and alternate ones).  Currently we don't track the number
           of calls crossed for webs.  We should.  */
!       if (flag_ra_pre_reload)
! 	COPY_HARD_REG_SET (colors, web->usable_regs);
!       else
  	{
! 	  if (web->use_my_regs)
! 	    {
! 	      COPY_HARD_REG_SET (colors, web->usable_regs);
! 	      AND_HARD_REG_SET (colors,
! 				usable_regs[reg_preferred_class (web->regno)]);
! 	    }
! 	  else
! 	    COPY_HARD_REG_SET (colors,
! 			       usable_regs[reg_preferred_class (web->regno)]);
  	}
  #ifdef CLASS_CANNOT_CHANGE_MODE
        if (web->mode_changed)
          AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
*************** colorize_one_web (web, hard)
*** 1388,1394 ****
  	c = get_biased_reg (dont_begin, bias, web->prefer_colors,
  			  colors, PSEUDO_REGNO_MODE (web->regno));
  
!       if (/*!web->use_my_regs &&*/ c < 0)
  	{
  	  if (web->use_my_regs)
  	    IOR_HARD_REG_SET (colors, web->usable_regs);
--- 1393,1399 ----
  	c = get_biased_reg (dont_begin, bias, web->prefer_colors,
  			  colors, PSEUDO_REGNO_MODE (web->regno));
  
!       if (/*!web->use_my_regs &&*/ c < 0 && !flag_ra_pre_reload)
  	{
  	  if (web->use_my_regs)
  	    IOR_HARD_REG_SET (colors, web->usable_regs);
*************** colorize_one_web (web, hard)
*** 1633,1639 ****
  	    }
  	}
      }
!   if (web->regno >= max_normal_pseudo && web->type == SPILLED)
      {
        web->color = an_unusable_color;
        remove_list (web->dlink, &WEBS(SPILLED));
--- 1638,1644 ----
  	    }
  	}
      }
!   if (SPILL_SLOT_P (web->regno) && web->type == SPILLED)
      {
        web->color = an_unusable_color;
        remove_list (web->dlink, &WEBS(SPILLED));
*************** check_colors ()
*** 2008,2014 ****
        struct web *aweb = alias (web);
        struct conflict_link *wl;
        int nregs, c;
!       if (aweb->type == SPILLED || web->regno >= max_normal_pseudo)
  	continue;
        else if (aweb->type == COLORED)
  	nregs = HARD_REGNO_NREGS (aweb->color, GET_MODE (web->orig_x));
--- 2013,2019 ----
        struct web *aweb = alias (web);
        struct conflict_link *wl;
        int nregs, c;
!       if (aweb->type == SPILLED || SPILL_SLOT_P (web->regno))
  	continue;
        else if (aweb->type == COLORED)
  	nregs = HARD_REGNO_NREGS (aweb->color, GET_MODE (web->orig_x));
*************** check_colors ()
*** 2028,2034 ****
        wl = (web->have_orig_conflicts ? web->orig_conflict_list
  	    : web->conflict_list);
        for (; wl; wl = wl->next)
! 	if (wl->t->regno >= max_normal_pseudo)
  	  continue;
  	else if (!wl->sub)
  	  {
--- 2033,2039 ----
        wl = (web->have_orig_conflicts ? web->orig_conflict_list
  	    : web->conflict_list);
        for (; wl; wl = wl->next)
! 	if (SPILL_SLOT_P (wl->t->regno))
  	  continue;
  	else if (!wl->sub)
  	  {
*************** extended_coalesce_2 ()
*** 2728,2734 ****
  	{
  	  struct web *dest = def2web[DF_REF_ID (info.defs[n])];
  	  dest = alias (find_web_for_subweb (dest));
! 	  if (dest->type != PRECOLORED && dest->regno < max_normal_pseudo)
  	    {
  	      unsigned int n2;
  	      for (n2 = 0; n2 < info.num_uses; n2++)
--- 2733,2739 ----
  	{
  	  struct web *dest = def2web[DF_REF_ID (info.defs[n])];
  	  dest = alias (find_web_for_subweb (dest));
! 	  if (dest->type != PRECOLORED && !SPILL_SLOT_P (dest->regno))
  	    {
  	      unsigned int n2;
  	      for (n2 = 0; n2 < info.num_uses; n2++)
*************** extended_coalesce_2 ()
*** 2737,2743 ****
  		  source = alias (find_web_for_subweb (source));
  		  if (source->type != PRECOLORED
  		      && source != dest
! 		      && source->regno < max_normal_pseudo
  		      /* Coalesced webs end up using the same REG rtx in
  			 emit_colors().  So we can only coalesce something
  			 of equal modes.  */
--- 2742,2748 ----
  		  source = alias (find_web_for_subweb (source));
  		  if (source->type != PRECOLORED
  		      && source != dest
! 		      && !SPILL_SLOT_P (source->regno)
  		      /* Coalesced webs end up using the same REG rtx in
  			 emit_colors().  So we can only coalesce something
  			 of equal modes.  */
cvs server: I know nothing about ra.c-orig
Index: ra-debug.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ra-debug.c,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 ra-debug.c
*** ra-debug.c	16 Jul 2002 19:52:44 -0000	1.1.2.3
--- ra-debug.c	1 Aug 2002 20:17:03 -0000
*************** dump_igraph (df)
*** 730,736 ****
  	ra_debug_msg (DUMP_WEBS, " dead");
        if (web->crosses_call)
  	ra_debug_msg (DUMP_WEBS, " xcall");
!       if (web->regno >= max_normal_pseudo)
  	ra_debug_msg (DUMP_WEBS, " stack");
        ra_debug_msg (DUMP_WEBS, "\n");
      }
--- 730,736 ----
  	ra_debug_msg (DUMP_WEBS, " dead");
        if (web->crosses_call)
  	ra_debug_msg (DUMP_WEBS, " xcall");
!       if (SPILL_SLOT_P (web->regno))
  	ra_debug_msg (DUMP_WEBS, " stack");
        ra_debug_msg (DUMP_WEBS, "\n");
      }
*************** web_conflicts_p (web1, web2)
*** 1020,1059 ****
  /* Dump all uids of insns in which WEB is mentioned.  */
  
  void
! dump_web_insns (web)
       struct web *web;
  {
    unsigned int i;
  
!   ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
! 	     web->id, web->regno, web->add_hardregs,
! 	     reg_class_names[web->regclass],
! 	     web->num_freedom, web->num_conflicts);
!   ra_debug_msg (DUMP_EVER, "   def insns:");
  
    for (i = 0; i < web->num_defs; ++i)
      {
!       ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
      }
  
!   ra_debug_msg (DUMP_EVER, "\n   use insns:");
    for (i = 0; i < web->num_uses; ++i)
      {
!       ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
      }
!   ra_debug_msg (DUMP_EVER, "\n");
  }
  
  /* Dump conflicts for web WEB.  */
  
  void
! dump_web_conflicts (web)
       struct web *web;
  {
    int num = 0;
    unsigned int def2;
  
!   ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
  	     web->id, web->regno, web->add_hardregs,
  	     reg_class_names[web->regclass],
  	     web->num_freedom, web->num_conflicts);
--- 1020,1059 ----
  /* Dump all uids of insns in which WEB is mentioned.  */
  
  void
! debug_web_insns (web)
       struct web *web;
  {
    unsigned int i;
  
!   fprintf (stderr, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
! 	   web->id, web->regno, web->add_hardregs,
! 	   reg_class_names[web->regclass],
! 	   web->num_freedom, web->num_conflicts);
!   fprintf (stderr, "   def insns:");
  
    for (i = 0; i < web->num_defs; ++i)
      {
!       fprintf (stderr, " %d ", INSN_UID (web->defs[i]->insn));
      }
  
!   fprintf (stderr, "\n   use insns:");
    for (i = 0; i < web->num_uses; ++i)
      {
!       fprintf (stderr, " %d ", INSN_UID (web->uses[i]->insn));
      }
!   fprintf (stderr, "\n");
  }
  
  /* Dump conflicts for web WEB.  */
  
  void
! debug_web_conflicts (web)
       struct web *web;
  {
    int num = 0;
    unsigned int def2;
  
!   fprintf (stderr, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
  	     web->id, web->regno, web->add_hardregs,
  	     reg_class_names[web->regclass],
  	     web->num_freedom, web->num_conflicts);
*************** dump_web_conflicts (web)
*** 1062,1098 ****
      if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
        {
  	if ((num % 9) == 5)
! 	  ra_debug_msg (DUMP_EVER, "\n             ");
  	num++;
  
! 	ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
  	if (id2web[def2]->add_hardregs)
! 	  ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
  
  	if (web_conflicts_p (web, id2web[def2]))
! 	  ra_debug_msg (DUMP_EVER, "/x");
  
  	if (id2web[def2]->type == SELECT)
! 	  ra_debug_msg (DUMP_EVER, "/s");
  
  	if (id2web[def2]->type == COALESCED)
! 	  ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
        }
!   ra_debug_msg (DUMP_EVER, "\n");
    {
      struct conflict_link *wl;
      num = 0;
!     ra_debug_msg (DUMP_EVER, "By conflicts:     ");
      for (wl = web->conflict_list; wl; wl = wl->next)
        {
  	struct web* w = wl->t;
  	if ((num % 9) == 8)
! 	  ra_debug_msg (DUMP_EVER, "\n              ");
  	num++;
! 	ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
  		   web_conflicts_p (web, w) ? "+" : "");
        }
!     ra_debug_msg (DUMP_EVER, "\n");
    }
  }
  
--- 1062,1098 ----
      if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
        {
  	if ((num % 9) == 5)
! 	  fprintf (stderr, "\n             ");
  	num++;
  
! 	fprintf (stderr, " %d(%d)", def2, id2web[def2]->regno);
  	if (id2web[def2]->add_hardregs)
! 	  fprintf (stderr, "+%d", id2web[def2]->add_hardregs);
  
  	if (web_conflicts_p (web, id2web[def2]))
! 	  fprintf (stderr, "/x");
  
  	if (id2web[def2]->type == SELECT)
! 	  fprintf (stderr, "/s");
  
  	if (id2web[def2]->type == COALESCED)
! 	  fprintf (stderr,"/c/%d", alias (id2web[def2])->id);
        }
!   fprintf (stderr, "\n");
    {
      struct conflict_link *wl;
      num = 0;
!     fprintf (stderr, "By conflicts:     ");
      for (wl = web->conflict_list; wl; wl = wl->next)
        {
  	struct web* w = wl->t;
  	if ((num % 9) == 8)
! 	  fprintf (stderr, "\n              ");
  	num++;
! 	fprintf (stderr, "%d(%d)%s ", w->id, w->regno,
  		   web_conflicts_p (web, w) ? "+" : "");
        }
!     fprintf (stderr, "\n");
    }
  }
  
Index: ra.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ra.h,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 ra.h
*** ra.h	16 Jul 2002 19:52:45 -0000	1.1.2.3
--- ra.h	1 Aug 2002 20:17:12 -0000
*************** extern bitmap *live_at_end;
*** 434,445 ****
     And this is how often we already ran that for the current function.  */
  extern int ra_pass;
  
- /* The maximum pseudo regno, just before register allocation starts.
-    While regalloc runs all pseudos with a larger number represent
-    potentially stack slots or hardregs.  I call them stackwebs or
-    stackpseudos.  */
- extern unsigned int max_normal_pseudo;
- 
  /* One of the fixed colors.  It must be < FIRST_PSEUDO_REGISTER, because
     we sometimes want to check the color against a HARD_REG_SET.  It must
     be >= 0, because negative values mean "no color".
--- 434,439 ----
*************** extern sbitmap last_check_uses;
*** 479,487 ****
     I-graph.  I.e. new conflicts due to coalescing trigger that copying.  */
  extern unsigned int remember_conflicts;
  
! /* The maximum UID right before calling regalloc().
!    Used to detect any instructions inserted by the allocator.  */
! extern int orig_max_uid;
  
  /* A HARD_REG_SET of those color, which can't be used for coalescing.
     Includes e.g. fixed_regs.  */
--- 473,486 ----
     I-graph.  I.e. new conflicts due to coalescing trigger that copying.  */
  extern unsigned int remember_conflicts;
  
! /* Used to detect spill instructions inserted by me.  */
! extern bitmap emitted_by_spill;
! 
! /* Insns which must be rescanned by pre_reload.  */
! extern bitmap ra_modified_insns;
! 
! /* This pseudos represents stack slots allocated by ra-rewrite.  */
! extern bitmap spill_slot_regs;
  
  /* A HARD_REG_SET of those color, which can't be used for coalescing.
     Includes e.g. fixed_regs.  */
*************** extern int flag_ra_spill_every_use;
*** 562,567 ****
--- 561,573 ----
  /* Nonzero to output all notes in the debug dumps.  */
  extern int flag_ra_dump_notes;
  
+ /* If nonzero, use pre-reload and web-class in new register allocator.  */
+ extern int flag_ra_pre_reload;
+ 
+ /* If nonzero, use separate passs for calculation web deaths in new
+    register allocator.  */
+ extern int flag_ra_spanned_deaths_from_scratch;
+ 
  extern inline void * ra_alloc PARAMS ((size_t));
  extern inline void * ra_calloc PARAMS ((size_t));
  extern int hard_regs_count PARAMS ((HARD_REG_SET));
*************** extern void emit_colors PARAMS ((struct 
*** 622,624 ****
--- 628,637 ----
  extern void delete_moves PARAMS ((void));
  extern void setup_renumber PARAMS ((int));
  extern void remove_suspicious_death_notes PARAMS ((void));
+ extern int is_partly_dead PARAMS ((sbitmap, struct web *));
+ extern void set_web_live PARAMS ((sbitmap, struct web *));
+ extern void reset_web_live PARAMS ((sbitmap, struct web *));
+ extern enum reg_class web_preferred_class PARAMS ((struct web *));
+ extern void web_class PARAMS ((void));
+ 
+ #define SPILL_SLOT_P(REGNO) bitmap_bit_p (spill_slot_regs, (REGNO))
Index: ra-rewrite.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ra-rewrite.c,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 ra-rewrite.c
*** ra-rewrite.c	16 Jul 2002 19:52:44 -0000	1.1.2.3
--- ra-rewrite.c	1 Aug 2002 20:17:37 -0000
*************** spill_coalescing (coalesce, spilled)
*** 106,111 ****
--- 106,112 ----
  	    PUT_CODE (m->insn, NOTE);
  	    NOTE_LINE_NUMBER (m->insn) = NOTE_INSN_DELETED;
  	    df_insn_modify (df, BLOCK_FOR_INSN (m->insn), m->insn);
+ 	    bitmap_set_bit (ra_modified_insns, INSN_UID (m->insn));
  
  	    m->target_web->target_of_spilled_move = 1;
  	    if (s == t)
*************** allocate_spill_web (web)
*** 326,331 ****
--- 327,333 ----
    set_mem_alias_set (slot, new_alias_set ());*/
    slot = gen_reg_rtx (PSEUDO_REGNO_MODE (regno));
    web->stack_slot = slot;
+   bitmap_set_bit (spill_slot_regs, REGNO (slot));
  }
  
  /* This chooses a color for all SPILLED webs for interference region
*************** rewrite_program (new_deaths)
*** 467,472 ****
--- 469,476 ----
  		  {
  		    set_block_for_insn (insn, bb);
  		    df_insn_modify (df, bb, insn);
+ 		    bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
+ 		    bitmap_set_bit (emitted_by_spill, INSN_UID (insn));
  		  }
  
  		emitted_spill_loads++;
*************** rewrite_program (new_deaths)
*** 530,543 ****
  		  emit_insn_after (insns, insn);
  		  if (bb->end == insn)
  		    bb->end = PREV_INSN (following);
! 		  for (insn = insns; insn != following; insn = NEXT_INSN (insn))
  		    {
  		      set_block_for_insn (insn, bb);
  		      df_insn_modify (df, bb, insn);
  		    }
  		}
  	      else
! 		df_insn_modify (df, bb, insn);
  	      emitted_spill_stores++;
  	      spill_store_cost += bb->frequency + 1;
  	      /* XXX we should set new_deaths for all inserted stores
--- 534,553 ----
  		  emit_insn_after (insns, insn);
  		  if (bb->end == insn)
  		    bb->end = PREV_INSN (following);
! 		  for (insn = insns; insn != following;
! 		       insn = NEXT_INSN (insn))
  		    {
  		      set_block_for_insn (insn, bb);
  		      df_insn_modify (df, bb, insn);
+ 		      bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
+ 		      bitmap_set_bit (emitted_by_spill, INSN_UID (insn));
  		    }
  		}
  	      else
! 		{
! 		  df_insn_modify (df, bb, insn);
! 		  bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
! 		}
  	      emitted_spill_stores++;
  	      spill_store_cost += bb->frequency + 1;
  	      /* XXX we should set new_deaths for all inserted stores
*************** insert_stores (new_deaths)
*** 733,745 ****
  			{
  			  set_block_for_insn (ni, bb);
  			  df_insn_modify (df, bb, ni);
  			}
  		    }
  		  else
! 		    df_insn_modify (df, bb, insn);
  		  emitted_spill_stores++;
  		  spill_store_cost += bb->frequency + 1;
! 		  bitmap_set_bit (new_deaths, INSN_UID (PREV_INSN (following)));
  		}
  	      else
  		{
--- 743,761 ----
  			{
  			  set_block_for_insn (ni, bb);
  			  df_insn_modify (df, bb, ni);
+ 			  bitmap_set_bit (ra_modified_insns, INSN_UID (ni));
+ 			  bitmap_set_bit (emitted_by_spill, INSN_UID (ni));
  			}
  		    }
  		  else
! 		    {
! 		      df_insn_modify (df, bb, insn);
! 		      bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
! 		    }
  		  emitted_spill_stores++;
  		  spill_store_cost += bb->frequency + 1;
! 		  bitmap_set_bit (new_deaths,
! 				  INSN_UID (PREV_INSN (following)));
  		}
  	      else
  		{
*************** is_partly_live_1 (live, web)
*** 809,817 ****
  }
  
  /* Fast version in case WEB has no subwebs.  */
! #define is_partly_live(live, web) ((!web->subreg_next)	\
! 				   ? TEST_BIT (live, web->id)	\
! 				   : is_partly_live_1 (live, web))
  
  /* Change the set of currently IN_USE colors according to
     WEB's color.  Either add those colors to the hardreg set (if ADD
--- 825,833 ----
  }
  
  /* Fast version in case WEB has no subwebs.  */
! #define is_partly_live(live, web) ((!web->subreg_next || web->parent_web) \
! 				   ? TEST_BIT (live, web->id)		  \
! 				   : is_partly_live_1 (live, web))	  \
  
  /* Change the set of currently IN_USE colors according to
     WEB's color.  Either add those colors to the hardreg set (if ADD
*************** emit_loads (ri, nl_first_reload, last_bl
*** 918,923 ****
--- 934,940 ----
        struct web *supweb;
        struct web *aweb;
        rtx ni, slot, reg;
+       enum machine_mode innermode;
        rtx before = NULL_RTX, after = NULL_RTX;
        basic_block bb;
        /* When spilltemps were spilled for the last insns, their
*************** emit_loads (ri, nl_first_reload, last_bl
*** 926,932 ****
        if (!web)
  	continue;
        supweb = find_web_for_subweb (web);
!       if (supweb->regno >= max_normal_pseudo)
  	abort ();
        /* Check for web being a spilltemp, if we only want to
  	 load spilltemps.  Also remember, that we emitted that
--- 943,949 ----
        if (!web)
  	continue;
        supweb = find_web_for_subweb (web);
!       if (SPILL_SLOT_P (supweb->regno))
  	abort ();
        /* Check for web being a spilltemp, if we only want to
  	 load spilltemps.  Also remember, that we emitted that
*************** emit_loads (ri, nl_first_reload, last_bl
*** 941,947 ****
  	}
        web->in_load = 0;
        /* The adding of reloads doesn't depend on liveness.  */
!       if (j < nl_first_reload && !TEST_BIT (ri->live, web->id))
  	continue;
        aweb = alias (supweb);
        aweb->changed = 1;
--- 958,964 ----
  	}
        web->in_load = 0;
        /* The adding of reloads doesn't depend on liveness.  */
!       if (j < nl_first_reload && !is_partly_live (ri->live, web))
  	continue;
        aweb = alias (supweb);
        aweb->changed = 1;
*************** emit_loads (ri, nl_first_reload, last_bl
*** 956,982 ****
  	  if (aweb != supweb)
  	    abort ();
  	  slot = copy_rtx (supweb->pattern);
! 	  reg = copy_rtx (supweb->orig_x);
! 	  /* Sanity check.  orig_x should be a REG rtx, which should be
! 	     shared over all RTL, so copy_rtx should have no effect.  */
! 	  if (reg != supweb->orig_x)
! 	    abort ();
  	}
        else
  	{
  	  allocate_spill_web (aweb);
  	  slot = aweb->stack_slot;
! 
! 	  /* If we don't copy the RTL there might be some SUBREG
! 	     rtx shared in the next iteration although being in
! 	     different webs, which leads to wrong code.  */
! 	  reg = copy_rtx (web->orig_x);
! 	  if (GET_CODE (reg) == SUBREG)
! 	    /*slot = adjust_address (slot, GET_MODE (reg), SUBREG_BYTE
! 	       (reg));*/
! 	    slot = simplify_gen_subreg (GET_MODE (reg), slot, GET_MODE (slot),
! 					SUBREG_BYTE (reg));
  	}
        ra_emit_move_insn (reg, slot);
        ni = get_insns ();
        end_sequence ();
--- 973,993 ----
  	  if (aweb != supweb)
  	    abort ();
  	  slot = copy_rtx (supweb->pattern);
! 	  innermode = GET_MODE (supweb->orig_x);
  	}
        else
  	{
  	  allocate_spill_web (aweb);
  	  slot = aweb->stack_slot;
! 	  innermode = GET_MODE (slot);
  	}
+       /* If we don't copy the RTL there might be some SUBREG
+ 	 rtx shared in the next iteration although being in
+ 	 different webs, which leads to wrong code.  */
+       reg = copy_rtx (web->orig_x);
+       if (GET_CODE (reg) == SUBREG)
+ 	slot = simplify_gen_subreg (GET_MODE (reg), slot, innermode,
+ 				    SUBREG_BYTE (reg));
        ra_emit_move_insn (reg, slot);
        ni = get_insns ();
        end_sequence ();
*************** emit_loads (ri, nl_first_reload, last_bl
*** 1000,1005 ****
--- 1011,1018 ----
  	    {
  	      set_block_for_insn (ni, bb);
  	      df_insn_modify (df, bb, ni);
+ 	      bitmap_set_bit (ra_modified_insns, INSN_UID (ni));
+ 	      bitmap_set_bit (emitted_by_spill, INSN_UID (ni));
  	    }
  	}
        else
*************** emit_loads (ri, nl_first_reload, last_bl
*** 1013,1018 ****
--- 1026,1033 ----
  	    {
  	      set_block_for_insn (ni, bb);
  	      df_insn_modify (df, bb, ni);
+ 	      bitmap_set_bit (ra_modified_insns, INSN_UID (ni));
+ 	      bitmap_set_bit (emitted_by_spill, INSN_UID (ni));
  	    }
  	}
        if (supweb->pattern)
*************** emit_loads (ri, nl_first_reload, last_bl
*** 1025,1031 ****
  	  emitted_spill_loads++;
  	  spill_load_cost += bb->frequency + 1;
  	}
!       RESET_BIT (ri->live, web->id);
        /* In the special case documented above only emit the reloads and
  	 one load.  */
        if (ri->need_load == 2 && j < nl_first_reload)
--- 1040,1046 ----
  	  emitted_spill_loads++;
  	  spill_load_cost += bb->frequency + 1;
  	}
!       reset_web_live (ri->live, web);
        /* In the special case documented above only emit the reloads and
  	 one load.  */
        if (ri->need_load == 2 && j < nl_first_reload)
*************** detect_bbs_for_rewrite (changed_bbs)
*** 1053,1058 ****
--- 1068,1121 ----
        }
  }
  
+ /* Test LIVE for partial WEB live.  */
+ int
+ is_partly_dead (live, web)
+      sbitmap live;
+      struct web *web;
+ {
+   struct web *sweb;
+   
+   if (web->subreg_next && !web->parent_web)
+     {
+       for (sweb = web->subreg_next; sweb; sweb = sweb->subreg_next)
+ 	if (!TEST_BIT (live, sweb->id))
+ 	  return 1;
+       return 0;
+     }
+   return !TEST_BIT (live, web->id);
+ }
+ 
+ /* Set live bit in LIVE for WEB or all his subwebs.  */
+ void
+ set_web_live (live, web)
+      sbitmap live;
+      struct web *web;
+ {
+   struct web *sweb;
+ 
+   if (web->subreg_next && !web->parent_web)
+     for (sweb = web->subreg_next; sweb; sweb = sweb->subreg_next)
+       SET_BIT (live, sweb->id);
+   else
+     SET_BIT (live, web->id);
+ }
+ 
+ /* Reset live bit in LIVE for WEB or all his subwebs.  */
+ void
+ reset_web_live (live, web)
+      sbitmap live;
+      struct web *web;
+ {
+   struct web *sweb;
+ 
+   if (web->subreg_next && !web->parent_web)
+     for (sweb = web->subreg_next; sweb; sweb = sweb->subreg_next)
+       RESET_BIT (live, sweb->id);
+   else
+     RESET_BIT (live, web->id);
+ }
+ 
  /* Fast version of rewrite_program2() for one basic block, where
     no spill code is necessary.  We detect here only insns with deaths.  */
  static void
*************** detect_deaths_in_bb (bb, live, new_death
*** 1094,1111 ****
        info = insn_df[INSN_UID (insn)];
        for (n = 0; n < info.num_defs; n++)
  	{
  	  struct ref *ref = info.defs[n];
  	  struct web *web = def2web[DF_REF_ID (ref)];
! 	  rtx reg = DF_REF_REG (ref);
  	  int is_non_def = 0;
- 	  unsigned int n2;
  
- 	  web = find_web_for_subweb (web);
  	  /* Detect rmw webs.  */
  	  for (n2 = 0; n2 < info.num_uses; n2++)
  	    {
  	      struct web *web2 = use2web[DF_REF_ID (info.uses[n2])];
! 	      if (web == find_web_for_subweb (web2))
  		{
  		  is_non_def = 1;
  		  break;
--- 1157,1173 ----
        info = insn_df[INSN_UID (insn)];
        for (n = 0; n < info.num_defs; n++)
  	{
+ 	  unsigned int n2;
  	  struct ref *ref = info.defs[n];
  	  struct web *web = def2web[DF_REF_ID (ref)];
! 	  struct web *supweb = find_web_for_subweb (web);
  	  int is_non_def = 0;
  
  	  /* Detect rmw webs.  */
  	  for (n2 = 0; n2 < info.num_uses; n2++)
  	    {
  	      struct web *web2 = use2web[DF_REF_ID (info.uses[n2])];
! 	      if (supweb == find_web_for_subweb (web2))
  		{
  		  is_non_def = 1;
  		  break;
*************** detect_deaths_in_bb (bb, live, new_death
*** 1114,1145 ****
  	  if (is_non_def)
  	    continue;
  
! 	  if (!is_partly_live (live, web))
  	    bitmap_set_bit (useless_defs, DF_REF_ID (ref));
  
! 	  if (GET_CODE (reg) == SUBREG)
! 	    {
! 	      struct web *sweb;
! 	      sweb = find_subweb (web, reg);
! 	      RESET_BIT (live, sweb->id);
! 	    }
! 	  else
! 	    {
! 	      struct web *sweb;
! 	      RESET_BIT (live, web->id);
! 	      for (sweb = web->subreg_next; sweb;
! 		   sweb = sweb->subreg_next)
! 		RESET_BIT (live, sweb->id);
! 	    }
  	}
  
        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 = !TEST_BIT (live, supweb->id);
! 	  is_death &= !TEST_BIT (live, web->id);
! 	  if (is_death)
  	    {
  	      bitmap_set_bit (new_deaths, INSN_UID (insn));
  	      break;
--- 1176,1191 ----
  	  if (is_non_def)
  	    continue;
  
! 	  if (!is_partly_live (live, supweb))
  	    bitmap_set_bit (useless_defs, DF_REF_ID (ref));
  
! 	  reset_web_live (live, web);
  	}
  
        for (n = 0; n < info.num_uses; n++)
  	{
  	  struct web *web = use2web[DF_REF_ID (info.uses[n])];
! 	  if (is_partly_dead (live, web))
  	    {
  	      bitmap_set_bit (new_deaths, INSN_UID (insn));
  	      break;
*************** detect_deaths_in_bb (bb, live, new_death
*** 1149,1155 ****
        for (n = 0; n < info.num_uses; n++)
  	{
  	  struct web *web = use2web[DF_REF_ID (info.uses[n])];
! 	  SET_BIT (live, web->id);
  	}
      }
  }
--- 1195,1201 ----
        for (n = 0; n < info.num_uses; n++)
  	{
  	  struct web *web = use2web[DF_REF_ID (info.uses[n])];
! 	  set_web_live (live, web);
  	}
      }
  }
*************** reloads_to_loads (ri, refs, num_refs, re
*** 1174,1180 ****
      {
        struct web *web = ref2web[DF_REF_ID (refs[n])];
        struct web *supweb = find_web_for_subweb (web);
-       int is_death;
        int j;
        /* Only emit reloads when entering their interference
  	 region.  A use of a spilled web never opens an
--- 1220,1225 ----
*************** reloads_to_loads (ri, refs, num_refs, re
*** 1185,1195 ****
  	  && TEST_HARD_REG_BIT (never_use_colors, supweb->color))
  	continue;
        /* Note, that if web (and supweb) are DEFs, we already cleared
! 	 the corresponding bits in live.  I.e. is_death becomes true, which
! 	 is what we want.  */
!       is_death = !TEST_BIT (ri->live, supweb->id);
!       is_death &= !TEST_BIT (ri->live, web->id);
!       if (is_death)
  	{
  	  int old_num_r = num_reloads;
  	  bitmap_clear (ri->scratch);
--- 1230,1238 ----
  	  && TEST_HARD_REG_BIT (never_use_colors, supweb->color))
  	continue;
        /* Note, that if web (and supweb) are DEFs, we already cleared
! 	 the corresponding bits in live.  I.e. is_partly_dead becomes true,
! 	 which is what we want.  */
!       if (is_partly_dead (ri->live, web))
  	{
  	  int old_num_r = num_reloads;
  	  bitmap_clear (ri->scratch);
*************** rewrite_program2 (new_deaths)
*** 1294,1300 ****
  	     Remember to not add to colors_in_use in that case.  */
  	  if (aweb->type != SPILLED /*|| aweb->color >= 0*/)
  	    {
! 	      SET_BIT (ri.live, web->id);
  	      if (aweb->type != SPILLED)
  	        update_spill_colors (&(ri.colors_in_use), web, 1);
  	    }
--- 1337,1343 ----
  	     Remember to not add to colors_in_use in that case.  */
  	  if (aweb->type != SPILLED /*|| aweb->color >= 0*/)
  	    {
! 	      set_web_live (ri.live, web);
  	      if (aweb->type != SPILLED)
  	        update_spill_colors (&(ri.colors_in_use), web, 1);
  	    }
*************** rewrite_program2 (new_deaths)
*** 1343,1349 ****
  		  struct web *aweb = alias (find_web_for_subweb (web));
  		  if (aweb->type != SPILLED)
  		    {
! 		      SET_BIT (ri.live, web->id);
  		      update_spill_colors (&(ri.colors_in_use), web, 1);
  		    }
  		});
--- 1386,1392 ----
  		  struct web *aweb = alias (find_web_for_subweb (web));
  		  if (aweb->type != SPILLED)
  		    {
! 		      set_web_live (ri.live, web);
  		      update_spill_colors (&(ri.colors_in_use), web, 1);
  		    }
  		});
*************** rewrite_program2 (new_deaths)
*** 1407,1413 ****
  		if (!is_partly_live (ri.live, supweb))
  		  bitmap_set_bit (useless_defs, DF_REF_ID (ref));
  
! 		RESET_BIT (ri.live, web->id);
  		if (bitmap_bit_p (ri.need_reload, web->id))
  		  {
  		    ri.num_reloads--;
--- 1450,1456 ----
  		if (!is_partly_live (ri.live, supweb))
  		  bitmap_set_bit (useless_defs, DF_REF_ID (ref));
  
! 		reset_web_live (ri.live, web);
  		if (bitmap_bit_p (ri.need_reload, web->id))
  		  {
  		    ri.num_reloads--;
*************** rewrite_program2 (new_deaths)
*** 1436,1442 ****
  		    for (sweb = supweb->subreg_next; sweb;
  			 sweb = sweb->subreg_next)
  		      {
- 		        RESET_BIT (ri.live, sweb->id);
  			if (bitmap_bit_p (ri.need_reload, sweb->id))
  			  {
  		            ri.num_reloads--;
--- 1479,1484 ----
*************** rewrite_program2 (new_deaths)
*** 1462,1474 ****
  	      {
  		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)
  		  {
  		    ri.need_load = 1;
  		    bitmap_set_bit (new_deaths, INSN_UID (insn));
--- 1504,1513 ----
  	      {
  		struct web *web = use2web[DF_REF_ID (info.uses[n])];
  		struct web *supweb = find_web_for_subweb (web);
  		if (supweb->type == PRECOLORED
  		    && TEST_HARD_REG_BIT (never_use_colors, supweb->color))
  		  continue;
! 		if (is_partly_dead (ri.live, web))
  		  {
  		    ri.need_load = 1;
  		    bitmap_set_bit (new_deaths, INSN_UID (insn));
*************** rewrite_program2 (new_deaths)
*** 1514,1520 ****
  		struct web *web = use2web[DF_REF_ID (info.uses[n])];
  		struct web *supweb = find_web_for_subweb (web);
  		struct web *aweb = alias (supweb);
! 		SET_BIT (ri.live, web->id);
  		if (aweb->type != SPILLED)
  		  continue;
  		if (supweb->spill_temp)
--- 1553,1559 ----
  		struct web *web = use2web[DF_REF_ID (info.uses[n])];
  		struct web *supweb = find_web_for_subweb (web);
  		struct web *aweb = alias (supweb);
! 		set_web_live (ri.live, web);
  		if (aweb->type != SPILLED)
  		  continue;
  		if (supweb->spill_temp)
*************** delete_useless_defs ()
*** 1783,1788 ****
--- 1822,1828 ----
  	  PUT_CODE (insn, NOTE);
  	  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
  	  df_insn_modify (df, BLOCK_FOR_INSN (insn), insn);
+ 	  bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
  	}
      });
  }
*************** emit_colors (df)
*** 1893,1899 ****
        if (web->reg_rtx || web->regno < FIRST_PSEUDO_REGISTER)
  	abort ();
  
!       if (web->regno >= max_normal_pseudo)
  	{
  	  rtx place;
  	  if (web->color == an_unusable_color)
--- 1933,1939 ----
        if (web->reg_rtx || web->regno < FIRST_PSEUDO_REGISTER)
  	abort ();
  
!       if (SPILL_SLOT_P (web->regno))
  	{
  	  rtx place;
  	  if (web->color == an_unusable_color)
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.418.2.15
diff -c -3 -p -r1.418.2.15 toplev.c
*** toplev.c	16 Jul 2002 19:52:43 -0000	1.418.2.15
--- toplev.c	1 Aug 2002 20:18:18 -0000
*************** int flag_renumber_insns = 1;
*** 869,874 ****
--- 869,879 ----
  
  /* If nonzero, use the graph coloring register allocator.  */
  int flag_new_regalloc = 1;
+ /* If nonzero, use pre-reload and web-class in new register allocator.  */
+ int flag_ra_pre_reload = 0;
+ /* If nonzero, use separate passs for calculation web deaths in new
+    register allocator.  */
+ int flag_ra_spanned_deaths_from_scratch = 0;
  
  /* Nonzero if we perform superblock formation.  */
  
*************** static const lang_independent_options f_
*** 1180,1185 ****
--- 1185,1194 ----
     N_("Trap for signed overflow in addition / subtraction / multiplication") },
    { "new-ra", &flag_new_regalloc, 1,
     N_("Use graph coloring register allocation.") },
+   { "new-ra-pre-reload", &flag_ra_pre_reload, 1,
+    N_("Use pre-reload in graph coloring register allocation.") },
+   { "new-ra-spanned-deaths-pass", &flag_ra_spanned_deaths_from_scratch, 1,
+    N_("Use special pass for detect web deaths in graph coloring register allocation.") },
  };
  
  /* Table of language-specific options.  */



More information about the Gcc-patches mailing list