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]
Other format: [Raw text]

Re: [dataflow]: PATCH: ia64 bootstrap and regression fixes


For now this is ok.  I want you to think about not adding those extra
bit vectors to the lr problem.  These are only used for register
allocation and will add a lot of space and time to the rest of the
compilation.  The urec problem is only used for register allocation and
it seems like if you can put the vectors and the computation there, you
can save a lot of time and space.

Kenny


Seongbae Park wrote:
> The attached patch makes
> df branch bootstrap with c,c++,fortran on ia64
> with no extra regressions than the mainline.
> Bootstrapped and tested on ia64 and x86-64 with no extra regressions.
>
> 2006-11-28  Seongbae Park <seongbae.park@gmail.com>
>
>        * dbgcnt.def: Updated comments. Added new counters.
>        * auto-inc-dec.c (try_merge): Debug counter.
>        * global.c (global_conflicts): Use DF_RA_LIVE_TOP() instead of
>        df_urec_get_live_at_top().
>        * dbgcnt.c (count, limit): Use dbgcnt.def.
>        (dbg_cnt_is_enabled): New function.
>        (dbg_cnt): Use dbg_cnt_is_enabled().
>        * local-alloc.c (block_alloc): Use DF_RA_LIVE_TOP instead of
> LIVE_IN.
>        Add a debug counter.
>        * df.h (DF_RA_LIVE_TOP): New Macro. Remove
> df_urec_get_live_at_top.
>        (struct df_rd_bb_info): Added new fields ADEF, AUSE and TOP.
>        (struct df_urec_bb_info): Added new field TOP.
>        * loop-iv.c (iv_analyze_def): Added REG_P check.
>        * df-problems.c (df_lr_free_bb_info): Free new fields AUSE,
> ADEF and
>        TOP.
>        (df_lr_alloc): Allocate new fields TOP, ADEF, AUSE.
>        (df_lr_bb_local_compute): Compute ADEF and AUSE.
>        (df_lr_transfer_function): Compute TOP, and then IN based on
> TOP, ADEF
>        and AUSE.
>        (df_lr_free): Free new fields AUSE, ADEF and TOP.
>        (df_ur_bb_local_compute): Partial/conditional defs don't hide
>        earlier defs.
>        (df_urec_alloc): Allocate new field TOP.
>        (df_urec_local_finalize): Calculate TOP as well as IN.
>        (df_urec_free): Free new field TOP.
>        (df_urec_get_live_at_top): Removed.
>        * Makefile.in (auto-inc-dec.o, local-alloc.o, sched-rgn.o,
>        sched-ebb.o, recog.o): Added dependency on DBGCNT_H.
>        * sched-rgn.c (schedule_insns, gate_handle_sched,
> gate_handle_sched2):
>        Added debug counter.
>        * config/ia64/ia64.c (enum ia64_frame_regs): New enum.
>        (struct ia64_frame_info): Changed register fields to use an array
>        index by enum.
>        (emitted_frame_related_regs): New static variable.
>        (reg_emitted, get_reg, is_emitted): New function.
>        (ia64_reload_gp): Use new enum.
>        (find_gr_spill): Added a new param. Use
> emitted_frame_related_regs.
>        (ia64_computea_frame_size, ia64_hard_regno_rename_ok,
>        ia64_epilogue_uses):
>        Use emitted_frame_related_regs.
>        (ia64_expand_prologue): Extra deubg output. Use new enum.
>        (ia64_expand_epilogue, ia64_direct_return,
> ia64_split_return_addr_rtx,
>        ia64_output_function_prologue, ia64_output_function_epilogue,
>        process_set):
>        Use new enum.
>        (ia64_init_expanders): New function.
>        (ia64_reorg): New debug counter.
>        * config/ia64/ia64.h (INIT_EXPANDERS): New call to
>        ia64_init_expanders.
>
> ------------------------------------------------------------------------
>
> Index: dbgcnt.def
> ===================================================================
> --- dbgcnt.def	(revision 119260)
> +++ dbgcnt.def	(working copy)
> @@ -37,7 +37,7 @@ Software Foundation, 51 Franklin Street,
>     the counter is incremented for the named-counter.
>     And the incremented value is compared against the threshold (limit)
>     specified by the option.
> -   dbg_cnt () returns true if it is below threshold, and false otherwise.
> +   dbg_cnt () returns true if it is at or below threshold, and false if above.
>  
>     How to add a new one ?
>  
> @@ -55,13 +55,22 @@ Software Foundation, 51 Franklin Street,
>  
>     How to use it ?
>  
> -   By default, all limits are 0, and if the limit is zero,
> -   dbg_cnt() returns true always regardless of the counter value
> +   By default, all limits are UINT_MAX.
> +   Since debug count is unsigned int, <= UINT_MAX returns true always.
> +   i.e.  dbg_cnt() returns true always regardless of the counter value
>     (although it still counts the event).
>     Use -fdbg-cnt=counter1:N,counter2:M,...
>     which sets the limit for counter1 to N, and the limit for counter2 to M, etc.
> +   e.g. setting a limit to zero will make dbg_cnt () return false *always*.
>  */
>  
>  /* Debug counter definitions.  */
>  DEBUG_COUNTER (new_dce)
>  DEBUG_COUNTER (tail_call)
> +DEBUG_COUNTER (auto_inc_dec)
> +DEBUG_COUNTER (sched_region)
> +DEBUG_COUNTER (sched_func)
> +DEBUG_COUNTER (sched2_func)
> +DEBUG_COUNTER (local_alloc_for_sched)
> +DEBUG_COUNTER (split_for_sched2)
> +DEBUG_COUNTER (ia64_sched2)
> Index: auto-inc-dec.c
> ===================================================================
> --- auto-inc-dec.c	(revision 119260)
> +++ auto-inc-dec.c	(working copy)
> @@ -40,7 +40,7 @@ Software Foundation, 51 Franklin Street,
>  #include "timevar.h"
>  #include "tree-pass.h"
>  #include "df.h"
> -
> +#include "dbgcnt.h"
>  
>  enum form
>    {
> @@ -706,6 +706,9 @@ try_merge (void)
>    gen_form = decision_table 
>      [inc_insn.reg1_state][mem_insn.reg1_state][inc_insn.form];
>  
> +  if (dbg_cnt (auto_inc_dec) == false)
> +    return false;
> +
>    switch (gen_form)
>      {
>      default:
> @@ -1463,7 +1466,6 @@ merge_in_block (int max_reg, basic_block
>  	  for (use = DF_INSN_UID_USES (df, uid); use; use = use->next_ref)
>  	    {
>  	      reg_next_use[DF_REF_REGNO (use)] = insn;
> -	      reg_next_use[DF_REF_REGNO (use)] = insn;
>  	      if (insn_is_add_or_inc)
>  		reg_next_inc_use[DF_REF_REGNO (use)] = insn;
>  	      else
> Index: global.c
> ===================================================================
> --- global.c	(revision 119260)
> +++ global.c	(working copy)
> @@ -682,14 +682,11 @@ global_conflicts (void)
>  	 be explicitly marked in basic_block_live_at_start.  */
>  
>        {
> -	regset old = ALLOC_REG_SET (&reg_obstack);
>  	int ax = 0;
>  	reg_set_iterator rsi;
>  
> -        df_urec_get_live_at_top (ra_df, b, old);
> -
> -	REG_SET_TO_HARD_REG_SET (hard_regs_live, old);
> -	EXECUTE_IF_SET_IN_REG_SET (old, FIRST_PSEUDO_REGISTER, i, rsi)
> +	REG_SET_TO_HARD_REG_SET (hard_regs_live, DF_RA_LIVE_TOP (ra_df, b));
> +	EXECUTE_IF_SET_IN_REG_SET (DF_RA_LIVE_TOP (ra_df, b), FIRST_PSEUDO_REGISTER, i, rsi)
>  	  {
>  	    int a = reg_allocno[i];
>  	    if (a >= 0)
> @@ -701,8 +698,6 @@ global_conflicts (void)
>  	      mark_reg_live_nc (a, PSEUDO_REGNO_MODE (i));
>  	  }
>  
> -        FREE_REG_SET (old);
> -
>  	/* Record that each allocno now live conflicts with each hard reg
>  	   now live.
>  
> @@ -1840,7 +1835,7 @@ build_insn_chain (rtx first)
>  
>  	  CLEAR_REG_SET (live_relevant_regs);
>  
> -	  EXECUTE_IF_SET_IN_BITMAP (DF_RA_LIVE_IN (ra_df, b), 0, i, bi)
> +	  EXECUTE_IF_SET_IN_BITMAP (DF_RA_LIVE_TOP (ra_df, b), 0, i, bi)
>  	    {
>  	      if (i < FIRST_PSEUDO_REGISTER
>  		  ? ! TEST_HARD_REG_BIT (eliminable_regset, i)
> Index: dbgcnt.c
> ===================================================================
> --- dbgcnt.c	(revision 119260)
> +++ dbgcnt.c	(working copy)
> @@ -37,17 +37,31 @@ static struct string2counter_map map[deb
>  {
>  #include "dbgcnt.def"
>  };
> +#undef DEBUG_COUNTER
>  
> -static int count[debug_counter_number_of_counters];
> -static int limit[debug_counter_number_of_counters];
> +#define DEBUG_COUNTER(a) UINT_MAX,
> +static unsigned int limit[debug_counter_number_of_counters] =
> +{
> +#include "dbgcnt.def"
> +};
> +#undef DEBUG_COUNTER
> +
> +static unsigned int count[debug_counter_number_of_counters];
> +
> +bool
> +dbg_cnt_is_enabled (enum debug_counter index)
> +{
> +  return count[index] <= limit[index];
> +}
>  
>  bool
>  dbg_cnt (enum debug_counter index)
>  {
>    count[index]++;
> -  return limit[index] == 0 || (count[index] < limit[index]);
> +  return dbg_cnt_is_enabled (index);
>  }
>  
> +
>  static void
>  dbg_cnt_set_limit_by_index (enum debug_counter index, int value)
>  {
> Index: dbgcnt.h
> ===================================================================
> --- dbgcnt.h	(revision 119260)
> +++ dbgcnt.h	(working copy)
> @@ -32,6 +32,7 @@ enum debug_counter {
>  
>  #undef DEBUG_COUNTER
>  
> +extern bool dbg_cnt_is_enabled (enum debug_counter index);
>  extern bool dbg_cnt (enum debug_counter index);
>  extern void dbg_cnt_process_opt (const char *arg);
>  
> Index: local-alloc.c
> ===================================================================
> --- local-alloc.c	(revision 119260)
> +++ local-alloc.c	(working copy)
> @@ -82,6 +82,8 @@ Software Foundation, 51 Franklin Street,
>  #include "timevar.h"
>  #include "tree-pass.h"
>  #include "df.h"
> +#include "dbgcnt.h"
> +
>  
>  /* Next quantity number available for allocation.  */
>  
> @@ -1272,7 +1274,7 @@ block_alloc (int b)
>  
>    /* Initialize table of hardware registers currently live.  */
>  
> -  REG_SET_TO_HARD_REG_SET (regs_live, DF_RA_LIVE_IN (ra_df, BASIC_BLOCK (b)));
> +  REG_SET_TO_HARD_REG_SET (regs_live, DF_RA_LIVE_TOP (ra_df, BASIC_BLOCK (b)));
>  
>    /* This loop scans the instructions of the basic block
>       and assigns quantities to registers.
> @@ -1646,7 +1648,7 @@ block_alloc (int b)
>  		 This optimization is only appropriate when we will run
>  		 a scheduling pass after reload and we are not optimizing
>  		 for code size.  */
> -	      if (flag_schedule_insns_after_reload
> +	      if (flag_schedule_insns_after_reload && dbg_cnt (local_alloc_for_sched)
>  		  && !optimize_size
>  		  && !SMALL_REGISTER_CLASSES)
>  		{
> @@ -1666,7 +1668,7 @@ block_alloc (int b)
>  
>  #ifdef INSN_SCHEDULING
>  	  /* Similarly, avoid false dependencies.  */
> -	  if (flag_schedule_insns_after_reload
> +	  if (flag_schedule_insns_after_reload && dbg_cnt (local_alloc_for_sched)
>  	      && !optimize_size
>  	      && !SMALL_REGISTER_CLASSES
>  	      && qty[q].alternate_class != NO_REGS)
> Index: df.h
> ===================================================================
> --- df.h	(revision 119260)
> +++ df.h	(working copy)
> @@ -450,6 +450,7 @@ struct df
>  /* Live in for register allocation also takes into account several other factors.  */
>  #define DF_RA_LIVE_IN(DF, BB) (DF_UREC_BB_INFO(DF, BB)->in) 
>  #define DF_RA_LIVE_OUT(DF, BB) (DF_UREC_BB_INFO(DF, BB)->out) 
> +#define DF_RA_LIVE_TOP(DF, BB) (DF_UREC_BB_INFO(DF, BB)->top) 
>  
>  /* These macros are currently used by only reg-stack since it is not
>     tolerant of uninitialized variables.  This intolerance should be
> @@ -617,19 +618,41 @@ struct df_rd_bb_info 
>  };
>  
>  
> -/* Live registers.  All bitmaps are referenced by the register number.  */
> +/* Live registers.  All bitmaps are referenced by the register number.  
> +
> +   df_lr_bb_info:IN is the "in" set of the traditional dataflow sense
> +   which is the confluence of out sets of all predecessor blocks.
> +   The difference between IN and TOP is 
> +   due to the artificial defs and uses at the top (DF_REF_TOP)
> +   (e.g. exception handling dispatch block, which can have
> +   a few registers defined by the runtime) - which is NOT included
> +   in the "in" set before this function but is included after.  
> +   For the initial live set of forward scanning, TOP should be used
> +   instead of IN - otherwise, artificial defs won't be in IN set
> +   causing the bad transformation. TOP set can not simply be
> +   the union of IN set and artificial defs at the top, 
> +   because artificial defs might not be used at all,
> +   in which case those defs are not live at any point
> +   (except as a dangling def) - hence TOP has to be calculated
> +   during the LR problem computation and stored in df_lr_bb_info.  */
> +
>  struct df_lr_bb_info 
>  {
>    /* Local sets to describe the basic blocks.  */
> -  bitmap def;   /* The set of registers set in this block.  */
> +  bitmap def;   /* The set of registers set in this block 
> +                   - except artificial defs at the top.  */
>    bitmap use;   /* The set of registers used in this block.  */
> +  bitmap adef;  /* The artificial defs at top. */
> +  bitmap ause;  /* The artificial uses at top. */
>  
>    /* The results of the dataflow problem.  */
> -  bitmap in;    /* At the top of the block.  */
> +  bitmap in;    /* Just before the block itself. */
> +  bitmap top;   /* Just before the first insn in the block. */
>    bitmap out;   /* At the bottom of the block.  */
>  };
>  
>  
> +
>  /* Uninitialized registers.  All bitmaps are referenced by the register number.  */
>  struct df_ur_bb_info 
>  {
> @@ -663,8 +686,8 @@ struct df_urec_bb_info 
>    bitmap gen;
>  
>    /* The results of the dataflow problem.  */
> -  bitmap in;    /* At the top of the block. 
> -                   See df_urec_local_finalize for caveat.  */
> +  bitmap in;    /* Just before the block.  */
> +  bitmap top;   /* Just before the first insn in the block. */
>    bitmap out;   /* At the bottom of the block.  */
>  };
>  
> @@ -758,7 +781,6 @@ extern struct dataflow *df_chain_add_pro
>  extern struct dataflow *df_ri_add_problem (struct df *);
>  extern bitmap df_ri_get_setjmp_crosses (struct df *);
>  
> -extern void df_urec_get_live_at_top (struct df *, basic_block, bitmap);
>  
>  /* Functions defined in df-scan.c.  */
>  
> Index: loop-iv.c
> ===================================================================
> --- loop-iv.c	(revision 119260)
> +++ loop-iv.c	(working copy)
> @@ -1078,6 +1078,9 @@ iv_analyze_def (struct df_ref *def, stru
>    if (!set)
>      return false;
>  
> +  if (!REG_P (SET_DEST (set)))
> +    return false;
> +
>    gcc_assert (SET_DEST (set) == reg);
>    rhs = find_reg_equal_equiv_note (insn);
>    if (rhs)
> Index: df-problems.c
> ===================================================================
> --- df-problems.c	(revision 119260)
> +++ df-problems.c	(working copy)
> @@ -1385,6 +1385,12 @@ df_lr_free_bb_info (struct dataflow *dfl
>        BITMAP_FREE (bb_info->def);
>        BITMAP_FREE (bb_info->in);
>        BITMAP_FREE (bb_info->out);
> +      BITMAP_FREE (bb_info->top);
> +      if (bb_info->ause)
> +        BITMAP_FREE (bb_info->ause);
> +      if (bb_info->adef)
> +        BITMAP_FREE (bb_info->adef);
> +
>        pool_free (dflow->block_pool, bb_info);
>      }
>  }
> @@ -1422,6 +1428,9 @@ df_lr_alloc (struct dataflow *dflow, bit
>  	  bb_info->def = BITMAP_ALLOC (NULL);
>  	  bb_info->in = BITMAP_ALLOC (NULL);
>  	  bb_info->out = BITMAP_ALLOC (NULL);
> +          bb_info->top = BITMAP_ALLOC (NULL);
> +          bb_info->adef = NULL;
> +          bb_info->ause = NULL;
>  	}
>      }
>  }
> @@ -1525,15 +1534,17 @@ df_lr_bb_local_compute (struct dataflow 
>  	/* Add use to set of uses in this BB.  */
>  	bitmap_set_bit (bb_info->use, DF_REF_REGNO (use));
>      }
> -
>    /* Process the registers set in an exception handler.  */
>    for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
>      if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP)
>  	&& (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))))
>        {
>  	unsigned int dregno = DF_REF_REGNO (def);
> -	bitmap_set_bit (bb_info->def, dregno);
> -	bitmap_clear_bit (bb_info->use, dregno);
> +        if (bb_info->adef == NULL)
> +          bb_info->adef = BITMAP_ALLOC (NULL);
> +        if (bb_info->ause == NULL)
> +          bb_info->ause = BITMAP_ALLOC (NULL);
> +	bitmap_set_bit (bb_info->adef, dregno);
>        }
>    
>  #ifdef EH_USES
> @@ -1541,7 +1552,13 @@ df_lr_bb_local_compute (struct dataflow 
>    for (use = df_get_artificial_uses (df, bb_index); use; use = use->next_ref)
>      /* Add use to set of uses in this BB.  */
>      if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
> -      bitmap_set_bit (bb_info->use, DF_REF_REGNO (use));
> +      {
> +        if (bb_info->adef == NULL)
> +          bb_info->adef = BITMAP_ALLOC (NULL);
> +        if (bb_info->ause == NULL)
> +          bb_info->ause = BITMAP_ALLOC (NULL);
> +        bitmap_set_bit (bb_info->ause, DF_REF_REGNO (use));
> +      }
>  #endif
>  }
>  
> @@ -1666,8 +1683,18 @@ df_lr_transfer_function (struct dataflow
>    bitmap out = bb_info->out;
>    bitmap use = bb_info->use;
>    bitmap def = bb_info->def;
> -
> -  return bitmap_ior_and_compl (in, use, out, def);
> +  bitmap top = bb_info->top;
> +  bitmap ause = bb_info->ause;
> +  bitmap adef = bb_info->adef;
> +
> +  bitmap_ior_and_compl (top, use, out, def);
> +  if (ause && adef)
> +    return bitmap_ior_and_compl (in, ause, top, adef);
> +
> +  if (bitmap_equal_p (in, top))
> +    return 0;
> +  bitmap_copy (in, top);
> +  return 1;
>  }
>  
>  
> @@ -1699,6 +1726,11 @@ df_lr_free (struct dataflow *dflow)
>  	      BITMAP_FREE (bb_info->def);
>  	      BITMAP_FREE (bb_info->in);
>  	      BITMAP_FREE (bb_info->out);
> +	      BITMAP_FREE (bb_info->top);
> +              if (bb_info->ause)
> +                BITMAP_FREE (bb_info->ause);
> +              if (bb_info->adef)
> +                BITMAP_FREE (bb_info->adef);
>  	    }
>  	}
>        free_alloc_pool (dflow->block_pool);
> @@ -1999,19 +2031,26 @@ df_ur_bb_local_compute (struct dataflow 
>  	  /* Only the last def counts.  */
>  	  if (!bitmap_bit_p (seen_in_block, regno))
>  	    {
> -	      bitmap_set_bit (seen_in_insn, regno);
> -	      
> -	      if (DF_REF_FLAGS (def) 
> -		  & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))
> -		{
> +              if (DF_REF_FLAGS_IS_SET (def,
> +                                       DF_REF_PARTIAL
> +                                       | DF_REF_CONDITIONAL))
> +                {
> +                  /* All partial or conditional def
> +                     seen are included in the gen set. */
> +                  bitmap_set_bit (bb_info->gen, regno);
> +                }
> +              else if (DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER))
> +                {
>  		  /* Only must clobbers for the entire reg destroy the
>  		     value.  */
> -		  if ((DF_REF_FLAGS (def) & DF_REF_MUST_CLOBBER)
> -		      && (!DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
> -		    bitmap_set_bit (bb_info->kill, regno);
> +                  bitmap_set_bit (seen_in_insn, regno);
> +                  bitmap_set_bit (bb_info->kill, regno);
>  		}
> -	      else
> -		bitmap_set_bit (bb_info->gen, regno);
> +              else if (! DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER))
> +		{
> +                  bitmap_set_bit (seen_in_insn, regno);
> +		  bitmap_set_bit (bb_info->gen, regno);
> +                }
>  	    }
>  	}
>        bitmap_ior_into (seen_in_block, seen_in_insn);
> @@ -2507,6 +2546,7 @@ df_urec_alloc (struct dataflow *dflow, b
>  	  bb_info->gen = BITMAP_ALLOC (NULL);
>  	  bb_info->in = BITMAP_ALLOC (NULL);
>  	  bb_info->out = BITMAP_ALLOC (NULL);
> +          bb_info->top = BITMAP_ALLOC (NULL);
>  	  bb_info->earlyclobber = BITMAP_ALLOC (NULL);
>  	}
>      }
> @@ -2857,6 +2897,10 @@ df_urec_local_finalize (struct dataflow 
>  	 we trim the rr result to the places where it is used.  */
>        bitmap_and_into (bb_info->in, bb_lr_info->in);
>        bitmap_and_into (bb_info->out, bb_lr_info->out);
> +      bitmap_copy (bb_info->top, bb_info->in);
> +      if (bb_lr_info->adef)
> +        bitmap_ior_into (bb_info->top, bb_lr_info->adef);
> +      bitmap_and_into (bb_info->top, bb_lr_info->top);
>  #if 0
>        /* Hard registers may still stick in the ur_out set, but not
>  	 be in the ur_in set, if their only mention was in a call
> @@ -2907,29 +2951,6 @@ df_urec_transfer_function (struct datafl
>  }
>  
>  
> -/* Get the live regset at the point just before
> -   the first insn in the basic block B. 
> -
> -   df_urec_bb_info:in is the "in" set of the traditional dataflow sense
> -   which is the confluence of out sets of all predecessor blocks.
> -   The difference from "in" set is from the artificial defs at the top
> -   (e.g. exception handling dispatch block, which can have
> -   a few registers defined by the runtime) - which is NOT included
> -   in the "in" set before this function but is included after.  */
> -
> -void
> -df_urec_get_live_at_top (struct df *df, basic_block b, bitmap top)
> -{
> -  struct df_ref *ref;
> -
> -  bitmap_ior_into (top, DF_RA_LIVE_IN (df, b));
> -
> -  /* artificial_defs at TOP has to be included in "in" set.  */
> -  for (ref = df_get_artificial_defs (df, b->index);
> -       ref; ref = DF_REF_NEXT_REF (ref))
> -    if (DF_REF_FLAGS_IS_SET (ref, DF_REF_AT_TOP))
> -      bitmap_set_bit (top, DF_REF_REGNO (ref));
> -}
>  
>  /* Free all storage associated with the problem.  */
>  
> @@ -2950,6 +2971,7 @@ df_urec_free (struct dataflow *dflow)
>  	      BITMAP_FREE (bb_info->in);
>  	      BITMAP_FREE (bb_info->out);
>  	      BITMAP_FREE (bb_info->earlyclobber);
> +              BITMAP_FREE (bb_info->top);
>  	    }
>  	}
>        
> Index: Makefile.in
> ===================================================================
> --- Makefile.in	(revision 119260)
> +++ Makefile.in	(working copy)
> @@ -2431,7 +2431,7 @@ alloc-pool.o : alloc-pool.c $(CONFIG_H) 
>  auto-inc-dec.o : auto-inc-dec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
>     $(TREE_H) $(RTL_H) $(TM_P_H) hard-reg-set.h $(BASIC_BLOCK_H) insn-config.h \
>     $(REGS_H) $(FLAGS_H) output.h $(FUNCTION_H) except.h toplev.h $(RECOG_H) \
> -   $(EXPR_H) $(TIMEVAR_H) tree-pass.h $(DF_H) 
> +   $(EXPR_H) $(TIMEVAR_H) tree-pass.h $(DF_H) $(DBGCNT_H)
>  cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \
>     $(REGS_H) hard-reg-set.h output.h toplev.h $(FUNCTION_H) except.h $(GGC_H) \
>     $(TM_P_H) $(TIMEVAR_H) $(OBSTACK_H) $(TREE_H) alloc-pool.h \
> @@ -2505,7 +2505,7 @@ regclass.o : regclass.c $(CONFIG_H) $(SY
>  local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
>     $(RTL_H) $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
>     output.h $(FUNCTION_H) $(INSN_ATTR_H) toplev.h  except.h reload.h $(TM_P_H) \
> -   $(GGC_H) $(INTEGRATE_H) $(TIMEVAR_H) tree-pass.h $(DF_H)
> +   $(GGC_H) $(INTEGRATE_H) $(TIMEVAR_H) tree-pass.h $(DF_H) $(DBGCNT_H)
>  bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H)  coretypes.h $(TM_H) $(RTL_H) \
>     $(FLAGS_H) $(GGC_H) gt-bitmap.h bitmap.h $(OBSTACK_H)
>  global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
> @@ -2585,11 +2585,11 @@ sched-deps.o : sched-deps.c $(CONFIG_H) 
>  sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
>     $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
>     $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(PARAMS_H) \
> -   $(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) tree-pass.h
> +   $(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) tree-pass.h $(DBGCNT_H)
>  sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
>     $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
>     $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) \
> -   $(PARAMS_H) $(CFGLAYOUT_H) $(TARGET_H) output.h
> +   $(PARAMS_H) $(CFGLAYOUT_H) $(TARGET_H) output.h 
>  sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
>     $(RTL_H) $(SCHED_INT_H) hard-reg-set.h $(BASIC_BLOCK_H) $(OBSTACK_H) \
>     $(TM_P_H) $(REAL_H) toplev.h tree-pass.h
> @@ -2603,7 +2603,7 @@ recog.o : recog.c $(CONFIG_H) $(SYSTEM_H
>     $(FUNCTION_H) $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) \
>     $(FLAGS_H) insn-config.h $(INSN_ATTR_H) toplev.h output.h reload.h \
>     addresses.h $(TM_P_H) $(TIMEVAR_H) tree-pass.h hard-reg-set.h $(REAL_H) \
> -   $(DF_H)
> +   $(DF_H) $(DBGCNT_H)
>  reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
>     $(RTL_H) $(TREE_H) $(RECOG_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
>     insn-config.h toplev.h reload.h $(FUNCTION_H) $(TM_P_H) $(GGC_H) \
> Index: sched-rgn.c
> ===================================================================
> --- sched-rgn.c	(revision 119260)
> +++ sched-rgn.c	(working copy)
> @@ -67,6 +67,7 @@ Software Foundation, 51 Franklin Street,
>  #include "target.h"
>  #include "timevar.h"
>  #include "tree-pass.h"
> +#include "dbgcnt.h"
>  
>  #ifdef INSN_SCHEDULING
>  /* Some accessor macros for h_i_d members only used within this file.  */
> @@ -2919,7 +2920,8 @@ schedule_insns (void)
>    
>    /* Schedule every region in the subroutine.  */
>    for (rgn = 0; rgn < nr_regions; rgn++)
> -    schedule_region (rgn);
> +    if (dbg_cnt (sched_region))
> +      schedule_region (rgn);
>    
>    free(ebb_head);
>    /* Reposition the prologue and epilogue notes in case we moved the
> @@ -3105,7 +3107,7 @@ static bool
>  gate_handle_sched (void)
>  {
>  #ifdef INSN_SCHEDULING
> -  return flag_schedule_insns;
> +  return flag_schedule_insns && dbg_cnt (sched_func);
>  #else
>    return 0;
>  #endif
> @@ -3125,7 +3127,8 @@ static bool
>  gate_handle_sched2 (void)
>  {
>  #ifdef INSN_SCHEDULING
> -  return optimize > 0 && flag_schedule_insns_after_reload;
> +  return optimize > 0 && flag_schedule_insns_after_reload 
> +    && dbg_cnt (sched2_func);
>  #else
>    return 0;
>  #endif
> Index: config/ia64/ia64.c
> ===================================================================
> --- config/ia64/ia64.c	(revision 119260)
> +++ config/ia64/ia64.c	(working copy)
> @@ -56,6 +56,7 @@ Boston, MA 02110-1301, USA.  */
>  #include "df.h"
>  #include "debug.h"
>  #include "params.h"
> +#include "dbgcnt.h"
>  
>  /* This is used for communication between ASM_OUTPUT_LABEL and
>     ASM_OUTPUT_LABELREF.  */
> @@ -125,6 +126,18 @@ int bundling_p = 0;
>  /* Structure to be filled in by ia64_compute_frame_size with register
>     save masks and offsets for the current function.  */
>  
> +enum ia64_frame_regs
> +{
> +   reg_fp,
> +   reg_save_b0,
> +   reg_save_pr,
> +   reg_save_ar_pfs,
> +   reg_save_ar_unat,
> +   reg_save_ar_lc,
> +   reg_save_gp,
> +   number_of_ia64_frame_regs
> +};
> +
>  struct ia64_frame_info
>  {
>    HOST_WIDE_INT total_size;	/* size of the stack frame, not including
> @@ -136,6 +149,8 @@ struct ia64_frame_info
>    unsigned int gr_used_mask;	/* mask of registers in use as gr spill
>  				   registers or long-term scratches.  */
>    int n_spilled;		/* number of spilled registers.  */
> +  int r[number_of_ia64_frame_regs];
> +#if 0
>    int reg_fp;			/* register for fp.  */
>    int reg_save_b0;		/* save register for b0.  */
>    int reg_save_pr;		/* save register for prs.  */
> @@ -143,6 +158,7 @@ struct ia64_frame_info
>    int reg_save_ar_unat;		/* save register for ar.unat.  */
>    int reg_save_ar_lc;		/* save register for ar.lc.  */
>    int reg_save_gp;		/* save register for gp.  */
> +#endif
>    int n_input_regs;		/* number of input registers used.  */
>    int n_local_regs;		/* number of local registers used.  */
>    int n_output_regs;		/* number of output registers used.  */
> @@ -154,6 +170,8 @@ struct ia64_frame_info
>  
>  /* Current frame information calculated by ia64_compute_frame_size.  */
>  static struct ia64_frame_info current_frame_info;
> +/* The actual registers that are emitted.  */
> +static int emitted_frame_related_regs[number_of_ia64_frame_regs];
>  
>  static int ia64_first_cycle_multipass_dfa_lookahead (void);
>  static void ia64_dependencies_evaluation_hook (rtx, rtx);
> @@ -173,7 +191,7 @@ static int ia64_spec_check_p (rtx);
>  static int ia64_spec_check_src_p (rtx);
>  static rtx gen_tls_get_addr (void);
>  static rtx gen_thread_pointer (void);
> -static int find_gr_spill (int);
> +static int find_gr_spill (enum ia64_frame_regs, int);
>  static int next_scratch_gr_reg (void);
>  static void mark_reg_gr_used_mask (rtx, void *);
>  static void ia64_compute_frame_size (HOST_WIDE_INT);
> @@ -1970,15 +1988,41 @@ ia64_expand_call (rtx retval, rtx addr, 
>      use_reg (&CALL_INSN_FUNCTION_USAGE (insn), b0);
>  }
>  
> +static void
> +reg_emitted (enum ia64_frame_regs r)
> +{
> +  if (emitted_frame_related_regs[r] == 0)
> +    emitted_frame_related_regs[r] = current_frame_info.r[r];
> +  else
> +    gcc_assert (emitted_frame_related_regs[r] == current_frame_info.r[r]);
> +}
> +
> +static int
> +get_reg (enum ia64_frame_regs r)
> +{
> +  reg_emitted (r);
> +  return current_frame_info.r[r];
> +}
> +
> +static bool
> +is_emitted (int regno)
> +{
> +  enum ia64_frame_regs r;
> +
> +  for (r = reg_fp; r < number_of_ia64_frame_regs; r++)
> +    if (emitted_frame_related_regs[r] == regno)
> +      return true;
> +  return false;
> +}
> +
>  void
>  ia64_reload_gp (void)
>  {
>    rtx tmp;
>  
> -  if (current_frame_info.reg_save_gp)
> +  if (current_frame_info.r[reg_save_gp])
>      {
> -      tmp = gen_rtx_REG (DImode, current_frame_info.reg_save_gp);
> -      current_frame_info.initialized = 1;
> +      tmp = gen_rtx_REG (DImode, get_reg (reg_save_gp));
>      }
>    else
>      {
> @@ -2240,10 +2284,22 @@ emit_safe_across_calls (void)
>     TRY_LOCALS is true if we should attempt to locate a local regnum.  */
>  
>  static int
> -find_gr_spill (int try_locals)
> +find_gr_spill (enum ia64_frame_regs r, int try_locals)
>  {
>    int regno;
>  
> +  if (emitted_frame_related_regs[r] != 0)
> +    {
> +      regno = emitted_frame_related_regs[r];
> +      if (regno >= LOC_REG (0) && regno < LOC_REG (80 - frame_pointer_needed))
> +        current_frame_info.n_local_regs = regno - LOC_REG (0) + 1;
> +      else if (current_function_is_leaf 
> +               && regno >= GR_REG (1) && regno <= GR_REG (31))
> +        current_frame_info.gr_used_mask |= 1 << regno;
> +
> +      return regno;
> +    }
> +
>    /* If this is a leaf function, first try an otherwise unused
>       call-clobbered register.  */
>    if (current_function_is_leaf)
> @@ -2253,7 +2309,8 @@ find_gr_spill (int try_locals)
>  	    && call_used_regs[regno]
>  	    && ! fixed_regs[regno]
>  	    && ! global_regs[regno]
> -	    && ((current_frame_info.gr_used_mask >> regno) & 1) == 0)
> +	    && ((current_frame_info.gr_used_mask >> regno) & 1) == 0
> +            && ! is_emitted (regno))
>  	  {
>  	    current_frame_info.gr_used_mask |= 1 << regno;
>  	    return regno;
> @@ -2325,6 +2382,7 @@ mark_reg_gr_used_mask (rtx reg, void *da
>      }
>  }
>  
> +
>  /* Returns the number of bytes offset between the frame pointer and the stack
>     pointer for the current function.  SIZE is the number of bytes of space
>     needed for local variables.  */
> @@ -2366,7 +2424,7 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>       since we'll be adjusting that down later.  */
>    regno = LOC_REG (78) + ! frame_pointer_needed;
>    for (; regno >= LOC_REG (0); regno--)
> -    if (regs_ever_live[regno])
> +    if (regs_ever_live[regno] && !is_emitted (regno))
>        break;
>    current_frame_info.n_local_regs = regno - LOC_REG (0) + 1;
>  
> @@ -2439,15 +2497,15 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>  
>    if (frame_pointer_needed)
>      {
> -      current_frame_info.reg_fp = find_gr_spill (1);
> +      current_frame_info.r[reg_fp] = find_gr_spill (reg_fp, 1);
>        /* If we did not get a register, then we take LOC79.  This is guaranteed
>  	 to be free, even if regs_ever_live is already set, because this is
>  	 HARD_FRAME_POINTER_REGNUM.  This requires incrementing n_local_regs,
>  	 as we don't count loc79 above.  */
> -      if (current_frame_info.reg_fp == 0)
> +      if (current_frame_info.r[reg_fp] == 0)
>  	{
> -	  current_frame_info.reg_fp = LOC_REG (79);
> -	  current_frame_info.n_local_regs++;
> +	  current_frame_info.r[reg_fp] = LOC_REG (79);
> +	  current_frame_info.n_local_regs = LOC_REG (79) - LOC_REG (0) + 1;
>  	}
>      }
>  
> @@ -2458,8 +2516,9 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>  	 able to unwind the stack.  */
>        SET_HARD_REG_BIT (mask, BR_REG (0));
>  
> -      current_frame_info.reg_save_b0 = find_gr_spill (1);
> -      if (current_frame_info.reg_save_b0 == 0)
> +      current_frame_info.r[reg_save_b0] = find_gr_spill (reg_save_b0, 1);
> +      /* reg_emitted (reg_save_b0); */
> +      if (current_frame_info.r[reg_save_b0] == 0)
>  	{
>  	  spill_size += 8;
>  	  n_spilled += 1;
> @@ -2467,8 +2526,8 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>  
>        /* Similarly for ar.pfs.  */
>        SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);
> -      current_frame_info.reg_save_ar_pfs = find_gr_spill (1);
> -      if (current_frame_info.reg_save_ar_pfs == 0)
> +      current_frame_info.r[reg_save_ar_pfs] = find_gr_spill (reg_save_ar_pfs, 1);
> +      if (current_frame_info.r[reg_save_ar_pfs] == 0)
>  	{
>  	  extra_spill_size += 8;
>  	  n_spilled += 1;
> @@ -2476,9 +2535,10 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>  
>        /* Similarly for gp.  Note that if we're calling setjmp, the stacked
>  	 registers are clobbered, so we fall back to the stack.  */
> -      current_frame_info.reg_save_gp
> -	= (current_function_calls_setjmp ? 0 : find_gr_spill (1));
> -      if (current_frame_info.reg_save_gp == 0)
> +      current_frame_info.r[reg_save_gp]
> +	= (current_function_calls_setjmp ? 0 : find_gr_spill (reg_save_gp, 1));
> +      /* reg_emitted (reg_save_gp); */
> +      if (current_frame_info.r[reg_save_gp] == 0)
>  	{
>  	  SET_HARD_REG_BIT (mask, GR_REG (1));
>  	  spill_size += 8;
> @@ -2497,8 +2557,10 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>        if (regs_ever_live[AR_PFS_REGNUM])
>  	{
>  	  SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);
> -	  current_frame_info.reg_save_ar_pfs = find_gr_spill (1);
> -	  if (current_frame_info.reg_save_ar_pfs == 0)
> + 	  current_frame_info.r[reg_save_ar_pfs] 
> +            = find_gr_spill (reg_save_ar_pfs, 1);
> +          /* reg_emitted (reg_save_ar_pfs); */
> +	  if (current_frame_info.r[reg_save_ar_pfs] == 0)
>  	    {
>  	      extra_spill_size += 8;
>  	      n_spilled += 1;
> @@ -2511,14 +2573,20 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>       it is absolutely critical that FP get the only hard register that's
>       guaranteed to be free, so we allocated it first.  If all three did
>       happen to be allocated hard regs, and are consecutive, rearrange them
> -     into the preferred order now.  */
> -  if (current_frame_info.reg_fp != 0
> -      && current_frame_info.reg_save_b0 == current_frame_info.reg_fp + 1
> -      && current_frame_info.reg_save_ar_pfs == current_frame_info.reg_fp + 2)
> -    {
> -      current_frame_info.reg_save_b0 = current_frame_info.reg_fp;
> -      current_frame_info.reg_save_ar_pfs = current_frame_info.reg_fp + 1;
> -      current_frame_info.reg_fp = current_frame_info.reg_fp + 2;
> +     into the preferred order now.  
> +     
> +     If we have already emitted code for any of those registers,
> +     then it's already too late to change.  */
> +  if (current_frame_info.r[reg_fp] != 0
> +      && current_frame_info.r[reg_save_b0] == current_frame_info.r[reg_fp] + 1
> +      && current_frame_info.r[reg_save_ar_pfs] == current_frame_info.r[reg_fp] + 2
> +      && emitted_frame_related_regs[reg_save_b0] == 0
> +      && emitted_frame_related_regs[reg_save_ar_pfs] == 0
> +      && emitted_frame_related_regs[reg_fp] == 0)
> +    {
> +      current_frame_info.r[reg_save_b0] = current_frame_info.r[reg_fp];
> +      current_frame_info.r[reg_save_ar_pfs] = current_frame_info.r[reg_fp] + 1;
> +      current_frame_info.r[reg_fp] = current_frame_info.r[reg_fp] + 2;
>      }
>  
>    /* See if we need to store the predicate register block.  */
> @@ -2528,8 +2596,9 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>    if (regno <= PR_REG (63))
>      {
>        SET_HARD_REG_BIT (mask, PR_REG (0));
> -      current_frame_info.reg_save_pr = find_gr_spill (1);
> -      if (current_frame_info.reg_save_pr == 0)
> +      current_frame_info.r[reg_save_pr] = find_gr_spill (reg_save_pr, 1);
> +      /* reg_emitted (reg_save_pr); */
> +      if (current_frame_info.r[reg_save_pr] == 0)
>  	{
>  	  extra_spill_size += 8;
>  	  n_spilled += 1;
> @@ -2549,8 +2618,10 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>      {
>        regs_ever_live[AR_UNAT_REGNUM] = 1;
>        SET_HARD_REG_BIT (mask, AR_UNAT_REGNUM);
> -      current_frame_info.reg_save_ar_unat = find_gr_spill (spill_size == 0);
> -      if (current_frame_info.reg_save_ar_unat == 0)
> +      current_frame_info.r[reg_save_ar_unat] 
> +        = find_gr_spill (reg_save_ar_unat, spill_size == 0);
> +      /* reg_emitted (reg_save_ar_unat); */
> +      if (current_frame_info.r[reg_save_ar_unat] == 0)
>  	{
>  	  extra_spill_size += 8;
>  	  n_spilled += 1;
> @@ -2560,8 +2631,10 @@ ia64_compute_frame_size (HOST_WIDE_INT s
>    if (regs_ever_live[AR_LC_REGNUM])
>      {
>        SET_HARD_REG_BIT (mask, AR_LC_REGNUM);
> -      current_frame_info.reg_save_ar_lc = find_gr_spill (spill_size == 0);
> -      if (current_frame_info.reg_save_ar_lc == 0)
> +      current_frame_info.r[reg_save_ar_lc] 
> +        = find_gr_spill (reg_save_ar_lc, spill_size == 0);
> +      /* reg_emitted (reg_save_ar_lc); */
> +      if (current_frame_info.r[reg_save_ar_lc] == 0)
>  	{
>  	  extra_spill_size += 8;
>  	  n_spilled += 1;
> @@ -2932,6 +3005,19 @@ ia64_expand_prologue (void)
>    ia64_compute_frame_size (get_frame_size ());
>    last_scratch_gr_reg = 15;
>  
> +  if (dump_file) 
> +    {
> +#define PRINTREG(a) if (current_frame_info.r[a]) fprintf(dump_file, "%s = %d\n", #a, current_frame_info.r[a])
> +      PRINTREG(reg_fp);
> +      PRINTREG(reg_save_b0);
> +      PRINTREG(reg_save_pr);
> +      PRINTREG(reg_save_ar_pfs);
> +      PRINTREG(reg_save_ar_unat);
> +      PRINTREG(reg_save_ar_lc);
> +      PRINTREG(reg_save_gp);
> +#undef PRINTREG
> +    }
> +
>    /* If there is no epilogue, then we don't need some prologue insns.
>       We need to avoid emitting the dead prologue insns, because flow
>       will complain about them.  */
> @@ -2974,12 +3060,12 @@ ia64_expand_prologue (void)
>       there is a frame pointer.  loc79 gets wasted in this case, as it is
>       renamed to a register that will never be used.  See also the try_locals
>       code in find_gr_spill.  */
> -  if (current_frame_info.reg_fp)
> +  if (current_frame_info.r[reg_fp])
>      {
>        const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];
>        reg_names[HARD_FRAME_POINTER_REGNUM]
> -	= reg_names[current_frame_info.reg_fp];
> -      reg_names[current_frame_info.reg_fp] = tmp;
> +	= reg_names[current_frame_info.r[reg_fp]];
> +      reg_names[current_frame_info.r[reg_fp]] = tmp;
>      }
>  
>    /* We don't need an alloc instruction if we've used no outputs or locals.  */
> @@ -2997,8 +3083,11 @@ ia64_expand_prologue (void)
>      {
>        current_frame_info.need_regstk = 0;
>  
> -      if (current_frame_info.reg_save_ar_pfs)
> -	regno = current_frame_info.reg_save_ar_pfs;
> +      if (current_frame_info.r[reg_save_ar_pfs])
> +        {
> +	  regno = current_frame_info.r[reg_save_ar_pfs];
> +	  reg_emitted (reg_save_ar_pfs);
> +	}
>        else
>  	regno = next_scratch_gr_reg ();
>        ar_pfs_save_reg = gen_rtx_REG (DImode, regno);
> @@ -3008,7 +3097,7 @@ ia64_expand_prologue (void)
>  				   GEN_INT (current_frame_info.n_local_regs),
>  				   GEN_INT (current_frame_info.n_output_regs),
>  				   GEN_INT (current_frame_info.n_rotate_regs)));
> -      RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_pfs != 0);
> +      RTX_FRAME_RELATED_P (insn) = (current_frame_info.r[reg_save_ar_pfs] != 0);
>      }
>  
>    /* Set up frame pointer, stack pointer, and spill iterators.  */
> @@ -3066,9 +3155,12 @@ ia64_expand_prologue (void)
>    /* Must copy out ar.unat before doing any integer spills.  */
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM))
>      {
> -      if (current_frame_info.reg_save_ar_unat)
> -	ar_unat_save_reg
> -	  = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_unat);
> +      if (current_frame_info.r[reg_save_ar_unat])
> +        {
> +	  ar_unat_save_reg
> +	    = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_unat]);
> +	  reg_emitted (reg_save_ar_unat);
> +	}
>        else
>  	{
>  	  alt_regno = next_scratch_gr_reg ();
> @@ -3078,11 +3170,11 @@ ia64_expand_prologue (void)
>  
>        reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
>        insn = emit_move_insn (ar_unat_save_reg, reg);
> -      RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_unat != 0);
> +      RTX_FRAME_RELATED_P (insn) = (current_frame_info.r[reg_save_ar_unat] != 0);
>  
>        /* Even if we're not going to generate an epilogue, we still
>  	 need to save the register so that EH works.  */
> -      if (! epilogue_p && current_frame_info.reg_save_ar_unat)
> +      if (! epilogue_p && current_frame_info.r[reg_save_ar_unat])
>  	emit_insn (gen_prologue_use (ar_unat_save_reg));
>      }
>    else
> @@ -3108,9 +3200,10 @@ ia64_expand_prologue (void)
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, PR_REG (0)))
>      {
>        reg = gen_rtx_REG (DImode, PR_REG (0));
> -      if (current_frame_info.reg_save_pr != 0)
> +      if (current_frame_info.r[reg_save_pr] != 0)
>  	{
> -	  alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_pr);
> +	  alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_pr]);
> +	  reg_emitted (reg_save_pr);
>  	  insn = emit_move_insn (alt_reg, reg);
>  
>  	  /* ??? Denote pr spill/fill by a DImode move that modifies all
> @@ -3138,7 +3231,7 @@ ia64_expand_prologue (void)
>  
>    /* Handle AR regs in numerical order.  All of them get special handling.  */
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM)
> -      && current_frame_info.reg_save_ar_unat == 0)
> +      && current_frame_info.r[reg_save_ar_unat] == 0)
>      {
>        reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
>        do_spill (gen_movdi_x, ar_unat_save_reg, cfa_off, reg);
> @@ -3149,7 +3242,7 @@ ia64_expand_prologue (void)
>       only thing we have to do now is copy that register to a stack slot
>       if we'd not allocated a local register for the job.  */
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM)
> -      && current_frame_info.reg_save_ar_pfs == 0)
> +      && current_frame_info.r[reg_save_ar_pfs] == 0)
>      {
>        reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
>        do_spill (gen_movdi_x, ar_pfs_save_reg, cfa_off, reg);
> @@ -3159,9 +3252,10 @@ ia64_expand_prologue (void)
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_LC_REGNUM))
>      {
>        reg = gen_rtx_REG (DImode, AR_LC_REGNUM);
> -      if (current_frame_info.reg_save_ar_lc != 0)
> +      if (current_frame_info.r[reg_save_ar_lc] != 0)
>  	{
> -	  alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_lc);
> +	  alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_lc]);
> +	  reg_emitted (reg_save_ar_lc);
>  	  insn = emit_move_insn (alt_reg, reg);
>  	  RTX_FRAME_RELATED_P (insn) = 1;
>  
> @@ -3180,10 +3274,11 @@ ia64_expand_prologue (void)
>  	}
>      }
>  
> -  if (current_frame_info.reg_save_gp)
> +  if (current_frame_info.r[reg_save_gp])
>      {
> +      reg_emitted (reg_save_gp);
>        insn = emit_move_insn (gen_rtx_REG (DImode,
> -					  current_frame_info.reg_save_gp),
> +					  current_frame_info.r[reg_save_gp]),
>  			     pic_offset_table_rtx);
>        /* We don't know for sure yet if this is actually needed, since
>  	 we've not split the PIC call patterns.  If all of the calls
> @@ -3211,9 +3306,10 @@ ia64_expand_prologue (void)
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
>      {
>        reg = gen_rtx_REG (DImode, BR_REG (0));
> -      if (current_frame_info.reg_save_b0 != 0)
> +      if (current_frame_info.r[reg_save_b0] != 0)
>  	{
> -	  alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
> +	  reg_emitted (reg_save_b0);
> +	  alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_b0]);
>  	  insn = emit_move_insn (alt_reg, reg);
>  	  RTX_FRAME_RELATED_P (insn) = 1;
>  
> @@ -3300,8 +3396,11 @@ ia64_expand_epilogue (int sibcall_p)
>    /* Restore the predicate registers.  */
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, PR_REG (0)))
>      {
> -      if (current_frame_info.reg_save_pr != 0)
> -	alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_pr);
> +      if (current_frame_info.r[reg_save_pr] != 0)
> +        {
> +	  alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_pr]);
> +	  reg_emitted (reg_save_pr);
> +	}
>        else
>  	{
>  	  alt_regno = next_scratch_gr_reg ();
> @@ -3319,9 +3418,12 @@ ia64_expand_epilogue (int sibcall_p)
>       after the GRs have been restored.  */
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM))
>      {
> -      if (current_frame_info.reg_save_ar_unat != 0)
> -        ar_unat_save_reg
> -	  = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_unat);
> +      if (current_frame_info.r[reg_save_ar_unat] != 0)
> +        {
> +          ar_unat_save_reg
> +	    = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_unat]);
> +	  reg_emitted (reg_save_ar_unat);
> +	}
>        else
>  	{
>  	  alt_regno = next_scratch_gr_reg ();
> @@ -3334,9 +3436,10 @@ ia64_expand_epilogue (int sibcall_p)
>    else
>      ar_unat_save_reg = NULL_RTX;
>  
> -  if (current_frame_info.reg_save_ar_pfs != 0)
> +  if (current_frame_info.r[reg_save_ar_pfs] != 0)
>      {
> -      alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_pfs);
> +      reg_emitted (reg_save_ar_pfs);
> +      alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_pfs]);
>        reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
>        emit_move_insn (reg, alt_reg);
>      }
> @@ -3352,8 +3455,11 @@ ia64_expand_epilogue (int sibcall_p)
>  
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_LC_REGNUM))
>      {
> -      if (current_frame_info.reg_save_ar_lc != 0)
> -	alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_lc);
> +      if (current_frame_info.r[reg_save_ar_lc] != 0)
> +        {
> +	  alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_lc]);
> +          reg_emitted (reg_save_ar_lc);
> +	}
>        else
>  	{
>  	  alt_regno = next_scratch_gr_reg ();
> @@ -3387,8 +3493,11 @@ ia64_expand_epilogue (int sibcall_p)
>       have gotten stored in some GR register.  */
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
>      {
> -      if (current_frame_info.reg_save_b0 != 0)
> -	alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
> +      if (current_frame_info.r[reg_save_b0] != 0)
> +        {
> +	  alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_b0]);
> +	  reg_emitted (reg_save_b0);
> +	}
>        else
>  	{
>  	  alt_regno = next_scratch_gr_reg ();
> @@ -3492,7 +3601,8 @@ ia64_expand_epilogue (int sibcall_p)
>  	 register, we may have swapped the names of r2 and HARD_FRAME_POINTER_REGNUM,
>  	 so we have to make sure we're using the string "r2" when emitting
>  	 the register name for the assembler.  */
> -      if (current_frame_info.reg_fp && current_frame_info.reg_fp == GR_REG (2))
> +      if (current_frame_info.r[reg_fp] 
> +          && current_frame_info.r[reg_fp] == GR_REG (2))
>  	fp = HARD_FRAME_POINTER_REGNUM;
>  
>        /* We must emit an alloc to force the input registers to become output
> @@ -3525,11 +3635,11 @@ ia64_direct_return (void)
>  
>        return (current_frame_info.total_size == 0
>  	      && current_frame_info.n_spilled == 0
> -	      && current_frame_info.reg_save_b0 == 0
> -	      && current_frame_info.reg_save_pr == 0
> -	      && current_frame_info.reg_save_ar_pfs == 0
> -	      && current_frame_info.reg_save_ar_unat == 0
> -	      && current_frame_info.reg_save_ar_lc == 0);
> +	      && current_frame_info.r[reg_save_b0] == 0
> +	      && current_frame_info.r[reg_save_pr] == 0
> +	      && current_frame_info.r[reg_save_ar_pfs] == 0
> +	      && current_frame_info.r[reg_save_ar_unat] == 0
> +	      && current_frame_info.r[reg_save_ar_lc] == 0);
>      }
>    return 0;
>  }
> @@ -3555,10 +3665,10 @@ ia64_split_return_addr_rtx (rtx dest)
>  
>    if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
>      {
> -      if (current_frame_info.reg_save_b0 != 0)
> +      if (current_frame_info.r[reg_save_b0] != 0)
>          {
> -	  src = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
> -	  current_frame_info.initialized = 1;
> +	  src = gen_rtx_REG (DImode, current_frame_info.r[reg_save_b0]);
> +	  reg_emitted (reg_save_b0);
>  	}
>        else
>  	{
> @@ -3604,21 +3714,14 @@ int
>  ia64_hard_regno_rename_ok (int from, int to)
>  {
>    /* Don't clobber any of the registers we reserved for the prologue.  */
> -  if (to == current_frame_info.reg_fp
> -      || to == current_frame_info.reg_save_b0
> -      || to == current_frame_info.reg_save_pr
> -      || to == current_frame_info.reg_save_ar_pfs
> -      || to == current_frame_info.reg_save_ar_unat
> -      || to == current_frame_info.reg_save_ar_lc)
> -    return 0;
> +  enum ia64_frame_regs r;
>  
> -  if (from == current_frame_info.reg_fp
> -      || from == current_frame_info.reg_save_b0
> -      || from == current_frame_info.reg_save_pr
> -      || from == current_frame_info.reg_save_ar_pfs
> -      || from == current_frame_info.reg_save_ar_unat
> -      || from == current_frame_info.reg_save_ar_lc)
> -    return 0;
> +  for (r = reg_fp; r <= reg_save_ar_lc; r++)
> +    if (to == current_frame_info.r[r] 
> +        || from == current_frame_info.r[r]
> +        || to == emitted_frame_related_regs[r]
> +        || from == emitted_frame_related_regs[r])
> +      return 0;
>  
>    /* Don't use output registers outside the register frame.  */
>    if (OUT_REGNO_P (to) && to >= OUT_REG (current_frame_info.n_output_regs))
> @@ -3676,36 +3779,36 @@ ia64_output_function_prologue (FILE *fil
>  
>    mask = 0;
>    grsave = grsave_prev = 0;
> -  if (current_frame_info.reg_save_b0 != 0)
> +  if (current_frame_info.r[reg_save_b0] != 0)
>      {
>        mask |= 8;
> -      grsave = grsave_prev = current_frame_info.reg_save_b0;
> +      grsave = grsave_prev = current_frame_info.r[reg_save_b0];
>      }
> -  if (current_frame_info.reg_save_ar_pfs != 0
> +  if (current_frame_info.r[reg_save_ar_pfs] != 0
>        && (grsave_prev == 0
> -	  || current_frame_info.reg_save_ar_pfs == grsave_prev + 1))
> +	  || current_frame_info.r[reg_save_ar_pfs] == grsave_prev + 1))
>      {
>        mask |= 4;
>        if (grsave_prev == 0)
> -	grsave = current_frame_info.reg_save_ar_pfs;
> -      grsave_prev = current_frame_info.reg_save_ar_pfs;
> +	grsave = current_frame_info.r[reg_save_ar_pfs];
> +      grsave_prev = current_frame_info.r[reg_save_ar_pfs];
>      }
> -  if (current_frame_info.reg_fp != 0
> +  if (current_frame_info.r[reg_fp] != 0
>        && (grsave_prev == 0
> -	  || current_frame_info.reg_fp == grsave_prev + 1))
> +	  || current_frame_info.r[reg_fp] == grsave_prev + 1))
>      {
>        mask |= 2;
>        if (grsave_prev == 0)
>  	grsave = HARD_FRAME_POINTER_REGNUM;
> -      grsave_prev = current_frame_info.reg_fp;
> +      grsave_prev = current_frame_info.r[reg_fp];
>      }
> -  if (current_frame_info.reg_save_pr != 0
> +  if (current_frame_info.r[reg_save_pr] != 0
>        && (grsave_prev == 0
> -	  || current_frame_info.reg_save_pr == grsave_prev + 1))
> +	  || current_frame_info.r[reg_save_pr] == grsave_prev + 1))
>      {
>        mask |= 1;
>        if (grsave_prev == 0)
> -	grsave = current_frame_info.reg_save_pr;
> +	grsave = current_frame_info.r[reg_save_pr];
>      }
>  
>    if (mask && TARGET_GNU_AS)
> @@ -3741,12 +3844,13 @@ ia64_output_function_epilogue (FILE *fil
>  {
>    int i;
>  
> -  if (current_frame_info.reg_fp)
> +  if (current_frame_info.r[reg_fp])
>      {
>        const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];
>        reg_names[HARD_FRAME_POINTER_REGNUM]
> -	= reg_names[current_frame_info.reg_fp];
> -      reg_names[current_frame_info.reg_fp] = tmp;
> +	= reg_names[current_frame_info.r[reg_fp]];
> +      reg_names[current_frame_info.r[reg_fp]] = tmp;
> +      reg_emitted (reg_fp);
>      }
>    if (! TARGET_REG_NAMES)
>      {
> @@ -3767,11 +3871,11 @@ ia64_dbx_register_number (int regno)
>    /* In ia64_expand_prologue we quite literally renamed the frame pointer
>       from its home at loc79 to something inside the register frame.  We
>       must perform the same renumbering here for the debug info.  */
> -  if (current_frame_info.reg_fp)
> +  if (current_frame_info.r[reg_fp])
>      {
>        if (regno == HARD_FRAME_POINTER_REGNUM)
> -	regno = current_frame_info.reg_fp;
> -      else if (regno == current_frame_info.reg_fp)
> +	regno = current_frame_info.r[reg_fp];
> +      else if (regno == current_frame_info.r[reg_fp])
>  	regno = HARD_FRAME_POINTER_REGNUM;
>      }
>  
> @@ -5208,6 +5312,11 @@ ia64_override_options (void)
>    init_machine_status = ia64_init_machine_status;
>  }
>  
> +void ia64_init_expanders (void)
> +{
> +  memset (&emitted_frame_related_regs, 0, sizeof (emitted_frame_related_regs));
> +}
> +
>  static struct machine_function *
>  ia64_init_machine_status (void)
>  {
> @@ -8453,7 +8562,7 @@ ia64_reorg (void)
>    if (optimize == 0)
>      split_all_insns ();
>  
> -  if (optimize && ia64_flag_schedule_insns2)
> +  if (optimize && ia64_flag_schedule_insns2 && dbg_cnt (ia64_sched2))
>      {
>        timevar_push (TV_SCHED2);
>        ia64_final_schedule = 1;
> @@ -8634,24 +8743,18 @@ ia64_epilogue_uses (int regno)
>  int
>  ia64_eh_uses (int regno)
>  {
> +  enum ia64_frame_regs r;
> +
>    if (! reload_completed)
>      return 0;
>  
> -  if (current_frame_info.reg_save_b0
> -      && regno == current_frame_info.reg_save_b0)
> -    return 1;
> -  if (current_frame_info.reg_save_pr
> -      && regno == current_frame_info.reg_save_pr)
> -    return 1;
> -  if (current_frame_info.reg_save_ar_pfs
> -      && regno == current_frame_info.reg_save_ar_pfs)
> -    return 1;
> -  if (current_frame_info.reg_save_ar_unat
> -      && regno == current_frame_info.reg_save_ar_unat)
> -    return 1;
> -  if (current_frame_info.reg_save_ar_lc
> -      && regno == current_frame_info.reg_save_ar_lc)
> -    return 1;
> +  if (regno == 0)
> +    return 0;
> +
> +  for (r = reg_save_b0; r <= reg_save_ar_lc; r++)
> +    if (regno == current_frame_info.r[r]
> +       || regno == emitted_frame_related_regs[r])
> +      return 1;
>  
>    return 0;
>  }
> @@ -8804,7 +8907,7 @@ process_set (FILE *asm_out_file, rtx pat
>  
>        /* If this is the final destination for ar.pfs, then this must
>  	 be the alloc in the prologue.  */
> -      if (dest_regno == current_frame_info.reg_save_ar_pfs)
> +      if (dest_regno == current_frame_info.r[reg_save_ar_pfs])
>  	{
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
> @@ -8869,28 +8972,28 @@ process_set (FILE *asm_out_file, rtx pat
>  	{
>  	case BR_REG (0):
>  	  /* Saving return address pointer.  */
> -	  gcc_assert (dest_regno == current_frame_info.reg_save_b0);
> +	  gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]);
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t.save rp, r%d\n",
>  		     ia64_dbx_register_number (dest_regno));
>  	  return 1;
>  
>  	case PR_REG (0):
> -	  gcc_assert (dest_regno == current_frame_info.reg_save_pr);
> +	  gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]);
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t.save pr, r%d\n",
>  		     ia64_dbx_register_number (dest_regno));
>  	  return 1;
>  
>  	case AR_UNAT_REGNUM:
> -	  gcc_assert (dest_regno == current_frame_info.reg_save_ar_unat);
> +	  gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]);
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
>  		     ia64_dbx_register_number (dest_regno));
>  	  return 1;
>  
>  	case AR_LC_REGNUM:
> -	  gcc_assert (dest_regno == current_frame_info.reg_save_ar_lc);
> +	  gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]);
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
>  		     ia64_dbx_register_number (dest_regno));
> @@ -8947,31 +9050,31 @@ process_set (FILE *asm_out_file, rtx pat
>        switch (src_regno)
>  	{
>  	case BR_REG (0):
> -	  gcc_assert (!current_frame_info.reg_save_b0);
> +	  gcc_assert (!current_frame_info.r[reg_save_b0]);
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
>  	  return 1;
>  
>  	case PR_REG (0):
> -	  gcc_assert (!current_frame_info.reg_save_pr);
> +	  gcc_assert (!current_frame_info.r[reg_save_pr]);
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
>  	  return 1;
>  
>  	case AR_LC_REGNUM:
> -	  gcc_assert (!current_frame_info.reg_save_ar_lc);
> +	  gcc_assert (!current_frame_info.r[reg_save_ar_lc]);
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
>  	  return 1;
>  
>  	case AR_PFS_REGNUM:
> -	  gcc_assert (!current_frame_info.reg_save_ar_pfs);
> +	  gcc_assert (!current_frame_info.r[reg_save_ar_pfs]);
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
>  	  return 1;
>  
>  	case AR_UNAT_REGNUM:
> -	  gcc_assert (!current_frame_info.reg_save_ar_unat);
> +	  gcc_assert (!current_frame_info.r[reg_save_ar_unat]);
>  	  if (unwind)
>  	    fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
>  	  return 1;
> Index: config/ia64/ia64.h
> ===================================================================
> --- config/ia64/ia64.h	(revision 119260)
> +++ config/ia64/ia64.h	(working copy)
> @@ -1048,10 +1048,12 @@ enum reg_class
>     in it.  */
>  #define ARG_POINTER_REGNUM R_GR(0)
>  
> +extern void ia64_init_expanders (void);
>  /* Due to the way varargs and argument spilling happens, the argument
>     pointer is not 16-byte aligned like the stack pointer.  */
>  #define INIT_EXPANDERS					\
>    do {							\
> +    ia64_init_expanders ();                             \
>      if (cfun && cfun->emit->regno_pointer_align)	\
>        REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) = 64;	\
>    } while (0)
>
>   


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