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]

[PATCH] FOR_EACH_RTX construct to replace for_each_rtx


This patch achieves a good speedup on bootstrap (all languages):

without
user    125m32.600s

with
user    123m13.560s

This is less than what I posted last time, but this time the machine was loaded. This may have biased the results, unfortunately I cannot afford four more hours of machine time for today.

Of course, this includes building host/build modules other than gcc, and time linking (~5 minutes for libjava!).

Uses of for_each_rtx remain in these files:

loop.c
alpha/alpha.c
frv/frv.c
i386/i386.c
ia64/ia64.c
m68hc11/m68hc11.c
mips/mips.c
rs6000/rs6000.c
s390/s390.c
sparc/sparc.c

As for loop.c, I already said I'd rather leave it aside for 4.0; the
back-ends are probably not the place where the expensive calls to
for_each_rtx come from, so it may be more appropriate to do that in 4.1
as well.

The patch is quite big.  If you want me to leave it out of
4.0, well that's fine because it was my original plan. :-)

Bootstrapped/regtested powerpc-darwin with no new failures (all
languages except Ada).  Bootstrap/regtest in progress for i686-pc-linux-gnu.

Paolo

2005-01-19  Paolo Bonzini  <bonzini@gnu.org>

	* alias.c (nonlocal_mentioned_p_1, nonlocal_referenced_p_1,
	nonlocal_set_p_1): Remove second parameter.  First parameter
	now an rtx, not an rtx *.  Do not check if the first parameter
	is NULL.
	(nonlocal_mentioned_p, nonlocal_referenced_p, nonlocal_set_p):
	Use FOR_EACH_RTX-style iteration.
	* bt-load.c (find_btr_reference, btr_referenced_p): Inline into...
	(find_btr_use): ... this one.  Add second parameter, previously taken
	by btr_referenced_p.  Use FOR_EACH_RTX-style iteration.
	(btr_reference_found): Removed.
	(insn_sets_btr_p, new_btr_user, compute_defs_uses_and_gen): Do not
	use btr_referenced_p.  Add second parameter to find_btr_use.
	* cfgcleanup.c (mentions_nonequal_regs): Take an rtx and regset,
	include iteration (via FOR_EACH_RTX) instead of demanding it to
	the caller.
	(thread_jump): Do not call mentions_nonequal_regs via for_each_rtx.
	(outgoing_edges_match, try_crossjump_to_edge): Do not call
	replace_label via for_each_rtx.
	* combine.c (unmentioned_reg_p_1): Inline into...
	(unmentioned_reg_p): ... this one.  Use FOR_EACH_RTX-style iteration.
	* cse.c (struct change_cc_mode_args, struct check_dependence_data):
	Remove.
	(approx_reg_cost_1): Inline into...
	(approx_reg_cost): ... this one.  Use FOR_EACH_RTX-style iteration.
	(check_for_label_ref): Take a single rtx, do FOR_EACH_RTX iteration.
	(check_dependence): Likewise, taking what used to be in
	struct check_dependence_data.
	(cse_change_cc_mode): Likewise, taking what used to be in
	struct change_cc_mode_args.
	(invalidate): Adjust call to check_dependence.
	(cse_basic_block): Adjust call to check_for_label_ref.
	(cse_change_cc_mode_insn): Adjust calls to cse_change_cc_mode.
	* ddg.c (mark_mem_use_1): Remove.
	(mark_mem_use): Do FOR_EACH_RTX iteration.
	(mem_read_insn_p): Pass mark_mem_use to note_uses.
	* df.c (struct replace_args): Remove.
	(df_rtx_mem_replace): Inline into...
	(df_insn_mem_replace): ... this one.  Use FOR_EACH_RTX-style iteration.
	(df_rtx_reg_replace): Inline into...
	(df_insn_reg_replace): ... this one.  Use FOR_EACH_RTX-style iteration.
	* flow.c (verify_wide_reg_1): Inline into...
	(verify_wide_reg): ... this one.  Use FOR_BB_INSNS and FOR_EACH_RTX
	for iteration.
	(find_regno_partial_param): Remove.
	(find_regno_partial): Take an rtx and regno, do FOR_EACH_RTX iteration.
	Return the rtx for the partial reg if found.
	(initialize_uninitialized_subregs):  Adjust call to find_regno_partial.
	(invalidate_mems_from_autoinc): Take a struct propagate_block_info and
	an rtx.  Do FOR_EACH_RTX iteration.
	(mark_set_1, mark_used_regs): Do not use for_each_rtx to call
	invalidate_mems_from_autoinc.
	* global.c (mark_reg_use_for_earlyclobber_1): Inline into...
	(mark_reg_use_for_earlyclobber): ... this one.  Use FOR_EACH_RTX-style
	iteration.
	(calculate_local_reg_bb_info): Pass mark_reg_use_for_earlyclobber to
	note_uses.
	* ifcvt.c (find_memory): Renamed to refers_to_mem_p.  Use FOR_EACH_RTX
	for iteration.
	(dead_or_predicable): Use refers_to_mem_p.
	* jump.c (returnjump_p_1): Inline into...
	(returnjump_p): ... this one.  Use FOR_EACH_RTX-style iteration.
	* loop-iv.c (altered_reg_used): Remove.
	(simplify_using_assignment): Inline altered_reg_used.  Change "ret"
	variable to "can_simplify", inverting the meaning.  Use FOR_EACH_RTX
	instead of for_each_rtx.
	(simplify_using_condition).  Use FOR_EACH_RTX instead of for_each_rtx,
	inlining altered_reg_used.
	* regmove.c (record_one_stack_memref): Take the "struct csa_memlist *"
	by reference.  Do nothing if the memref is not stack_memref_p.
	(struct record_stack_memrefs_data): Remove.
	(record_stack_memrefs): Take the arguments that were in struct
	record_stack_memrefs_data.  Do FOR_EACH_RTX iteration.
	Simplify the code by demanding some checks to record_one_stack_memref.
	(combine_stack_adjustments_for_block): Do not use for_each_rtx to
	call record_stack_memrefs.
	* regrename.c (kill_autoinc_value): Rename to kill_autoinc_values.
	Take a struct value_data *.  Use FOR_EACH_RTX for iteration.
	(copyprop_hardreg_forward_1): Call kill_autoinc_values.
	* rtl.h (struct replace_label_data): Remove.
	(replace_label): Take what was in struct replace_label_data.
	(FOR_EACH_RTX, rtx_iter, union rtx_stack_item, struct rtx_stack_entry,
	rtx_iter_init, rtx_iter_push_vec, rtx_iter_next, rtx_iter_skip): New.
	* rtlanal.c (global_reg_mentioned_p_1): Inline into...
	(global_reg_mentioned_p): ... this one.  Use FOR_EACH_RTX to iterate.
	(replace_label): Get arguments directly.  Use FOR_EACH_RTX iteration
	instead of demanding it to the caller.  Adjust the recursive call.
	(rtx_referenced_p_1): Inline into...
	(rtx_referenced_p): ... this one.
	(for_each_rtx): Use FOR_EACH_RTX and rtx_iter_skip to implement the
	same semantics as before.
	* value-prof.c (find_mem_reference_1): Inline into...
	(find_mem_reference): ... this one, using FOR_EACH_RTX for iteration.
	(count_uses, add_uses): Take two rtx.
	(count_uses_1, add_uses_1): Use FOR_EACH_RTX for iteration.
	(count_stores): Adjust call to count_uses.
	* varasm.c (const_rtx_hash_1): Inline into...
	(const_rtx_hash): ... this one, using FOR_EACH_RTX for iteration.
	(mark_constant): Accept a struct constant_pool *, and a SYMBOL_REF.
	Call mark_constants_1 to iterate on the definition of a constant.
	(mark_constants_1): New.
	(mark_constants): Use mark_constants_1.
	
Index: alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/alias.c,v
retrieving revision 1.248
diff -c -p -r1.248 alias.c
*** alias.c	4 Dec 2004 00:20:29 -0000	1.248
--- alias.c	19 Jan 2005 09:49:13 -0000
*************** static rtx adjust_offset_for_component_r
*** 115,125 ****
  static int nonoverlapping_memrefs_p (rtx, rtx);
  static int write_dependence_p (rtx, rtx, int);
  
! static int nonlocal_mentioned_p_1 (rtx *, void *);
  static int nonlocal_mentioned_p (rtx);
! static int nonlocal_referenced_p_1 (rtx *, void *);
  static int nonlocal_referenced_p (rtx);
! static int nonlocal_set_p_1 (rtx *, void *);
  static int nonlocal_set_p (rtx);
  static void memory_modified_1 (rtx, rtx, void *);
  static void record_alias_subset (HOST_WIDE_INT, HOST_WIDE_INT);
--- 115,125 ----
  static int nonoverlapping_memrefs_p (rtx, rtx);
  static int write_dependence_p (rtx, rtx, int);
  
! static int nonlocal_mentioned_p_1 (rtx);
  static int nonlocal_mentioned_p (rtx);
! static int nonlocal_referenced_p_1 (rtx);
  static int nonlocal_referenced_p (rtx);
! static int nonlocal_set_p_1 (rtx);
  static int nonlocal_set_p (rtx);
  static void memory_modified_1 (rtx, rtx, void *);
  static void record_alias_subset (HOST_WIDE_INT, HOST_WIDE_INT);
*************** output_dependence (rtx mem, rtx x)
*** 2325,2343 ****
    return write_dependence_p (mem, x, /*writep=*/1);
  }
  
! /* A subroutine of nonlocal_mentioned_p, returns 1 if *LOC mentions
     something which is not local to the function and is not constant.  */
  
  static int
! nonlocal_mentioned_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
  {
-   rtx x = *loc;
    rtx base;
    int regno;
  
-   if (! x)
-     return 0;
- 
    switch (GET_CODE (x))
      {
      case SUBREG:
--- 2325,2339 ----
    return write_dependence_p (mem, x, /*writep=*/1);
  }
  
! /* A subroutine of nonlocal_mentioned_p, returns 1 if X mentions
     something which is not local to the function and is not constant.  */
  
  static int
! nonlocal_mentioned_p_1 (rtx x)
  {
    rtx base;
    int regno;
  
    switch (GET_CODE (x))
      {
      case SUBREG:
*************** nonlocal_mentioned_p_1 (rtx *loc, void *
*** 2429,2434 ****
--- 2425,2433 ----
  static int
  nonlocal_mentioned_p (rtx x)
  {
+   rtx_iter iter;
+   rtx *loc;
+ 
    if (INSN_P (x))
      {
        if (CALL_P (x))
*************** nonlocal_mentioned_p (rtx x)
*** 2443,2462 ****
  	x = PATTERN (x);
      }
  
!   return for_each_rtx (&x, nonlocal_mentioned_p_1, NULL);
  }
  
! /* A subroutine of nonlocal_referenced_p, returns 1 if *LOC references
     something which is not local to the function and is not constant.  */
  
  static int
! nonlocal_referenced_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
  {
-   rtx x = *loc;
- 
-   if (! x)
-     return 0;
- 
    switch (GET_CODE (x))
      {
      case MEM:
--- 2442,2460 ----
  	x = PATTERN (x);
      }
  
!   FOR_EACH_RTX (&x, loc, iter)
!     if (*loc && nonlocal_mentioned_p_1 (*loc))
!       return 1;
! 
!   return 0;
  }
  
! /* A subroutine of nonlocal_referenced_p, returns 1 if X references
     something which is not local to the function and is not constant.  */
  
  static int
! nonlocal_referenced_p_1 (rtx x)
  {
    switch (GET_CODE (x))
      {
      case MEM:
*************** nonlocal_referenced_p_1 (rtx *loc, void 
*** 2523,2528 ****
--- 2521,2529 ----
  static int
  nonlocal_referenced_p (rtx x)
  {
+   rtx_iter iter;
+   rtx *loc;
+ 
    if (INSN_P (x))
      {
        if (CALL_P (x))
*************** nonlocal_referenced_p (rtx x)
*** 2537,2556 ****
  	x = PATTERN (x);
      }
  
!   return for_each_rtx (&x, nonlocal_referenced_p_1, NULL);
  }
  
! /* A subroutine of nonlocal_set_p, returns 1 if *LOC sets
     something which is not local to the function and is not constant.  */
  
  static int
! nonlocal_set_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
  {
-   rtx x = *loc;
- 
-   if (! x)
-     return 0;
- 
    switch (GET_CODE (x))
      {
      case CALL:
--- 2538,2556 ----
  	x = PATTERN (x);
      }
  
!   FOR_EACH_RTX (&x, loc, iter)
!     if (*loc && nonlocal_referenced_p_1 (*loc))
!       return 1;
! 
!   return 0;
  }
  
! /* A subroutine of nonlocal_set_p, returns 1 if X sets
     something which is not local to the function and is not constant.  */
  
  static int
! nonlocal_set_p_1 (rtx x)
  {
    switch (GET_CODE (x))
      {
      case CALL:
*************** nonlocal_set_p_1 (rtx *loc, void *data A
*** 2599,2604 ****
--- 2599,2607 ----
  static int
  nonlocal_set_p (rtx x)
  {
+   rtx_iter iter;
+   rtx *loc;
+ 
    if (INSN_P (x))
      {
        if (CALL_P (x))
*************** nonlocal_set_p (rtx x)
*** 2613,2619 ****
  	x = PATTERN (x);
      }
  
!   return for_each_rtx (&x, nonlocal_set_p_1, NULL);
  }
  
  /* Mark the function if it is pure or constant.  */
--- 2616,2626 ----
  	x = PATTERN (x);
      }
  
!   FOR_EACH_RTX (&x, loc, iter)
!     if (*loc && nonlocal_set_p_1 (*loc))
!       return 1;
! 
!   return 0;
  }
  
  /* Mark the function if it is pure or constant.  */
Index: bt-load.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/bt-load.c,v
retrieving revision 2.30
diff -c -p -r2.30 bt-load.c
*** bt-load.c	6 Dec 2004 16:07:57 -0000	2.30
--- bt-load.c	19 Jan 2005 09:49:13 -0000
*************** static int issue_rate;
*** 109,117 ****
  
  static int basic_block_freq (basic_block);
  static int insn_sets_btr_p (rtx, int, int *);
! static rtx *find_btr_use (rtx);
! static int btr_referenced_p (rtx, rtx *);
! static int find_btr_reference (rtx *, void *);
  static void find_btr_def_group (btr_def_group *, btr_def);
  static btr_def add_btr_def (fibheap_t, basic_block, int, rtx,
  			    unsigned int, int, btr_def_group *);
--- 109,115 ----
  
  static int basic_block_freq (basic_block);
  static int insn_sets_btr_p (rtx, int, int *);
! static rtx *find_btr_use (rtx, rtx *);
  static void find_btr_def_group (btr_def_group *, btr_def);
  static btr_def add_btr_def (fibheap_t, basic_block, int, rtx,
  			    unsigned int, int, btr_def_group *);
*************** basic_block_freq (basic_block bb)
*** 180,221 ****
    return bb->frequency;
  }
  
- static rtx *btr_reference_found;
- 
- /* A subroutine of btr_referenced_p, called through for_each_rtx.
-    PREG is a pointer to an rtx that is to be excluded from the
-    traversal.  If we find a reference to a target register anywhere
-    else, return 1, and put a pointer to it into btr_reference_found.  */
- static int
- find_btr_reference (rtx *px, void *preg)
- {
-   rtx x;
-   int regno, i;
- 
-   if (px == preg)
-     return -1;
-   x = *px;
-   if (!REG_P (x))
-     return 0;
-   regno = REGNO (x);
-   for (i = hard_regno_nregs[regno][GET_MODE (x)] - 1; i >= 0; i--)
-     if (TEST_HARD_REG_BIT (all_btrs, regno+i))
-       {
- 	btr_reference_found = px;
- 	return 1;
-       }
-   return -1;
- }
- 
- /* Return nonzero if X references (sets or reads) any branch target register.
-    If EXCLUDEP is set, disregard any references within the rtx pointed to
-    by it.  If returning nonzero, also set btr_reference_found as above.  */
- static int
- btr_referenced_p (rtx x, rtx *excludep)
- {
-   return for_each_rtx (&x, find_btr_reference, excludep);
- }
- 
  /* Return true if insn is an instruction that sets a target register.
     if CHECK_CONST is true, only return true if the source is constant.
     If such a set is found and REGNO is nonzero, assign the register number
--- 178,183 ----
*************** insn_sets_btr_p (rtx insn, int check_con
*** 237,243 ****
        if (REG_P (dest)
  	  && TEST_HARD_REG_BIT (all_btrs, REGNO (dest)))
  	{
! 	  gcc_assert (!btr_referenced_p (src, NULL));
  	  
  	  if (!check_const || CONSTANT_P (src))
  	    {
--- 199,205 ----
        if (REG_P (dest)
  	  && TEST_HARD_REG_BIT (all_btrs, REGNO (dest)))
  	{
! 	  gcc_assert (!find_btr_use (src, NULL));
  	  
  	  if (!check_const || CONSTANT_P (src))
  	    {
*************** insn_sets_btr_p (rtx insn, int check_con
*** 250,260 ****
    return 0;
  }
  
! /* Find and return a use of a target register within an instruction INSN.  */
  static rtx *
! find_btr_use (rtx insn)
  {
!   return btr_referenced_p (insn, NULL) ? btr_reference_found : NULL;
  }
  
  /* Find the group that the target register definition DEF belongs
--- 212,246 ----
    return 0;
  }
  
! /* Find and return a use of a target register within an instruction INSN.
!    If EXCLUDEP is set, disregard any references within the rtx pointed to
!    by it.  */
  static rtx *
! find_btr_use (rtx insn, rtx *excludep)
  {
!   rtx_iter iter;
!   rtx *loc;
!   FOR_EACH_RTX (&insn, loc, iter)
!     {
!       rtx x;
!       int regno, i;
! 
!       if (loc == excludep)
!         {
! 	  rtx_iter_skip (&iter);
! 	  continue;
! 	}
! 
!       x = *loc;
!       if (!REG_P (x))
!         continue;
!       regno = REGNO (x);
!       for (i = hard_regno_nregs[regno][GET_MODE (x)] - 1; i >= 0; i--)
!         if (TEST_HARD_REG_BIT (all_btrs, regno+i))
!           return loc;
!     }
! 
!   return NULL;
  }
  
  /* Find the group that the target register definition DEF belongs
*************** new_btr_user (basic_block bb, int insn_l
*** 337,343 ****
       to decide whether we can replace all target register
       uses easily.
     */
!   rtx *usep = find_btr_use (PATTERN (insn));
    rtx use;
    btr_user user = NULL;
  
--- 323,329 ----
       to decide whether we can replace all target register
       uses easily.
     */
!   rtx *usep = find_btr_use (PATTERN (insn), NULL);
    rtx use;
    btr_user user = NULL;
  
*************** new_btr_user (basic_block bb, int insn_l
*** 348,354 ****
        /* We want to ensure that USE is the only use of a target
  	 register in INSN, so that we know that to rewrite INSN to use
  	 a different target register, all we have to do is replace USE.  */
!       unambiguous_single_use = !btr_referenced_p (PATTERN (insn), usep);
        if (!unambiguous_single_use)
  	usep = NULL;
      }
--- 334,340 ----
        /* We want to ensure that USE is the only use of a target
  	 register in INSN, so that we know that to rewrite INSN to use
  	 a different target register, all we have to do is replace USE.  */
!       unambiguous_single_use = !find_btr_use (PATTERN (insn), usep);
        if (!unambiguous_single_use)
  	usep = NULL;
      }
*************** compute_defs_uses_and_gen (fibheap_t all
*** 508,514 ****
  		}
  	      else
  		{
! 		  if (btr_referenced_p (PATTERN (insn), NULL))
  		    {
  		      btr_user user = new_btr_user (bb, insn_luid, insn);
  
--- 494,500 ----
  		}
  	      else
  		{
! 		  if (find_btr_use (PATTERN (insn), NULL))
  		    {
  		      btr_user user = new_btr_user (bb, insn_luid, insn);
  
Index: cfgcleanup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgcleanup.c,v
retrieving revision 1.138
diff -c -p -r1.138 cfgcleanup.c
*** cfgcleanup.c	29 Nov 2004 20:46:10 -0000	1.138
--- cfgcleanup.c	19 Jan 2005 09:49:15 -0000
*************** static edge thread_jump (int, edge, basi
*** 86,92 ****
  static bool mark_effect (rtx, bitmap);
  static void notice_new_block (basic_block);
  static void update_forwarder_flag (basic_block);
! static int mentions_nonequal_regs (rtx *, void *);
  static void merge_memattrs (rtx, rtx);
  
  /* Set flags for newly created block.  */
--- 86,92 ----
  static bool mark_effect (rtx, bitmap);
  static void notice_new_block (basic_block);
  static void update_forwarder_flag (basic_block);
! static int mentions_nonequal_regs (rtx, regset);
  static void merge_memattrs (rtx, rtx);
  
  /* Set flags for newly created block.  */
*************** mark_effect (rtx exp, regset nonequal)
*** 245,259 ****
      }
  }
  
! /* Return nonzero if X is a register set in regset DATA.
!    Called via for_each_rtx.  */
  static int
! mentions_nonequal_regs (rtx *x, void *data)
  {
!   regset nonequal = (regset) data;
!   if (REG_P (*x))
      {
        int regno;
  
        regno = REGNO (*x);
        if (REGNO_REG_SET_P (nonequal, regno))
--- 245,261 ----
      }
  }
  
! /* Return nonzero if COND refers to a register set in regset DATA.  */
  static int
! mentions_nonequal_regs (rtx cond, regset nonequal)
  {
!   rtx_iter iter;
!   rtx *x;
!   FOR_EACH_RTX (&cond, x, iter)
      {
        int regno;
+       if (!*x || !REG_P (*x))
+ 	continue;
  
        regno = REGNO (*x);
        if (REGNO_REG_SET_P (nonequal, regno))
*************** mentions_nonequal_regs (rtx *x, void *da
*** 268,273 ****
--- 270,276 ----
      }
    return 0;
  }
+ 
  /* Attempt to prove that the basic block B will have no side effects and
     always continues in the same edge if reached via E.  Return the edge
     if exist, NULL otherwise.  */
*************** thread_jump (int mode, edge e, basic_blo
*** 390,396 ****
  
    /* cond2 must not mention any register that is not equal to the
       former block.  */
!   if (for_each_rtx (&cond2, mentions_nonequal_regs, nonequal))
      goto failed_exit;
  
    /* In case liveness information is available, we need to prove equivalence
--- 393,399 ----
  
    /* cond2 must not mention any register that is not equal to the
       former block.  */
!   if (mentions_nonequal_regs (cond2, nonequal))
      goto failed_exit;
  
    /* In case liveness information is available, we need to prove equivalence
*************** outgoing_edges_match (int mode, basic_bl
*** 1397,1411 ****
  
  	      if (identical)
  		{
- 		  replace_label_data rr;
  		  bool match;
  
  		  /* Temporarily replace references to LABEL1 with LABEL2
  		     in BB1->END so that we could compare the instructions.  */
! 		  rr.r1 = label1;
! 		  rr.r2 = label2;
! 		  rr.update_label_nuses = false;
! 		  for_each_rtx (&BB_END (bb1), replace_label, &rr);
  
  		  match = insns_match_p (mode, BB_END (bb1), BB_END (bb2));
  		  if (dump_file && match)
--- 1400,1410 ----
  
  	      if (identical)
  		{
  		  bool match;
  
  		  /* Temporarily replace references to LABEL1 with LABEL2
  		     in BB1->END so that we could compare the instructions.  */
! 		  replace_label (&BB_END (bb1), label1, label2, false);
  
  		  match = insns_match_p (mode, BB_END (bb1), BB_END (bb2));
  		  if (dump_file && match)
*************** outgoing_edges_match (int mode, basic_bl
*** 1416,1424 ****
  		  /* Set the original label in BB1->END because when deleting
  		     a block whose end is a tablejump, the tablejump referenced
  		     from the instruction is deleted too.  */
! 		  rr.r1 = label2;
! 		  rr.r2 = label1;
! 		  for_each_rtx (&BB_END (bb1), replace_label, &rr);
  
  		  return match;
  		}
--- 1415,1421 ----
  		  /* Set the original label in BB1->END because when deleting
  		     a block whose end is a tablejump, the tablejump referenced
  		     from the instruction is deleted too.  */
! 		  replace_label (&BB_END (bb1), label2, label1, false);
  
  		  return match;
  		}
*************** try_crossjump_to_edge (int mode, edge e1
*** 1576,1595 ****
  	  && tablejump_p (BB_END (src2), &label2, &table2)
  	  && label1 != label2)
  	{
- 	  replace_label_data rr;
  	  rtx insn;
  
  	  /* Replace references to LABEL1 with LABEL2.  */
- 	  rr.r1 = label1;
- 	  rr.r2 = label2;
- 	  rr.update_label_nuses = true;
  	  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
  	    {
  	      /* Do not replace the label in SRC1->END because when deleting
  		 a block whose end is a tablejump, the tablejump referenced
  		 from the instruction is deleted too.  */
  	      if (insn != BB_END (src1))
! 		for_each_rtx (&insn, replace_label, &rr);
  	    }
  	}
      }
--- 1573,1588 ----
  	  && tablejump_p (BB_END (src2), &label2, &table2)
  	  && label1 != label2)
  	{
  	  rtx insn;
  
  	  /* Replace references to LABEL1 with LABEL2.  */
  	  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
  	    {
  	      /* Do not replace the label in SRC1->END because when deleting
  		 a block whose end is a tablejump, the tablejump referenced
  		 from the instruction is deleted too.  */
  	      if (insn != BB_END (src1))
! 		replace_label (&insn, label1, label2, true);
  	    }
  	}
      }
Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.329
diff -c -p -r1.329 cse.c
*** cse.c	5 Jan 2005 23:19:17 -0000	1.329
--- cse.c	19 Jan 2005 09:49:29 -0000
*************** struct qty_table_elem
*** 262,275 ****
  /* The table of all qtys, indexed by qty number.  */
  static struct qty_table_elem *qty_table;
  
- /* Structure used to pass arguments via for_each_rtx to function
-    cse_change_cc_mode.  */
- struct change_cc_mode_args
- {
-   rtx insn;
-   rtx newreg;
- };
- 
  #ifdef HAVE_cc0
  /* For machines that have a CC0, we do not record its value in the hash
     table since its use is guaranteed to be the insn immediately following
--- 262,267 ----
*************** struct cse_basic_block_data
*** 600,606 ****
  
  static bool fixed_base_plus_p (rtx x);
  static int notreg_cost (rtx, enum rtx_code);
- static int approx_reg_cost_1 (rtx *, void *);
  static int approx_reg_cost (rtx);
  static int preferable (int, int, int, int);
  static void new_basic_block (void);
--- 592,597 ----
*************** static void invalidate_skipped_set (rtx,
*** 650,665 ****
  static void invalidate_skipped_block (rtx);
  static rtx cse_basic_block (rtx, rtx, struct branch_path *);
  static void count_reg_usage (rtx, int *, int);
! static int check_for_label_ref (rtx *, void *);
  extern void dump_class (struct table_elt*);
  static struct cse_reg_info * get_cse_reg_info (unsigned int);
! static int check_dependence (rtx *, void *);
  
  static void flush_hash_table (void);
  static bool insn_live_p (rtx, int *);
  static bool set_live_p (rtx, rtx, int *);
  static bool dead_libcall_p (rtx, int *);
! static int cse_change_cc_mode (rtx *, void *);
  static void cse_change_cc_mode_insn (rtx, rtx);
  static void cse_change_cc_mode_insns (rtx, rtx, rtx);
  static enum machine_mode cse_cc_succs (basic_block, rtx, rtx, bool);
--- 641,656 ----
  static void invalidate_skipped_block (rtx);
  static rtx cse_basic_block (rtx, rtx, struct branch_path *);
  static void count_reg_usage (rtx, int *, int);
! static bool check_for_label_ref (rtx);
  extern void dump_class (struct table_elt*);
  static struct cse_reg_info * get_cse_reg_info (unsigned int);
! static bool check_dependence (rtx, rtx, enum machine_mode, rtx);
  
  static void flush_hash_table (void);
  static bool insn_live_p (rtx, int *);
  static bool set_live_p (rtx, rtx, int *);
  static bool dead_libcall_p (rtx, int *);
! static void cse_change_cc_mode (rtx *, rtx, rtx);
  static void cse_change_cc_mode_insn (rtx, rtx);
  static void cse_change_cc_mode_insns (rtx, rtx, rtx);
  static enum machine_mode cse_cc_succs (basic_block, rtx, rtx, bool);
*************** dump_class (struct table_elt *classp)
*** 717,750 ****
      }
  }
  
- /* Subroutine of approx_reg_cost; called through for_each_rtx.  */
- 
- static int
- approx_reg_cost_1 (rtx *xp, void *data)
- {
-   rtx x = *xp;
-   int *cost_p = data;
- 
-   if (x && REG_P (x))
-     {
-       unsigned int regno = REGNO (x);
- 
-       if (! CHEAP_REGNO (regno))
- 	{
- 	  if (regno < FIRST_PSEUDO_REGISTER)
- 	    {
- 	      if (SMALL_REGISTER_CLASSES)
- 		return 1;
- 	      *cost_p += 2;
- 	    }
- 	  else
- 	    *cost_p += 1;
- 	}
-     }
- 
-   return 0;
- }
- 
  /* Return an estimate of the cost of the registers used in an rtx.
     This is mostly the number of different REG expressions in the rtx;
     however for some exceptions like fixed registers we use a cost of
--- 708,713 ----
*************** static int
*** 754,762 ****
  approx_reg_cost (rtx x)
  {
    int cost = 0;
  
!   if (for_each_rtx (&x, approx_reg_cost_1, (void *) &cost))
!     return MAX_COST;
  
    return cost;
  }
--- 717,742 ----
  approx_reg_cost (rtx x)
  {
    int cost = 0;
+   rtx_iter iter;
+   rtx *loc;
  
!   FOR_EACH_RTX (&x, loc, iter)
!     if (*loc && REG_P (*loc))
!       {
!         unsigned int regno = REGNO (*loc);
! 
!         if (! CHEAP_REGNO (regno))
! 	  {
! 	    if (regno < FIRST_PSEUDO_REGISTER)
! 	      {
! 	        if (SMALL_REGISTER_CLASSES)
! 		  return MAX_COST;
! 	        cost += 2;
! 	      }
! 	    else
! 	      cost += 1;
! 	  }
!       }
  
    return cost;
  }
*************** flush_hash_table (void)
*** 1715,1738 ****
  	  remove_from_table (p, i);
        }
  }
- 
  /* Function called for each rtx to check whether true dependence exist.  */
- struct check_dependence_data
- {
-   enum machine_mode mode;
-   rtx exp;
-   rtx addr;
- };
  
! static int
! check_dependence (rtx *x, void *data)
  {
!   struct check_dependence_data *d = (struct check_dependence_data *) data;
!   if (*x && MEM_P (*x))
!     return canon_true_dependence (d->exp, d->mode, d->addr, *x,
! 		    		  cse_rtx_varies_p);
!   else
!     return 0;
  }
  
  /* Remove from the hash table, or mark as invalid, all expressions whose
--- 1695,1713 ----
  	  remove_from_table (p, i);
        }
  }
  /* Function called for each rtx to check whether true dependence exist.  */
  
! static bool
! check_dependence (rtx x, rtx exp, enum machine_mode mode, rtx addr)
  {
!   rtx_iter iter;
!   rtx *loc;
!   FOR_EACH_RTX (&x, loc, iter)
!     if (*loc && MEM_P (*loc)
!         && canon_true_dependence (exp, mode, addr, *loc, cse_rtx_varies_p))
!       return true;
! 
!   return false;
  }
  
  /* Remove from the hash table, or mark as invalid, all expressions whose
*************** invalidate (rtx x, enum machine_mode ful
*** 1862,1879 ****
  	      next = p->next_same_hash;
  	      if (p->in_memory)
  		{
- 		  struct check_dependence_data d;
- 
  		  /* Just canonicalize the expression once;
  		     otherwise each time we call invalidate
  		     true_dependence will canonicalize the
  		     expression again.  */
  		  if (!p->canon_exp)
  		    p->canon_exp = canon_rtx (p->exp);
! 		  d.exp = x;
! 		  d.addr = addr;
! 		  d.mode = full_mode;
! 		  if (for_each_rtx (&p->canon_exp, check_dependence, &d))
  		    remove_from_table (p, i);
  		}
  	    }
--- 1837,1849 ----
  	      next = p->next_same_hash;
  	      if (p->in_memory)
  		{
  		  /* Just canonicalize the expression once;
  		     otherwise each time we call invalidate
  		     true_dependence will canonicalize the
  		     expression again.  */
  		  if (!p->canon_exp)
  		    p->canon_exp = canon_rtx (p->exp);
! 		  if (check_dependence (p->canon_exp, x, full_mode, addr))
  		    remove_from_table (p, i);
  		}
  	    }
*************** cse_basic_block (rtx from, rtx to, struc
*** 6944,6951 ****
  	  /* If we haven't already found an insn where we added a LABEL_REF,
  	     check this one.  */
  	  if (NONJUMP_INSN_P (insn) && ! recorded_label_ref
! 	      && for_each_rtx (&PATTERN (insn), check_for_label_ref,
! 			       (void *) insn))
  	    recorded_label_ref = 1;
  	}
  
--- 6914,6920 ----
  	  /* If we haven't already found an insn where we added a LABEL_REF,
  	     check this one.  */
  	  if (NONJUMP_INSN_P (insn) && ! recorded_label_ref
! 	      && check_for_label_ref (insn))
  	    recorded_label_ref = 1;
  	}
  
*************** cse_basic_block (rtx from, rtx to, struc
*** 7042,7064 ****
    return to ? NEXT_INSN (to) : 0;
  }
  
! /* Called via for_each_rtx to see if an insn is using a LABEL_REF for which
!    there isn't a REG_LABEL note.  Return one if so.  DATA is the insn.  */
  
! static int
! check_for_label_ref (rtx *rtl, void *data)
  {
!   rtx insn = (rtx) data;
  
    /* If this insn uses a LABEL_REF and there isn't a REG_LABEL note for it,
       we must rerun jump since it needs to place the note.  If this is a
       LABEL_REF for a CODE_LABEL that isn't in the insn chain, don't do this
       since no REG_LABEL will be added.  */
!   return (GET_CODE (*rtl) == LABEL_REF
! 	  && ! LABEL_REF_NONLOCAL_P (*rtl)
! 	  && LABEL_P (XEXP (*rtl, 0))
! 	  && INSN_UID (XEXP (*rtl, 0)) != 0
! 	  && ! find_reg_note (insn, REG_LABEL, XEXP (*rtl, 0)));
  }
  
  /* Count the number of times registers are used (not set) in X.
--- 7011,7038 ----
    return to ? NEXT_INSN (to) : 0;
  }
  
! /* Called to see if INSN is using a LABEL_REF for which there isn't a REG_LABEL
!    note.  Return true if so.  */
  
! static bool
! check_for_label_ref (rtx insn)
  {
!   rtx_iter iter;
!   rtx *rtl;
  
    /* If this insn uses a LABEL_REF and there isn't a REG_LABEL note for it,
       we must rerun jump since it needs to place the note.  If this is a
       LABEL_REF for a CODE_LABEL that isn't in the insn chain, don't do this
       since no REG_LABEL will be added.  */
!   FOR_EACH_RTX (&PATTERN (insn), rtl, iter)
!     if (GET_CODE (*rtl) == LABEL_REF
! 	&& ! LABEL_REF_NONLOCAL_P (*rtl)
! 	&& LABEL_P (XEXP (*rtl, 0))
! 	&& INSN_UID (XEXP (*rtl, 0)) != 0
! 	&& ! find_reg_note (insn, REG_LABEL, XEXP (*rtl, 0)))
!       return true;
! 
!   return false;
  }
  
  /* Count the number of times registers are used (not set) in X.
*************** delete_trivially_dead_insns (rtx insns, 
*** 7367,7392 ****
    return ndead;
  }
  
! /* This function is called via for_each_rtx.  The argument, NEWREG, is
!    a condition code register with the desired mode.  If we are looking
!    at the same register in a different mode, replace it with
!    NEWREG.  */
  
! static int
! cse_change_cc_mode (rtx *loc, void *data)
  {
!   struct change_cc_mode_args* args = (struct change_cc_mode_args*)data;
! 
!   if (*loc
!       && REG_P (*loc)
!       && REGNO (*loc) == REGNO (args->newreg)
!       && GET_MODE (*loc) != GET_MODE (args->newreg))
!     {
!       validate_change (args->insn, loc, args->newreg, 1);
!       
!       return -1;
!     }
!   return 0;
  }
  
  /* Change the mode of any reference to the register REGNO (NEWREG) to
--- 7341,7364 ----
    return ndead;
  }
  
! /* The argument, NEWREG, is a condition code register with the desired mode.
!    Wherever INSN refers to the same register in a different mode, replace it
!    with NEWREG.  */
  
! static void
! cse_change_cc_mode (rtx *x, rtx insn, rtx newreg)
  {
!   rtx_iter iter;
!   rtx *loc;
!   unsigned regno = REGNO (newreg);
!   enum machine_mode mode = GET_MODE (newreg);
! 
!   FOR_EACH_RTX (x, loc, iter)
!     if (*loc
!         && REG_P (*loc)
!         && REGNO (*loc) == regno
!         && GET_MODE (*loc) != mode)
!       validate_change (insn, loc, newreg, 1);
  }
  
  /* Change the mode of any reference to the register REGNO (NEWREG) to
*************** cse_change_cc_mode (rtx *loc, void *data
*** 7395,7411 ****
  static void
  cse_change_cc_mode_insn (rtx insn, rtx newreg)
  {
-   struct change_cc_mode_args args;
    int success;
  
    if (!INSN_P (insn))
      return;
  
!   args.insn = insn;
!   args.newreg = newreg;
!   
!   for_each_rtx (&PATTERN (insn), cse_change_cc_mode, &args);
!   for_each_rtx (&REG_NOTES (insn), cse_change_cc_mode, &args);
    
    /* If the following assertion was triggered, there is most probably
       something wrong with the cc_modes_compatible back end function.
--- 7367,7379 ----
  static void
  cse_change_cc_mode_insn (rtx insn, rtx newreg)
  {
    int success;
  
    if (!INSN_P (insn))
      return;
  
!   cse_change_cc_mode (&PATTERN (insn), insn, newreg);
!   cse_change_cc_mode (&REG_NOTES (insn), insn, newreg);
    
    /* If the following assertion was triggered, there is most probably
       something wrong with the cc_modes_compatible back end function.
Index: ddg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ddg.c,v
retrieving revision 1.11
diff -c -p -r1.11 ddg.c
*** ddg.c	22 Nov 2004 12:23:47 -0000	1.11
--- ddg.c	19 Jan 2005 09:49:30 -0000
*************** static void add_edge_to_ddg (ddg_ptr g, 
*** 64,82 ****
  static bool mem_ref_p;
  
  /* Auxiliary function for mem_read_insn_p.  */
- static int
- mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED)
- {
-   if (MEM_P (*x))
-     mem_ref_p = true;
-   return 0;
- }
- 
- /* Auxiliary function for mem_read_insn_p.  */
  static void
! mark_mem_use_1 (rtx *x, void *data)
  {
!   for_each_rtx (x, mark_mem_use, data);
  }
  
  /* Returns nonzero if INSN reads from memory.  */
--- 64,80 ----
  static bool mem_ref_p;
  
  /* Auxiliary function for mem_read_insn_p.  */
  static void
! mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED)
  {
!   rtx_iter iter;
!   rtx *loc;
!   FOR_EACH_RTX (x, loc, iter)
!     if (MEM_P (*loc))
!       {
! 	mem_ref_p = true;
! 	return;
!       }
  }
  
  /* Returns nonzero if INSN reads from memory.  */
*************** static bool
*** 84,90 ****
  mem_read_insn_p (rtx insn)
  {
    mem_ref_p = false;
!   note_uses (&PATTERN (insn), mark_mem_use_1, NULL);
    return mem_ref_p;
  }
  
--- 82,88 ----
  mem_read_insn_p (rtx insn)
  {
    mem_ref_p = false;
!   note_uses (&PATTERN (insn), mark_mem_use, NULL);
    return mem_ref_p;
  }
  
Index: df.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/df.c,v
retrieving revision 1.80
diff -c -p -r1.80 df.c
*** df.c	5 Jan 2005 23:19:17 -0000	1.80
--- df.c	19 Jan 2005 09:49:32 -0000
*************** static int df_refs_update (struct df *, 
*** 270,277 ****
  static void df_analyze_1 (struct df *, bitmap, int, int);
  
  static void df_insns_modify (struct df *, basic_block, rtx, rtx);
- static int df_rtx_mem_replace (rtx *, void *);
- static int df_rtx_reg_replace (rtx *, void *);
  void df_refs_reg_replace (struct df *, bitmap, struct df_link *, rtx, rtx);
  
  static int df_def_dominates_all_uses_p (struct df *, struct ref *def);
--- 270,275 ----
*************** typedef struct replace_args
*** 2686,2745 ****
  } replace_args;
  
  
! /* Replace mem pointed to by PX with its associated pseudo register.
!    DATA is actually a pointer to a structure describing the
!    instruction currently being scanned and the MEM we are currently
!    replacing.  */
! static int
! df_rtx_mem_replace (rtx *px, void *data)
! {
!   replace_args *args = (replace_args *) data;
!   rtx mem = *px;
! 
!   if (mem == NULL_RTX)
!     return 0;
! 
!   switch (GET_CODE (mem))
!     {
!     case MEM:
!       break;
! 
!     case CONST_DOUBLE:
!       /* We're not interested in the MEM associated with a
! 	 CONST_DOUBLE, so there's no need to traverse into one.  */
!       return -1;
! 
!     default:
!       /* This is not a MEM.  */
!       return 0;
!     }
! 
!   if (!rtx_equal_p (args->match, mem))
!     /* This is not the MEM we are currently replacing.  */
!     return 0;
! 
!   /* Actually replace the MEM.  */
!   validate_change (args->insn, px, args->replacement, 1);
!   args->modified++;
! 
!   return 0;
! }
! 
  
  int
  df_insn_mem_replace (struct df *df, basic_block bb, rtx insn, rtx mem, rtx reg)
  {
!   replace_args args;
  
!   args.insn = insn;
!   args.match = mem;
!   args.replacement = reg;
!   args.modified = 0;
  
!   /* Search and replace all matching mems within insn.  */
!   for_each_rtx (&insn, df_rtx_mem_replace, &args);
  
!   if (args.modified)
      df_insn_modify (df, bb, insn);
  
    /* ???? FIXME.  We may have a new def or one or more new uses of REG
--- 2684,2728 ----
  } replace_args;
  
  
! /* Search and replace with REG all matching MEMs within INSN.  */
  
  int
  df_insn_mem_replace (struct df *df, basic_block bb, rtx insn, rtx mem, rtx reg)
  {
!   rtx_iter iter;  
!   rtx *loc;
!   int modified = 0; 
!   FOR_EACH_RTX (&insn, loc, iter)
!     {
!       rtx x = *loc;
  
!       if (x == NULL_RTX)
!         continue;
  
!       switch (GET_CODE (x))
!         {
!         case MEM:
! 	  if (!rtx_equal_p (mem, x))
! 	    /* This is not the MEM we are currently replacing.  */
! 	    break;
! 
! 	  /* Actually replace the MEM.  */
! 	  validate_change (insn, loc, reg, 1);
! 	  modified++;
! 	  break;
! 
!         case CONST_DOUBLE:
!           /* We're not interested in the MEM associated with a
! 	     CONST_DOUBLE, so there's no need to traverse into one.  */
!           rtx_iter_skip (&iter);
! 
!         default:
!           /* This is not a MEM.  */
!           break;
!         }
!     }
  
!   if (modified)
      df_insn_modify (df, bb, insn);
  
    /* ???? FIXME.  We may have a new def or one or more new uses of REG
*************** df_insn_mem_replace (struct df *df, basi
*** 2747,2775 ****
       dataflow information that we currently have.  We should add
       the new uses and defs to INSN and then recreate the chains
       when df_analyze is called.  */
!   return args.modified;
! }
! 
! 
! /* Replace one register with another.  Called through for_each_rtx; PX
!    points to the rtx being scanned.  DATA is actually a pointer to a
!    structure of arguments.  */
! static int
! df_rtx_reg_replace (rtx *px, void *data)
! {
!   rtx x = *px;
!   replace_args *args = (replace_args *) data;
! 
!   if (x == NULL_RTX)
!     return 0;
! 
!   if (x == args->match)
!     {
!       validate_change (args->insn, px, args->replacement, 1);
!       args->modified++;
!     }
! 
!   return 0;
  }
  
  
--- 2730,2736 ----
       dataflow information that we currently have.  We should add
       the new uses and defs to INSN and then recreate the chains
       when df_analyze is called.  */
!   return modified;
  }
  
  
*************** void
*** 2780,2794 ****
  df_refs_reg_replace (struct df *df, bitmap blocks, struct df_link *chain, rtx oldreg, rtx newreg)
  {
    struct df_link *link;
!   replace_args args;
  
    if (! blocks)
      blocks = df->all_blocks;
  
-   args.match = oldreg;
-   args.replacement = newreg;
-   args.modified = 0;
- 
    for (link = chain; link; link = link->next)
      {
        struct ref *ref = link->ref;
--- 2741,2752 ----
  df_refs_reg_replace (struct df *df, bitmap blocks, struct df_link *chain, rtx oldreg, rtx newreg)
  {
    struct df_link *link;
!   rtx_iter iter;
!   rtx *loc;
  
    if (! blocks)
      blocks = df->all_blocks;
  
    for (link = chain; link; link = link->next)
      {
        struct ref *ref = link->ref;
*************** df_refs_reg_replace (struct df *df, bitm
*** 2806,2813 ****
  	   != DF_REF_INSN (link->next->ref))
  	  && REG_NOTES (insn))
  	{
! 	  args.insn = insn;
! 	  for_each_rtx (&REG_NOTES (insn), df_rtx_reg_replace, &args);
  	}
      }
  }
--- 2764,2772 ----
  	   != DF_REF_INSN (link->next->ref))
  	  && REG_NOTES (insn))
  	{
! 	  FOR_EACH_RTX (&REG_NOTES (insn), loc, iter);
! 	    if (*loc == oldreg)
! 	      validate_change (insn, loc, newreg, 1);
  	}
      }
  }
Index: flow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flow.c,v
retrieving revision 1.612
diff -c -p -r1.612 flow.c
*** flow.c	5 Jan 2005 23:19:18 -0000	1.612
--- flow.c	19 Jan 2005 09:49:35 -0000
*************** static int *reg_deaths;
*** 288,295 ****
  #define MAX_MEM_SET_LIST_LEN	100
  
  /* Forward declarations */
! static int verify_wide_reg_1 (rtx *, void *);
! static void verify_wide_reg (int, basic_block);
  static void verify_local_live_at_start (regset, basic_block);
  static void notice_stack_pointer_modification_1 (rtx, rtx, void *);
  static void notice_stack_pointer_modification (void);
--- 288,294 ----
  #define MAX_MEM_SET_LIST_LEN	100
  
  /* Forward declarations */
! static void verify_wide_reg (unsigned, basic_block);
  static void verify_local_live_at_start (regset, basic_block);
  static void notice_stack_pointer_modification_1 (rtx, rtx, void *);
  static void notice_stack_pointer_modification (void);
*************** static int libcall_dead_p (struct propag
*** 303,309 ****
  static void mark_set_regs (struct propagate_block_info *, rtx, rtx);
  static void mark_set_1 (struct propagate_block_info *, enum rtx_code, rtx,
  			rtx, rtx, int);
! static int find_regno_partial (rtx *, void *);
  
  #ifdef HAVE_conditional_execution
  static int mark_regno_cond_dead (struct propagate_block_info *, int, rtx);
--- 302,308 ----
  static void mark_set_regs (struct propagate_block_info *, rtx, rtx);
  static void mark_set_1 (struct propagate_block_info *, enum rtx_code, rtx,
  			rtx, rtx, int);
! static rtx find_regno_partial (rtx, unsigned);
  
  #ifdef HAVE_conditional_execution
  static int mark_regno_cond_dead (struct propagate_block_info *, int, rtx);
*************** static void mark_used_reg (struct propag
*** 326,332 ****
  static void mark_used_regs (struct propagate_block_info *, rtx, rtx, rtx);
  void debug_flow_info (void);
  static void add_to_mem_set_list (struct propagate_block_info *, rtx);
! static int invalidate_mems_from_autoinc (rtx *, void *);
  static void invalidate_mems_from_set (struct propagate_block_info *, rtx);
  static void clear_log_links (sbitmap);
  static int count_or_remove_death_notes_bb (basic_block, int);
--- 325,331 ----
  static void mark_used_regs (struct propagate_block_info *, rtx, rtx, rtx);
  void debug_flow_info (void);
  static void add_to_mem_set_list (struct propagate_block_info *, rtx);
! static void invalidate_mems_from_autoinc (struct propagate_block_info *, rtx);
  static void invalidate_mems_from_set (struct propagate_block_info *, rtx);
  static void clear_log_links (sbitmap);
  static int count_or_remove_death_notes_bb (basic_block, int);
*************** life_analysis (FILE *file, int flags)
*** 446,492 ****
    delete_dead_jumptables ();
  }
  
- /* A subroutine of verify_wide_reg, called through for_each_rtx.
-    Search for REGNO.  If found, return 2 if it is not wider than
-    word_mode.  */
- 
- static int
- verify_wide_reg_1 (rtx *px, void *pregno)
- {
-   rtx x = *px;
-   unsigned int regno = *(int *) pregno;
- 
-   if (REG_P (x) && REGNO (x) == regno)
-     {
-       if (GET_MODE_BITSIZE (GET_MODE (x)) <= BITS_PER_WORD)
- 	return 2;
-       return 1;
-     }
-   return 0;
- }
- 
  /* A subroutine of verify_local_live_at_start.  Search through insns
!    of BB looking for register REGNO.  */
  
  static void
! verify_wide_reg (int regno, basic_block bb)
  {
!   rtx head = BB_HEAD (bb), end = BB_END (bb);
! 
!   while (1)
      {
!       if (INSN_P (head))
  	{
! 	  int r = for_each_rtx (&PATTERN (head), verify_wide_reg_1, &regno);
! 	  if (r == 1)
  	    return;
- 	  if (r == 2)
- 	    break;
  	}
-       if (head == end)
- 	break;
-       head = NEXT_INSN (head);
      }
    if (dump_file)
      {
        fprintf (dump_file, "Register %d died unexpectedly.\n", regno);
--- 445,478 ----
    delete_dead_jumptables ();
  }
  
  /* A subroutine of verify_local_live_at_start.  Search through insns
!    of BB looking for register REGNO.  Fail if it is referenced in
!    a mode smaller than the word_mode, or if it cannot be found.  */
  
  static void
! verify_wide_reg (unsigned regno, basic_block bb)
  {
!   rtx insn;
!   FOR_BB_INSNS (bb, insn)
      {
!       rtx_iter iter;
!       rtx *px;
!       if (!INSN_P (insn))
! 	continue;
!       FOR_EACH_RTX (&PATTERN (insn), px, iter)
  	{
! 	  rtx x = *px;
! 	  if (!REG_P (x) || REGNO (x) != regno)
! 	    continue;
! 
! 	  if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
! 	    goto fail;
! 	  else
  	    return;
  	}
      }
+ 
+  fail:
    if (dump_file)
      {
        fprintf (dump_file, "Register %d died unexpectedly.\n", regno);
*************** calculate_global_regs_live (sbitmap bloc
*** 1315,1370 ****
  }
  
  
! /* This structure is used to pass parameters to and from the
!    the function find_regno_partial(). It is used to pass in the
!    register number we are looking, as well as to return any rtx
!    we find.  */
! 
! typedef struct {
!   unsigned regno_to_find;
!   rtx retval;
! } find_regno_partial_param;
! 
! 
! /* Find the rtx for the reg numbers specified in 'data' if it is
!    part of an expression which only uses part of the register.  Return
!    it in the structure passed in.  */
! static int
! find_regno_partial (rtx *ptr, void *data)
  {
!   find_regno_partial_param *param = (find_regno_partial_param *)data;
!   unsigned reg = param->regno_to_find;
!   param->retval = NULL_RTX;
  
!   if (*ptr == NULL_RTX)
!     return 0;
! 
!   switch (GET_CODE (*ptr))
      {
!     case ZERO_EXTRACT:
!     case SIGN_EXTRACT:
!     case STRICT_LOW_PART:
!       if (REG_P (XEXP (*ptr, 0)) && REGNO (XEXP (*ptr, 0)) == reg)
! 	{
! 	  param->retval = XEXP (*ptr, 0);
! 	  return 1;
! 	}
!       break;
  
!     case SUBREG:
!       if (REG_P (SUBREG_REG (*ptr))
! 	  && REGNO (SUBREG_REG (*ptr)) == reg)
! 	{
! 	  param->retval = SUBREG_REG (*ptr);
! 	  return 1;
! 	}
!       break;
  
!     default:
!       break;
      }
  
!   return 0;
  }
  
  /* Process all immediate successors of the entry block looking for pseudo
--- 1301,1340 ----
  }
  
  
! /* Find the rtx for the reg number REG if it is part of an expression which
!    only uses part of the register.  Return it in the structure passed in.  */
! static rtx
! find_regno_partial (rtx exp, unsigned reg)
  {
!   rtx_iter iter;
!   rtx *ptr;
  
!   FOR_EACH_RTX (&exp, ptr, iter)
      {
!       if (*ptr == NULL_RTX)
!         continue;
  
!       switch (GET_CODE (*ptr))
!         {
!         case ZERO_EXTRACT:
!         case SIGN_EXTRACT:
!         case STRICT_LOW_PART:
!           if (REG_P (XEXP (*ptr, 0)) && REGNO (XEXP (*ptr, 0)) == reg)
! 	    return XEXP (*ptr, 0);
!           break;
  
!         case SUBREG:
!           if (REG_P (SUBREG_REG (*ptr))
! 	      && REGNO (SUBREG_REG (*ptr)) == reg)
! 	    return SUBREG_REG (*ptr);
!           break;
! 
!         default:
!           break;
!         }
      }
  
!   return NULL_RTX;
  }
  
  /* Process all immediate successors of the entry block looking for pseudo
*************** initialize_uninitialized_subregs (void)
*** 1380,1386 ****
    rtx insn;
    edge e;
    unsigned reg, did_something = 0;
-   find_regno_partial_param param;
    edge_iterator ei;
  
    FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
--- 1350,1355 ----
*************** initialize_uninitialized_subregs (void)
*** 1404,1416 ****
  	  if (i != NULL_RTX)
  	    {
  	      /* Found the insn, now get the REG rtx, if we can.  */
! 	      param.regno_to_find = reg;
! 	      for_each_rtx (&i, find_regno_partial, &param);
! 	      if (param.retval != NULL_RTX)
  		{
  		  start_sequence ();
! 		  emit_move_insn (param.retval,
! 				  CONST0_RTX (GET_MODE (param.retval)));
  		  insn = get_insns ();
  		  end_sequence ();
  		  insert_insn_on_edge (insn, e);
--- 1373,1383 ----
  	  if (i != NULL_RTX)
  	    {
  	      /* Found the insn, now get the REG rtx, if we can.  */
! 	      rtx use = find_regno_partial (i, reg);
! 	      if (use != NULL_RTX)
  		{
  		  start_sequence ();
! 		  emit_move_insn (use, CONST0_RTX (GET_MODE (use)));
  		  insn = get_insns ();
  		  end_sequence ();
  		  insert_insn_on_edge (insn, e);
*************** add_to_mem_set_list (struct propagate_bl
*** 2394,2412 ****
     Find any entries on the mem_set_list that need to be invalidated due
     to an address change.  */
  
! static int
! invalidate_mems_from_autoinc (rtx *px, void *data)
  {
!   rtx x = *px;
!   struct propagate_block_info *pbi = data;
! 
!   if (GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
!     {
!       invalidate_mems_from_set (pbi, XEXP (x, 0));
!       return -1;
      }
- 
-   return 0;
  }
  
  /* EXP is a REG.  Remove any dependent entries from pbi->mem_set_list.  */
--- 2361,2379 ----
     Find any entries on the mem_set_list that need to be invalidated due
     to an address change.  */
  
! static void
! invalidate_mems_from_autoinc (struct propagate_block_info *pbi, rtx insn)
  {
!   rtx_iter iter;
!   rtx *px;
!   FOR_EACH_RTX (&PATTERN (insn), px, iter)
!     {
!       if (GET_RTX_CLASS (GET_CODE (*px)) == RTX_AUTOINC)
!         {
!           invalidate_mems_from_set (pbi, XEXP (*px, 0));
!           rtx_iter_skip (&iter);
!         }
      }
  }
  
  /* EXP is a REG.  Remove any dependent entries from pbi->mem_set_list.  */
*************** mark_set_1 (struct propagate_block_info 
*** 2638,2644 ****
  	 address modes) then we may need to kill some entries on the
  	 memory set list.  */
        if (insn && MEM_P (reg))
! 	for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi);
  
        if (MEM_P (reg) && ! side_effects_p (reg)
  	  /* ??? With more effort we could track conditional memory life.  */
--- 2605,2611 ----
  	 address modes) then we may need to kill some entries on the
  	 memory set list.  */
        if (insn && MEM_P (reg))
! 	invalidate_mems_from_autoinc (pbi, insn);
  
        if (MEM_P (reg) && ! side_effects_p (reg)
  	  /* ??? With more effort we could track conditional memory life.  */
*************** mark_used_regs (struct propagate_block_i
*** 3793,3799 ****
  	     address modes.  Then we may need to kill some entries on the
  	     memory set list.  */
  	  if (insn)
! 	    for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi);
  	}
  
  #ifdef AUTO_INC_DEC
--- 3760,3766 ----
  	     address modes.  Then we may need to kill some entries on the
  	     memory set list.  */
  	  if (insn)
! 	    invalidate_mems_from_autoinc (pbi, insn);
  	}
  
  #ifdef AUTO_INC_DEC
Index: global.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/global.c,v
retrieving revision 1.121
diff -c -p -r1.121 global.c
*** global.c	30 Dec 2004 09:09:06 -0000	1.121
--- global.c	19 Jan 2005 09:49:37 -0000
*************** static void reg_dies (int, enum machine_
*** 309,316 ****
  static void allocate_bb_info (void);
  static void free_bb_info (void);
  static bool check_earlyclobber (rtx);
! static void mark_reg_use_for_earlyclobber_1 (rtx *, void *);
! static int mark_reg_use_for_earlyclobber (rtx *, void *);
  static void calculate_local_reg_bb_info (void);
  static void set_up_bb_rts_numbers (void);
  static int rpost_cmp (const void *, const void *);
--- 309,315 ----
  static void allocate_bb_info (void);
  static void free_bb_info (void);
  static bool check_earlyclobber (rtx);
! static void mark_reg_use_for_earlyclobber (rtx *, void *);
  static void calculate_local_reg_bb_info (void);
  static void set_up_bb_rts_numbers (void);
  static int rpost_cmp (const void *, const void *);
*************** check_earlyclobber (rtx insn)
*** 2179,2203 ****
    return found;
  }
  
! /* The function checks that pseudo-register *X has a class
!    intersecting with the class of pseudo-register could be early
!    clobbered in the same insn.
     This function is a no-op if earlyclobber_regclass is empty.  */
  
! static int
! mark_reg_use_for_earlyclobber (rtx *x, void *data ATTRIBUTE_UNUSED)
  {
!   enum reg_class pref_class, alt_class;
!   int i, regno;
    basic_block bb = data;
    struct bb_info *bb_info = BB_INFO (bb);
  
!   if (GET_CODE (*x) == REG && REGNO (*x) >= FIRST_PSEUDO_REGISTER)
      {
!       regno = REGNO (*x);
!       if (bitmap_bit_p (bb_info->killed, regno)
  	  || bitmap_bit_p (bb_info->avloc, regno))
! 	return 0;
        pref_class = reg_preferred_class (regno);
        alt_class = reg_alternate_class (regno);
        for (i = VARRAY_ACTIVE_SIZE (earlyclobber_regclass) - 1; i >= 0; i--)
--- 2178,2210 ----
    return found;
  }
  
! /* The function processes all pseudo-registers in *X and checks that
!    they have a class intersecting with the class of pseudo-register
!    possibly early-clobbered in the same insn.
     This function is a no-op if earlyclobber_regclass is empty.  */
  
! static void
! mark_reg_use_for_earlyclobber (rtx *insn, void *data)
  {
!   rtx_iter iter;  
!   rtx *loc;
    basic_block bb = data;
    struct bb_info *bb_info = BB_INFO (bb);
  
!   FOR_EACH_RTX (insn, loc, iter)
      {
!       rtx x = *loc;
!       enum reg_class pref_class, alt_class;
!       int i, regno;
! 
!       if (!REG_P (x))
!         continue;
! 
!       regno = REGNO (x);
!       if (REGNO (x) < FIRST_PSEUDO_REGISTER
! 	  || bitmap_bit_p (bb_info->killed, regno)
  	  || bitmap_bit_p (bb_info->avloc, regno))
! 	continue;
        pref_class = reg_preferred_class (regno);
        alt_class = reg_alternate_class (regno);
        for (i = VARRAY_ACTIVE_SIZE (earlyclobber_regclass) - 1; i >= 0; i--)
*************** mark_reg_use_for_earlyclobber (rtx *x, v
*** 2212,2227 ****
  	    break;
  	  }
      }
-   return 0;
- }
- 
- /* The function processes all pseudo-registers in *X with the aid of
-    previous function.  */
- 
- static void
- mark_reg_use_for_earlyclobber_1 (rtx *x, void *data)
- {
-   for_each_rtx (x, mark_reg_use_for_earlyclobber, data);
  }
  
  /* The function calculates local info for each basic block.  */
--- 2219,2224 ----
*************** calculate_local_reg_bb_info (void)
*** 2242,2248 ****
  	  {
  	    note_stores (PATTERN (insn), mark_reg_change, bb);
  	    if (check_earlyclobber (insn))
! 	      note_uses (&PATTERN (insn), mark_reg_use_for_earlyclobber_1, bb);
  	  }
      }
  }
--- 2239,2245 ----
  	  {
  	    note_stores (PATTERN (insn), mark_reg_change, bb);
  	    if (check_earlyclobber (insn))
! 	      note_uses (&PATTERN (insn), mark_reg_use_for_earlyclobber, bb);
  	  }
      }
  }
Index: ifcvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v
retrieving revision 1.177
diff -c -p -r1.177 ifcvt.c
*** ifcvt.c	8 Jan 2005 14:47:56 -0000	1.177
--- ifcvt.c	19 Jan 2005 09:49:38 -0000
*************** static int block_jumps_and_fallthru_p (b
*** 104,110 ****
  static int find_if_block (ce_if_block_t *);
  static int find_if_case_1 (basic_block, edge, edge);
  static int find_if_case_2 (basic_block, edge, edge);
! static int find_memory (rtx *, void *);
  static int dead_or_predicable (basic_block, basic_block, basic_block,
  			       basic_block, int);
  static void noce_emit_move_insn (rtx, rtx);
--- 104,110 ----
  static int find_if_block (ce_if_block_t *);
  static int find_if_case_1 (basic_block, edge, edge);
  static int find_if_case_2 (basic_block, edge, edge);
! static int refers_to_mem_p (rtx);
  static int dead_or_predicable (basic_block, basic_block, basic_block,
  			       basic_block, int);
  static void noce_emit_move_insn (rtx, rtx);
*************** find_if_case_2 (basic_block test_bb, edg
*** 3055,3067 ****
    return TRUE;
  }
  
! /* A subroutine of dead_or_predicable called through for_each_rtx.
!    Return 1 if a memory is found.  */
  
  static int
! find_memory (rtx *px, void *data ATTRIBUTE_UNUSED)
  {
!   return MEM_P (*px);
  }
  
  /* Used by the code above to perform the actual rtl transformations.
--- 3055,3073 ----
    return TRUE;
  }
  
! /* A subroutine of dead_or_predicable.  Return 1 if a memory is found
!    within PAT.  */
  
  static int
! refers_to_mem_p (rtx pat)
  {
!   rtx_iter iter;
!   rtx *loc;
!   FOR_EACH_RTX (&pat, loc, iter)
!     if (MEM_P (*loc))
!       return 1;
! 
!   return 0;
  }
  
  /* Used by the code above to perform the actual rtl transformations.
*************** dead_or_predicable (basic_block test_bb,
*** 3164,3178 ****
  	    return FALSE;
  	  if (INSN_P (insn))
  	    {
! 	      if (may_trap_p (PATTERN (insn)))
! 		return FALSE;
  
! 	      /* ??? Even non-trapping memories such as stack frame
! 		 references must be avoided.  For stores, we collect
! 		 no lifetime info; for reads, we'd have to assert
! 		 true_dependence false against every store in the
! 		 TEST range.  */
! 	      if (for_each_rtx (&PATTERN (insn), find_memory, NULL))
  		return FALSE;
  	    }
  	  if (insn == end)
--- 3170,3183 ----
  	    return FALSE;
  	  if (INSN_P (insn))
  	    {
! 	      if (may_trap_p (PATTERN (insn))
  
! 	          /* ??? Even non-trapping memories such as stack frame
! 		     references must be avoided.  For stores, we collect
! 		     no lifetime info; for reads, we'd have to assert
! 		     true_dependence false against every store in the
! 		     TEST range.  */
! 		  || refers_to_mem_p (PATTERN (insn)))
  		return FALSE;
  	    }
  	  if (insn == end)
Index: jump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/jump.c,v
retrieving revision 1.253
diff -c -p -r1.253 jump.c
*** jump.c	24 Nov 2004 11:32:23 -0000	1.253
--- jump.c	19 Jan 2005 09:49:39 -0000
*************** static void redirect_exp_1 (rtx *, rtx, 
*** 70,76 ****
  static int redirect_exp (rtx, rtx, rtx);
  static void invert_exp_1 (rtx);
  static int invert_exp (rtx);
- static int returnjump_p_1 (rtx *, void *);
  static void delete_prior_computation (rtx, rtx);
  
  /* Alternate entry into the jump optimizer.  This entry point only rebuilds
--- 70,75 ----
*************** condjump_label (rtx insn)
*** 891,911 ****
  
  /* Return true if INSN is a (possibly conditional) return insn.  */
  
- static int
- returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
- {
-   rtx x = *loc;
- 
-   return x && (GET_CODE (x) == RETURN
- 	       || (GET_CODE (x) == SET && SET_IS_RETURN_P (x)));
- }
- 
  int
  returnjump_p (rtx insn)
  {
    if (!JUMP_P (insn))
      return 0;
!   return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
  }
  
  /* Return true if INSN is a jump that only transfers control and
--- 890,912 ----
  
  /* Return true if INSN is a (possibly conditional) return insn.  */
  
  int
  returnjump_p (rtx insn)
  {
+   rtx_iter iter;  
+   rtx *loc;
    if (!JUMP_P (insn))
      return 0;
! 
!   FOR_EACH_RTX (&PATTERN (insn), loc, iter)
!     {
!       rtx x = *loc;
!       if (x && (GET_CODE (x) == RETURN
! 	        || (GET_CODE (x) == SET && SET_IS_RETURN_P (x))))
! 	return true;
!     }
! 
!   return false;
  }
  
  /* Return true if INSN is a jump that only transfers control and
Index: loop-iv.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-iv.c,v
retrieving revision 2.26
diff -c -p -r2.26 loop-iv.c
*** loop-iv.c	28 Dec 2004 10:33:39 -0000	2.26
--- loop-iv.c	19 Jan 2005 09:49:40 -0000
*************** determine_max_iter (struct niter_desc *d
*** 1345,1361 ****
    return nmax / inc;
  }
  
- /* Checks whether register *REG is in set ALT.  Callback for for_each_rtx.  */
- 
- static int
- altered_reg_used (rtx *reg, void *alt)
- {
-   if (!REG_P (*reg))
-     return 0;
- 
-   return REGNO_REG_SET_P (alt, REGNO (*reg));
- }
- 
  /* Marks registers altered by EXPR in set ALT.  */
  
  static void
--- 1345,1350 ----
*************** simple_rhs_p (rtx rhs)
*** 1405,1423 ****
  static void
  simplify_using_assignment (rtx insn, rtx *expr, regset altered)
  {
    rtx set = single_set (insn);
    rtx lhs = NULL_RTX, rhs;
!   bool ret = false;
  
    if (set)
      {
        lhs = SET_DEST (set);
!       if (!REG_P (lhs)
! 	  || altered_reg_used (&lhs, altered))
! 	ret = true;
      }
    else
!     ret = true;
  
    note_stores (PATTERN (insn), mark_altered, altered);
    if (CALL_P (insn))
--- 1394,1414 ----
  static void
  simplify_using_assignment (rtx insn, rtx *expr, regset altered)
  {
+   rtx_iter iter;
+   rtx *loc;
    rtx set = single_set (insn);
    rtx lhs = NULL_RTX, rhs;
!   bool can_simplify;
  
+   /* We only simplify INSNs that set a REG, and then, only one that has not
+      been altered so far.  */
    if (set)
      {
        lhs = SET_DEST (set);
!       can_simplify = REG_P (lhs) && !REGNO_REG_SET_P (altered, REGNO (lhs));
      }
    else
!     can_simplify = false;
  
    note_stores (PATTERN (insn), mark_altered, altered);
    if (CALL_P (insn))
*************** simplify_using_assignment (rtx insn, rtx
*** 1430,1436 ****
  	  SET_REGNO_REG_SET (altered, i);
      }
  
!   if (ret)
      return;
  
    rhs = find_reg_equal_equiv_note (insn);
--- 1421,1427 ----
  	  SET_REGNO_REG_SET (altered, i);
      }
  
!   if (!can_simplify)
      return;
  
    rhs = find_reg_equal_equiv_note (insn);
*************** simplify_using_assignment (rtx insn, rtx
*** 1442,1449 ****
    if (!simple_rhs_p (rhs))
      return;
  
!   if (for_each_rtx (&rhs, altered_reg_used, altered))
!     return;
  
    *expr = simplify_replace_rtx (*expr, lhs, rhs);
  }
--- 1433,1442 ----
    if (!simple_rhs_p (rhs))
      return;
  
!   /* Check that nothing has been altered so far.  */
!   FOR_EACH_RTX (&rhs, loc, iter)
!     if (REG_P (*loc) && REGNO_REG_SET_P (altered, REGNO (*loc)))
!       return;
  
    *expr = simplify_replace_rtx (*expr, lhs, rhs);
  }
*************** void
*** 1607,1621 ****
  simplify_using_condition (rtx cond, rtx *expr, regset altered)
  {
    rtx rev, reve, exp = *expr;
  
    if (!COMPARISON_P (exp))
      return;
  
    /* If some register gets altered later, we do not really speak about its
       value at the time of comparison.  */
!   if (altered
!       && for_each_rtx (&cond, altered_reg_used, altered))
!     return;
  
    rev = reversed_condition (cond);
    reve = reversed_condition (exp);
--- 1600,1617 ----
  simplify_using_condition (rtx cond, rtx *expr, regset altered)
  {
    rtx rev, reve, exp = *expr;
+   rtx_iter iter;
+   rtx *loc;
  
    if (!COMPARISON_P (exp))
      return;
  
    /* If some register gets altered later, we do not really speak about its
       value at the time of comparison.  */
!   if (altered)
!     FOR_EACH_RTX (&cond, loc, iter)
!       if (REG_P (*loc) && REGNO_REG_SET_P (altered, REGNO (*loc)))
!         return;
  
    rev = reversed_condition (cond);
    reve = reversed_condition (exp);
Index: regmove.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regmove.c,v
retrieving revision 1.166
diff -c -p -r1.166 regmove.c
*** regmove.c	10 Dec 2004 21:11:02 -0000	1.166
--- regmove.c	19 Jan 2005 09:49:42 -0000
*************** struct csa_memlist
*** 2101,2112 ****
  static int stack_memref_p (rtx);
  static rtx single_set_for_csa (rtx);
  static void free_csa_memlist (struct csa_memlist *);
! static struct csa_memlist *record_one_stack_memref (rtx, rtx *,
! 						    struct csa_memlist *);
  static int try_apply_stack_adjustment (rtx, struct csa_memlist *,
  				       HOST_WIDE_INT, HOST_WIDE_INT);
  static void combine_stack_adjustments_for_block (basic_block);
! static int record_stack_memrefs (rtx *, void *);
  
  
  /* Main entry point for stack adjustment combination.  */
--- 2101,2111 ----
  static int stack_memref_p (rtx);
  static rtx single_set_for_csa (rtx);
  static void free_csa_memlist (struct csa_memlist *);
! static void record_one_stack_memref (rtx, rtx *, struct csa_memlist **);
  static int try_apply_stack_adjustment (rtx, struct csa_memlist *,
  				       HOST_WIDE_INT, HOST_WIDE_INT);
  static void combine_stack_adjustments_for_block (basic_block);
! static int record_stack_memrefs (rtx, struct csa_memlist **);
  
  
  /* Main entry point for stack adjustment combination.  */
*************** free_csa_memlist (struct csa_memlist *me
*** 2187,2199 ****
      }
  }
  
! /* Create a new csa_memlist node from the given memory reference.
!    It is already known that the memory is stack_memref_p.  */
  
! static struct csa_memlist *
! record_one_stack_memref (rtx insn, rtx *mem, struct csa_memlist *next_memlist)
  {
    struct csa_memlist *ml;
  
    ml = xmalloc (sizeof (*ml));
  
--- 2186,2201 ----
      }
  }
  
! /* Create a new csa_memlist node from the given memory reference.  */
  
! static void
! record_one_stack_memref (rtx insn, rtx *mem, struct csa_memlist **p_memlist)
  {
    struct csa_memlist *ml;
+   /* We are not able to handle correctly all possible memrefs
+      containing stack pointer, so this check is necessary.  */
+   if (!stack_memref_p (*mem))
+     return;
  
    ml = xmalloc (sizeof (*ml));
  
*************** record_one_stack_memref (rtx insn, rtx *
*** 2204,2212 ****
  
    ml->insn = insn;
    ml->mem = mem;
!   ml->next = next_memlist;
  
!   return ml;
  }
  
  /* Attempt to apply ADJUST to the stack adjusting insn INSN, as well
--- 2206,2214 ----
  
    ml->insn = insn;
    ml->mem = mem;
!   ml->next = *p_memlist;
  
!   *p_memlist = ml;
  }
  
  /* Attempt to apply ADJUST to the stack adjusting insn INSN, as well
*************** try_apply_stack_adjustment (rtx insn, st
*** 2241,2290 ****
      return 0;
  }
  
! /* Called via for_each_rtx and used to record all stack memory references in
!    the insn and discard all other stack pointer references.  */
! struct record_stack_memrefs_data
! {
!   rtx insn;
!   struct csa_memlist *memlist;
! };
! 
  static int
! record_stack_memrefs (rtx *xp, void *data)
  {
!   rtx x = *xp;
!   struct record_stack_memrefs_data *d =
!     (struct record_stack_memrefs_data *) data;
!   if (!x)
!     return 0;
!   switch (GET_CODE (x))
      {
!     case MEM:
!       if (!reg_mentioned_p (stack_pointer_rtx, x))
! 	return -1;
!       /* We are not able to handle correctly all possible memrefs containing
!          stack pointer, so this check is necessary.  */
!       if (stack_memref_p (x))
! 	{
! 	  d->memlist = record_one_stack_memref (d->insn, xp, d->memlist);
! 	  return -1;
! 	}
!       return 1;
!     case REG:
!       /* ??? We want be able to handle non-memory stack pointer
! 	 references later.  For now just discard all insns referring to
! 	 stack pointer outside mem expressions.  We would probably
! 	 want to teach validate_replace to simplify expressions first.
! 
! 	 We can't just compare with STACK_POINTER_RTX because the
! 	 reference to the stack pointer might be in some other mode.
! 	 In particular, an explicit clobber in an asm statement will
! 	 result in a QImode clobber.  */
!       if (REGNO (x) == STACK_POINTER_REGNUM)
! 	return 1;
!       break;
!     default:
!       break;
      }
    return 0;
  }
--- 2243,2287 ----
      return 0;
  }
  
! /* Record all stack memory references in the insn and discard all other
!    stack pointer references.  */
  static int
! record_stack_memrefs (rtx insn, struct csa_memlist **p_memlist)
  {
!   rtx_iter iter;
!   rtx *loc;
!   FOR_EACH_RTX (&PATTERN (insn), loc, iter)
      {
!       rtx x = *loc;
!       if (x == NULL_RTX)
!         continue;
! 
!       switch (GET_CODE (x))
!         {
!         case MEM:
!           if (reg_mentioned_p (stack_pointer_rtx, x))
! 	    {
! 	      record_one_stack_memref (insn, loc, p_memlist);
! 	      rtx_iter_skip (&iter);
! 	    }
!           break;
! 
!         case REG:
!           /* ??? We want be able to handle non-memory stack pointer
! 	     references later.  For now just discard all insns referring to
! 	     stack pointer outside mem expressions.  We would probably
! 	     want to teach validate_replace to simplify expressions first.
! 
! 	     We can't just compare with STACK_POINTER_RTX because the
! 	     reference to the stack pointer might be in some other mode.
! 	     In particular, an explicit clobber in an asm statement will
! 	     result in a QImode clobber.  */
!           if (REGNO (x) == STACK_POINTER_REGNUM)
! 	    return 1;
!           break;
!         default:
!           break;
!         }
      }
    return 0;
  }
*************** combine_stack_adjustments_for_block (bas
*** 2298,2304 ****
    rtx last_sp_set = NULL_RTX;
    struct csa_memlist *memlist = NULL;
    rtx insn, next, set;
-   struct record_stack_memrefs_data data;
    bool end_of_block = false;
  
    for (insn = BB_HEAD (bb); !end_of_block ; insn = next)
--- 2295,2300 ----
*************** combine_stack_adjustments_for_block (bas
*** 2430,2444 ****
  	    }
  	}
  
-       data.insn = insn;
-       data.memlist = memlist;
        if (!CALL_P (insn) && last_sp_set
! 	  && !for_each_rtx (&PATTERN (insn), record_stack_memrefs, &data))
! 	{
! 	   memlist = data.memlist;
! 	   continue;
! 	}
!       memlist = data.memlist;
  
        /* Otherwise, we were not able to process the instruction.
  	 Do not continue collecting data across such a one.  */
--- 2426,2434 ----
  	    }
  	}
  
        if (!CALL_P (insn) && last_sp_set
! 	  && !record_stack_memrefs (insn, &memlist))
! 	continue;
  
        /* Otherwise, we were not able to process the instruction.
  	 Do not continue collecting data across such a one.  */
Index: regrename.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regrename.c,v
retrieving revision 1.94
diff -c -p -r1.94 regrename.c
*** regrename.c	15 Jan 2005 16:06:14 -0000	1.94
--- regrename.c	19 Jan 2005 09:49:43 -0000
*************** static void set_value_regno (unsigned, e
*** 1015,1021 ****
  static void init_value_data (struct value_data *);
  static void kill_clobbered_value (rtx, rtx, void *);
  static void kill_set_value (rtx, rtx, void *);
! static int kill_autoinc_value (rtx *, void *);
  static void copy_value (rtx, rtx, struct value_data *);
  static bool mode_change_ok (enum machine_mode, enum machine_mode,
  			    unsigned int);
--- 1015,1021 ----
  static void init_value_data (struct value_data *);
  static void kill_clobbered_value (rtx, rtx, void *);
  static void kill_set_value (rtx, rtx, void *);
! static void kill_autoinc_values (rtx, struct value_data *);
  static void copy_value (rtx, rtx, struct value_data *);
  static bool mode_change_ok (enum machine_mode, enum machine_mode,
  			    unsigned int);
*************** kill_set_value (rtx x, rtx set, void *da
*** 1176,1200 ****
      }
  }
  
! /* Called through for_each_rtx.  Kill any register used as the base of an
!    auto-increment expression, and install that register as the root of its
!    own value list.  */
  
! static int
! kill_autoinc_value (rtx *px, void *data)
  {
!   rtx x = *px;
!   struct value_data *vd = data;
! 
!   if (GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
!     {
!       x = XEXP (x, 0);
!       kill_value (x, vd);
!       set_value_regno (REGNO (x), Pmode, vd);
!       return -1;
      }
- 
-   return 0;
  }
  
  /* Assert that SRC has been copied to DEST.  Adjust the data structures
--- 1176,1200 ----
      }
  }
  
! /* Kill any register used as the base of an auto-increment expression, and
!    install that register as the root of its own value list.  */
  
! static void
! kill_autoinc_values (rtx exp, struct value_data *vd)
  {
!   rtx_iter iter;
!   rtx *loc, x;
!   FOR_EACH_RTX (&exp, loc, iter)
!     {
!       x = *loc;
!       if (GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
!         {
!           x = XEXP (x, 0);
!           kill_value (x, vd);
!           set_value_regno (REGNO (x), Pmode, vd);
!           rtx_iter_skip (&iter);
! 	}
      }
  }
  
  /* Assert that SRC has been copied to DEST.  Adjust the data structures
*************** copyprop_hardreg_forward_1 (basic_block 
*** 1597,1603 ****
  
        /* Kill all auto-incremented values.  */
        /* ??? REG_INC is useless, since stack pushes aren't done that way.  */
!       for_each_rtx (&PATTERN (insn), kill_autoinc_value, vd);
  
        /* Kill all early-clobbered operands.  */
        for (i = 0; i < n_ops; i++)
--- 1597,1603 ----
  
        /* Kill all auto-incremented values.  */
        /* ??? REG_INC is useless, since stack pushes aren't done that way.  */
!       kill_autoinc_values (PATTERN (insn), vd);
  
        /* Kill all early-clobbered operands.  */
        for (i = 0; i < n_ops; i++)
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.532
diff -c -p -r1.532 rtl.h
*** rtl.h	17 Jan 2005 08:46:15 -0000	1.532
--- rtl.h	19 Jan 2005 09:49:45 -0000
*************** extern rtx set_unique_reg_note (rtx, enu
*** 1558,1571 ****
  		       : NULL_RTX)
  #define single_set_1(I) single_set_2 (I, PATTERN (I))
  
- /* Structure used for passing data to REPLACE_LABEL.  */
- typedef struct replace_label_data
- {
-   rtx r1;
-   rtx r2;
-   bool update_label_nuses;
- } replace_label_data;
- 
  extern int rtx_addr_can_trap_p (rtx);
  extern bool nonzero_address_p (rtx);
  extern int rtx_unstable_p (rtx);
--- 1558,1563 ----
*************** extern int may_trap_p (rtx);
*** 1611,1617 ****
  extern int inequality_comparisons_p (rtx);
  extern rtx replace_rtx (rtx, rtx, rtx);
  extern rtx replace_regs (rtx, rtx *, unsigned int, int);
! extern int replace_label (rtx *, void *);
  extern int rtx_referenced_p (rtx, rtx);
  extern bool tablejump_p (rtx, rtx *, rtx *);
  extern int computed_jump_p (rtx);
--- 1603,1609 ----
  extern int inequality_comparisons_p (rtx);
  extern rtx replace_rtx (rtx, rtx, rtx);
  extern rtx replace_regs (rtx, rtx *, unsigned int, int);
! extern void replace_label (rtx *, rtx, rtx, bool);
  extern int rtx_referenced_p (rtx, rtx);
  extern bool tablejump_p (rtx, rtx *, rtx *);
  extern int computed_jump_p (rtx);
*************** extern void reg_alloc (void);
*** 2181,2186 ****
--- 2173,2320 ----
  /* In modulo-sched.c.  */
  extern void sms_schedule (FILE *);
  
+ /* Traverse X via depth-first search, calling F for each
+    sub-expression (including X itself).  F is also passed the DATA.
+    If F returns -1, do not traverse sub-expressions, but continue
+    traversing the rest of the tree.  Upon an iteration, SUB_RTX points
+    to an rtx in the tree; rtx_iter_skip can be called to avoid visiting
+    the subexpressions of SUB_RTX.  */
+ 
+ /* Always ensure two free items in the list, which are needed for rtvecs.
+    The ENABLE_CHECKING version stores each element in the NEXT field of
+    the iterator, so that rtx_iter_skip can check that the correct value
+    is passed.  */
+ #define FOR_EACH_RTX(X, SUB_RTX, ITER) \
+   for ((SUB_RTX) = rtx_iter_init (&(ITER), (X)); \
+        (SUB_RTX); \
+        ((ITER).free == NULL \
+ 	? (void) ((ITER).free = alloca (sizeof (rtx_stack_entry)), \
+ 	    (ITER).free->next = NULL) : (void) 0), \
+        ((ITER).free->next == NULL \
+ 	? (void) ((ITER).free->next = alloca (sizeof (rtx_stack_entry)), \
+ 	    (ITER).free->next->next = NULL) : (void) 0), \
+         (SUB_RTX) = rtx_iter_next (&(ITER)))
+ 
+ union rtx_stack_item {
+   rtx   *x;
+   rtvec  vec;
+ };
+ 
+ typedef struct rtx_stack_entry {
+   struct rtx_stack_entry *next;
+   union rtx_stack_item    fld;
+   int			  n;
+   const char		 *format;
+ } rtx_stack_entry;
+ 
+ typedef struct {
+   rtx_stack_entry	 *stack, *free;
+   rtx             *next;
+ } rtx_iter;
+ 
+ static inline rtx *
+ rtx_iter_init (rtx_iter *iter, rtx *x)
+ {
+   iter->stack = NULL;
+   iter->free = NULL;
+   iter->next = x;
+   return x;
+ }
+ 
+ static void
+ rtx_iter_push_vec (rtx_iter *iter, rtvec vec)
+ {
+   struct rtx_stack_entry *cur;
+   iter->next = &RTVEC_ELT (vec, 0);
+ 
+   cur = iter->free;
+   iter->free = cur->next;
+ 
+   cur->n = 1;
+   cur->fld.vec = vec;
+   cur->format = NULL;
+   cur->next = iter->stack;
+   iter->stack = cur;
+ }
+ 
+ static inline rtx *
+ rtx_iter_next (rtx_iter *iter)
+ {
+   struct rtx_stack_entry *cur;
+   const char *format, *recursion_point;
+ 
+   if (iter->next && *iter->next)
+     {
+       format = GET_RTX_FORMAT (GET_CODE (*iter->next));
+       recursion_point = strpbrk (format, "eEV");
+ 
+       /* Optimize leaves (like PC, or REGs).  */
+       if (recursion_point != NULL)
+         {
+ 	  /* We have to push an entry on the stack.  */
+ 	  cur = iter->free;
+ 	  cur->n = recursion_point - format;
+ 	  cur->fld.x = iter->next;
+ 	  cur->format = format;
+ 
+ 	  iter->free = cur->next;
+ 	  cur->next = iter->stack;
+ 	  iter->stack = cur;
+ 	}
+     }
+ 
+   /* rtx_iter_skip may cause the entry condition to be false!  */
+   while ((cur = iter->stack) != NULL)
+     {
+       const char *format = cur->format;
+       if (format)
+         {
+ 	  /* Looking in an rtx */
+ 	  char c;
+ 	  rtx x = *cur->fld.x;
+           for (; (c = format[cur->n]) != '\0'; cur->n++)
+             if (c == 'e')
+ 	      {
+ 	        iter->next = &XEXP (x, cur->n);
+ 		cur->n++;
+ 	        return iter->next;
+ 	      }
+ 	    else if ((c == 'E' || c == 'V') && XVECLEN (x, cur->n) > 0)
+ 	      {
+ 		rtx_iter_push_vec (iter, XVEC (x, cur->n));
+ 		cur->n++;
+ 	        return iter->next;
+ 	      }
+ 	}
+       else
+         {
+ 	  /* Looking in an rtvec */
+ 	  rtvec vec = cur->fld.vec;
+           if (cur->n < GET_NUM_ELEM (vec))
+ 	    {
+ 	      iter->next = &RTVEC_ELT (vec, cur->n);
+ 	      cur->n++;
+ 	      return iter->next;
+ 	    }
+ 	}
+ 
+       /* Pop an entry off the stack */
+       iter->stack = cur->next;
+       cur->next = iter->free;
+       iter->free = cur;
+     }
+ 
+   return NULL;
+ }
+ 
+ /* Avoid that *X's subexpressions are visited.  There is no way to stop
+    visiting the elements of a vector.  */
+ static inline void
+ rtx_iter_skip (rtx_iter *iter)
+ {
+   iter->next = NULL;
+ }
+ 
  struct rtl_hooks
  {
    rtx (*gen_lowpart) (enum machine_mode, rtx);
Index: rtlanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtlanal.c,v
retrieving revision 1.208
diff -c -p -r1.208 rtlanal.c
*** rtlanal.c	15 Jan 2005 04:14:10 -0000	1.208
--- rtlanal.c	19 Jan 2005 09:49:50 -0000
*************** Software Foundation, 59 Temple Place - S
*** 38,48 ****
  #include "function.h"
  
  /* Forward declarations */
- static int global_reg_mentioned_p_1 (rtx *, void *);
  static void set_of_1 (rtx, rtx, void *);
  static bool covers_regno_p (rtx, unsigned int);
  static bool covers_regno_no_parallel_p (rtx, unsigned int);
- static int rtx_referenced_p_1 (rtx *, void *);
  static int computed_jump_p_1 (rtx);
  static void parms_set (rtx, rtx, void *);
  
--- 38,46 ----
*************** get_related_value (rtx x)
*** 433,493 ****
    return 0;
  }
  
- /* A subroutine of global_reg_mentioned_p, returns 1 if *LOC mentions
-    a global register.  */
- 
- static int
- global_reg_mentioned_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
- {
-   int regno;
-   rtx x = *loc;
- 
-   if (! x)
-     return 0;
- 
-   switch (GET_CODE (x))
-     {
-     case SUBREG:
-       if (REG_P (SUBREG_REG (x)))
- 	{
- 	  if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
- 	      && global_regs[subreg_regno (x)])
- 	    return 1;
- 	  return 0;
- 	}
-       break;
- 
-     case REG:
-       regno = REGNO (x);
-       if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
- 	return 1;
-       return 0;
- 
-     case SCRATCH:
-     case PC:
-     case CC0:
-     case CONST_INT:
-     case CONST_DOUBLE:
-     case CONST:
-     case LABEL_REF:
-       return 0;
- 
-     case CALL:
-       /* A non-constant call might use a global register.  */
-       return 1;
- 
-     default:
-       break;
-     }
- 
-   return 0;
- }
- 
  /* Returns nonzero if X mentions a global register.  */
  
  int
  global_reg_mentioned_p (rtx x)
  {
    if (INSN_P (x))
      {
        if (CALL_P (x))
--- 431,443 ----
    return 0;
  }
  
  /* Returns nonzero if X mentions a global register.  */
  
  int
  global_reg_mentioned_p (rtx x)
  {
+   rtx_iter iter;
+   rtx *loc;
    if (INSN_P (x))
      {
        if (CALL_P (x))
*************** global_reg_mentioned_p (rtx x)
*** 502,508 ****
  	x = PATTERN (x);
      }
  
!   return for_each_rtx (&x, global_reg_mentioned_p_1, NULL);
  }
  
  /* Return the number of places FIND appears within X.  If COUNT_DEST is
--- 452,499 ----
  	x = PATTERN (x);
      }
  
!   FOR_EACH_RTX (&x, loc, iter)
!     {
!       int regno;
!       rtx y = *loc;
! 
!       if (! y)
!         return 0;
! 
!       switch (GET_CODE (y))
!         {
!         case SUBREG:
!           if (REG_P (SUBREG_REG (y))
! 	      && REGNO (SUBREG_REG (y)) < FIRST_PSEUDO_REGISTER
! 	      && global_regs[subreg_regno (y)])
! 	    return 1;
!           break;
! 
!         case REG:
!           regno = REGNO (y);
!           if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
! 	    return 1;
!           break;
!     
!         case SCRATCH:
!         case PC:
!         case CC0:
!         case CONST_INT:
!         case CONST_DOUBLE:
!         case CONST:
!         case LABEL_REF:
!           break;
! 
!         case CALL:
!           /* A non-constant call might use a global register.  */
!           return 1;
! 
!         default:
!           break;
!         }
!     }
! 
!   return 0;
  }
  
  /* Return the number of places FIND appears within X.  If COUNT_DEST is
*************** replace_regs (rtx x, rtx *reg_map, unsig
*** 2415,2509 ****
  /* Replace occurrences of the old label in *X with the new one.
     DATA is a REPLACE_LABEL_DATA containing the old and new labels.  */
  
! int
! replace_label (rtx *x, void *data)
  {
!   rtx l = *x;
!   rtx old_label = ((replace_label_data *) data)->r1;
!   rtx new_label = ((replace_label_data *) data)->r2;
!   bool update_label_nuses = ((replace_label_data *) data)->update_label_nuses;
! 
!   if (l == NULL_RTX)
!     return 0;
! 
!   if (GET_CODE (l) == SYMBOL_REF
!       && CONSTANT_POOL_ADDRESS_P (l))
      {
!       rtx c = get_pool_constant (l);
!       if (rtx_referenced_p (old_label, c))
  	{
! 	  rtx new_c, new_l;
! 	  replace_label_data *d = (replace_label_data *) data;
  
! 	  /* Create a copy of constant C; replace the label inside
! 	     but do not update LABEL_NUSES because uses in constant pool
! 	     are not counted.  */
! 	  new_c = copy_rtx (c);
! 	  d->update_label_nuses = false;
! 	  for_each_rtx (&new_c, replace_label, data);
! 	  d->update_label_nuses = update_label_nuses;
! 
! 	  /* Add the new constant NEW_C to constant pool and replace
! 	     the old reference to constant by new reference.  */
! 	  new_l = XEXP (force_const_mem (get_pool_mode (l), new_c), 0);
! 	  *x = replace_rtx (l, l, new_l);
  	}
-       return 0;
-     }
  
!   /* If this is a JUMP_INSN, then we also need to fix the JUMP_LABEL
!      field.  This is not handled by for_each_rtx because it doesn't
!      handle unprinted ('0') fields.  */
!   if (JUMP_P (l) && JUMP_LABEL (l) == old_label)
!     JUMP_LABEL (l) = new_label;
! 
!   if ((GET_CODE (l) == LABEL_REF
!        || GET_CODE (l) == INSN_LIST)
!       && XEXP (l, 0) == old_label)
!     {
!       XEXP (l, 0) = new_label;
!       if (update_label_nuses)
! 	{
! 	  ++LABEL_NUSES (new_label);
! 	  --LABEL_NUSES (old_label);
! 	}
!       return 0;
      }
- 
-   return 0;
  }
  
! /* When *BODY is equal to X or X is directly referenced by *BODY
!    return nonzero, thus FOR_EACH_RTX stops traversing and returns nonzero
!    too, otherwise FOR_EACH_RTX continues traversing *BODY.  */
  
! static int
! rtx_referenced_p_1 (rtx *body, void *x)
  {
!   rtx y = (rtx) x;
! 
!   if (*body == NULL_RTX)
!     return y == NULL_RTX;
  
!   /* Return true if a label_ref *BODY refers to label Y.  */
!   if (GET_CODE (*body) == LABEL_REF && LABEL_P (y))
!     return XEXP (*body, 0) == y;
  
!   /* If *BODY is a reference to pool constant traverse the constant.  */
!   if (GET_CODE (*body) == SYMBOL_REF
!       && CONSTANT_POOL_ADDRESS_P (*body))
!     return rtx_referenced_p (y, get_pool_constant (*body));
  
!   /* By default, compare the RTL expressions.  */
!   return rtx_equal_p (*body, y);
! }
  
! /* Return true if X is referenced in BODY.  */
  
! int
! rtx_referenced_p (rtx x, rtx body)
! {
!   return for_each_rtx (&body, rtx_referenced_p_1, x);
  }
  
  /* If INSN is a tablejump return true and store the label (before jump table) to
--- 2406,2513 ----
  /* Replace occurrences of the old label in *X with the new one.
     DATA is a REPLACE_LABEL_DATA containing the old and new labels.  */
  
! void
! replace_label (rtx *x, rtx old_label, rtx new_label, bool update_label_nuses)
  {
!   rtx_iter iter;
!   rtx *sub;
!   FOR_EACH_RTX (x, sub, iter)
      {
!       rtx l = *sub;
! 
!       if (l != NULL_RTX
!           && GET_CODE (l) == SYMBOL_REF
! 	  && CONSTANT_POOL_ADDRESS_P (l))
  	{
! 	  rtx c = get_pool_constant (l);
! 	  if (rtx_referenced_p (old_label, c))
! 	    {
! 	      rtx new_c, new_l;
  
! 	      /* Create a copy of constant C; replace the label inside
! 	         but do not update LABEL_NUSES because uses in constant pool
! 	         are not counted.  */
! 	      new_c = copy_rtx (c);
! 	      replace_label (&new_c, old_label, new_label, false);
! 
! 	      /* Add the new constant NEW_C to constant pool and replace
! 	         the old reference to constant by new reference.  */
! 	      new_l = XEXP (force_const_mem (get_pool_mode (l), new_c), 0);
! 	      *x = replace_rtx (l, l, new_l);
! 	    }
  	}
  
!      /* If this is a JUMP_INSN, then we also need to fix the JUMP_LABEL
!         field.  This is not handled by FOR_EACH_RTX because it doesn't
!         handle unprinted ('0') fields.  */
!      if (JUMP_P (l) && JUMP_LABEL (l) == old_label)
!        JUMP_LABEL (l) = new_label;
! 
!      if ((GET_CODE (l) == LABEL_REF
!           || GET_CODE (l) == INSN_LIST)
!          && XEXP (l, 0) == old_label)
!        {
!          XEXP (l, 0) = new_label;
!          if (update_label_nuses)
! 	   {
! 	     ++LABEL_NUSES (new_label);
! 	     --LABEL_NUSES (old_label);
! 	   }
!        }
      }
  }
  
! /* Return true if X is referenced in BODY.  */
  
! int
! rtx_referenced_p (rtx x, rtx body)
  {
!   rtx_iter iter;
!   rtx *loc;
!   FOR_EACH_RTX (&body, loc, iter)
!     {
!       if (x == NULL_RTX || *loc == NULL_RTX)
! 	{
!           if (x == *loc)
! 	    return true;
! 	  else
! 	    continue;
! 	}
  
!       switch (GET_CODE (*loc))
! 	{
! 	case LABEL_REF:
!           /* Return true if a label_ref *BODY refers to label X.  */
! 	  if (LABEL_P (x))
! 	    {
! 	      if (XEXP (*loc, 0) == x)
! 		return 1;
! 	      else
! 		continue;
! 	    }
! 	  break;
  
! 	case SYMBOL_REF:
!           /* If *BODY is a reference to pool constant traverse the constant.  */
!           if (CONSTANT_POOL_ADDRESS_P (*loc))
! 	    {
! 	      if (rtx_referenced_p (x, get_pool_constant (*loc)))
! 		return 1;
! 	      else
! 		continue;
! 	    }
! 	  break;
  
! 	default:
! 	  break;
! 	}
  
!       /* By default, compare the RTL expressions.  */
!       if (rtx_equal_p (*loc, x))
! 	return 1;
!     }
  
!   return 0;
  }
  
  /* If INSN is a tablejump return true and store the label (before jump table) to
*************** computed_jump_p (rtx insn)
*** 2629,2638 ****
     If F returns -1, do not traverse sub-expressions, but continue
     traversing the rest of the tree.  If F ever returns any other
     nonzero value, stop the traversal, and return the value returned
!    by F.  Otherwise, return 0.  This function does not traverse inside
!    tree structure that contains RTX_EXPRs, or into sub-expressions
!    whose format code is `0' since it is not known whether or not those
!    codes are actually RTL.
  
     This routine is very general, and could (should?) be used to
     implement many of the other routines in this file.  */
--- 2633,2641 ----
     If F returns -1, do not traverse sub-expressions, but continue
     traversing the rest of the tree.  If F ever returns any other
     nonzero value, stop the traversal, and return the value returned
!    by F.  Otherwise, return 0.  This function does not traverse
!    into sub-expressions whose format code is `0' since it is not known
!    whether or not those codes are actually RTL.
  
     This routine is very general, and could (should?) be used to
     implement many of the other routines in this file.  */
*************** computed_jump_p (rtx insn)
*** 2640,2695 ****
  int
  for_each_rtx (rtx *x, rtx_function f, void *data)
  {
!   int result;
!   int length;
!   const char *format;
!   int i;
! 
!   /* Call F on X.  */
!   result = (*f) (x, data);
!   if (result == -1)
!     /* Do not traverse sub-expressions.  */
!     return 0;
!   else if (result != 0)
!     /* Stop the traversal.  */
!     return result;
! 
!   if (*x == NULL_RTX)
!     /* There are no sub-expressions.  */
!     return 0;
! 
!   length = GET_RTX_LENGTH (GET_CODE (*x));
!   format = GET_RTX_FORMAT (GET_CODE (*x));
! 
!   for (i = 0; i < length; ++i)
!     {
!       switch (format[i])
! 	{
! 	case 'e':
! 	  result = for_each_rtx (&XEXP (*x, i), f, data);
! 	  if (result != 0)
! 	    return result;
! 	  break;
! 
! 	case 'V':
! 	case 'E':
! 	  if (XVEC (*x, i) != 0)
! 	    {
! 	      int j;
! 	      for (j = 0; j < XVECLEN (*x, i); ++j)
! 		{
! 		  result = for_each_rtx (&XVECEXP (*x, i, j), f, data);
! 		  if (result != 0)
! 		    return result;
! 		}
! 	    }
! 	  break;
! 
! 	default:
! 	  /* Nothing to do.  */
! 	  break;
! 	}
! 
      }
  
    return 0;
--- 2643,2659 ----
  int
  for_each_rtx (rtx *x, rtx_function f, void *data)
  {
!   rtx_iter iter;
!   rtx *each;
!   FOR_EACH_RTX (x, each, iter)
!     {
!       int result = f (each, data);
!       if (result == -1)
! 	/* Do not traverse sub-expressions.  */
! 	rtx_iter_skip (&iter);
!       else if (result != 0)
! 	/* Stop the traversal.  */
! 	return result;
      }
  
    return 0;
Index: value-prof.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/value-prof.c,v
retrieving revision 1.16
diff -c -p -r1.16 value-prof.c
*** value-prof.c	14 Nov 2004 23:35:03 -0000	1.16
--- value-prof.c	19 Jan 2005 09:49:51 -0000
*************** static struct value_prof_hooks *value_pr
*** 77,83 ****
  static void insn_divmod_values_to_profile (rtx, histogram_values *);
  #ifdef HAVE_prefetch
  static bool insn_prefetch_values_to_profile (rtx, histogram_values *);
- static int find_mem_reference_1 (rtx *, void *);
  static void find_mem_reference_2 (rtx, rtx, void *);
  static bool find_mem_reference (rtx, rtx *, int *);
  #endif
--- 77,82 ----
*************** insn_divmod_values_to_profile (rtx insn,
*** 185,209 ****
  
  #ifdef HAVE_prefetch
  
! /* Called from find_mem_reference through for_each_rtx, finds a memory
!    reference.  I.e. if *EXPR is a MEM, the reference to this MEM is stored
!    to *RET and the traversing of the expression is interrupted by returning 1.
!    Otherwise 0 is returned.  */
! 
! static int
! find_mem_reference_1 (rtx *expr, void *ret)
! {
!   rtx *mem = ret;
! 
!   if (GET_CODE (*expr) == MEM)
!     {
!       *mem = *expr;
!       return 1;
!     }
!   return 0;
! }
! 
! /* Called form find_mem_reference through note_stores to find out whether
     the memory reference MEM is a store.  I.e. if EXPR == MEM, the variable
     FMR2_WRITE is set to true.  */
  
--- 184,190 ----
  
  #ifdef HAVE_prefetch
  
! /* Called from find_mem_reference through note_stores to find out whether
     the memory reference MEM is a store.  I.e. if EXPR == MEM, the variable
     FMR2_WRITE is set to true.  */
  
*************** find_mem_reference_2 (rtx expr, rtx pat 
*** 222,237 ****
  static bool
  find_mem_reference (rtx insn, rtx *mem, int *write)
  {
!   *mem = NULL_RTX;
!   for_each_rtx (&PATTERN (insn), find_mem_reference_1, mem);
  
!   if (!*mem)
!     return false;
!   
!   fmr2_write = false;
!   note_stores (PATTERN (insn), find_mem_reference_2, *mem);
!   *write = fmr2_write;
!   return true;
  }
  
  /* Find values inside INSN for that we want to measure histograms for
--- 203,222 ----
  static bool
  find_mem_reference (rtx insn, rtx *mem, int *write)
  {
!   rtx_iter iter;
!   rtx *expr;
!   FOR_EACH_RTX (&PATTERN (insn), expr, iter)
!     if (GET_CODE (*expr) == MEM)
!       {
!         *mem = *expr;
! 	fmr2_write = false;
! 	note_stores (PATTERN (insn), find_mem_reference_2, *mem);
! 	*write = fmr2_write;
! 	return true;
!       }
  
!   *mem = NULL_RTX;
!   return false;
  }
  
  /* Find values inside INSN for that we want to measure histograms for
Index: var-tracking.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/var-tracking.c,v
retrieving revision 2.24
diff -c -p -r2.24 var-tracking.c
*** var-tracking.c	1 Jan 2005 01:43:11 -0000	2.24
--- var-tracking.c	19 Jan 2005 09:49:53 -0000
*************** static void dataflow_set_destroy (datafl
*** 315,324 ****
  
  static bool contains_symbol_ref (rtx);
  static bool track_expr_p (tree);
! static int count_uses (rtx *, void *);
  static void count_uses_1 (rtx *, void *);
  static void count_stores (rtx, rtx, void *);
! static int add_uses (rtx *, void *);
  static void add_uses_1 (rtx *, void *);
  static void add_stores (rtx, rtx, void *);
  static bool compute_bb_dataflow (basic_block);
--- 315,324 ----
  
  static bool contains_symbol_ref (rtx);
  static bool track_expr_p (tree);
! static void count_uses (rtx, rtx);
  static void count_uses_1 (rtx *, void *);
  static void count_stores (rtx, rtx, void *);
! static void add_uses (rtx, rtx);
  static void add_uses_1 (rtx *, void *);
  static void add_stores (rtx, rtx, void *);
  static bool compute_bb_dataflow (basic_block);
*************** track_expr_p (tree expr)
*** 1503,1529 ****
  /* Count uses (register and memory references) LOC which will be tracked.
     INSN is instruction which the LOC is part of.  */
  
! static int
! count_uses (rtx *loc, void *insn)
  {
!   basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
  
!   if (REG_P (*loc))
      {
  #ifdef ENABLE_CHECKING
! 	if (REGNO (*loc) >= FIRST_PSEUDO_REGISTER)
! 	  abort ();
  #endif
! 	VTI (bb)->n_mos++;
!     }
!   else if (MEM_P (*loc)
! 	   && MEM_EXPR (*loc)
! 	   && track_expr_p (MEM_EXPR (*loc)))
!     {
! 	  VTI (bb)->n_mos++;
      }
! 
!   return 0;
  }
  
  /* Helper function for finding all uses of REG/MEM in X in insn INSN.  */
--- 1503,1525 ----
  /* Count uses (register and memory references) LOC which will be tracked.
     INSN is instruction which the LOC is part of.  */
  
! static inline void
! count_uses (rtx x, rtx insn)
  {
!   basic_block bb = BLOCK_FOR_INSN (insn);
  
!   if (REG_P (x))
      {
  #ifdef ENABLE_CHECKING
!       if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
! 	abort ();
  #endif
!       VTI (bb)->n_mos++;
      }
!   else if (MEM_P (x)
! 	   && MEM_EXPR (x)
! 	   && track_expr_p (MEM_EXPR (x)))
!     VTI (bb)->n_mos++;
  }
  
  /* Helper function for finding all uses of REG/MEM in X in insn INSN.  */
*************** count_uses (rtx *loc, void *insn)
*** 1531,1577 ****
  static void
  count_uses_1 (rtx *x, void *insn)
  {
!   for_each_rtx (x, count_uses, insn);
  }
  
  /* Count stores (register and memory references) LOC which will be tracked.
     INSN is instruction which the LOC is part of.  */
  
  static void
! count_stores (rtx loc, rtx expr ATTRIBUTE_UNUSED, void *insn)
  {
!   count_uses (&loc, insn);
  }
  
  /* Add uses (register and memory references) LOC which will be tracked
     to VTI (bb)->mos.  INSN is instruction which the LOC is part of.  */
  
! static int
! add_uses (rtx *loc, void *insn)
  {
!   if (REG_P (*loc))
      {
!       basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
        micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
  
!       mo->type = ((REG_EXPR (*loc) && track_expr_p (REG_EXPR (*loc)))
  		  ? MO_USE : MO_USE_NO_VAR);
!       mo->u.loc = *loc;
!       mo->insn = (rtx) insn;
      }
!   else if (MEM_P (*loc)
! 	   && MEM_EXPR (*loc)
! 	   && track_expr_p (MEM_EXPR (*loc)))
      {
!       basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
        micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
  
        mo->type = MO_USE;
!       mo->u.loc = *loc;
!       mo->insn = (rtx) insn;
      }
- 
-   return 0;
  }
  
  /* Helper function for finding all uses of REG/MEM in X in insn INSN.  */
--- 1527,1574 ----
  static void
  count_uses_1 (rtx *x, void *insn)
  {
!   rtx_iter iter;  
!   rtx *loc;
!   FOR_EACH_RTX (x, loc, iter)
!     count_uses (*loc, (rtx) insn);
  }
  
  /* Count stores (register and memory references) LOC which will be tracked.
     INSN is instruction which the LOC is part of.  */
  
  static void
! count_stores (rtx x, rtx expr ATTRIBUTE_UNUSED, void *insn)
  {
!   count_uses (x, (rtx) insn);
  }
  
  /* Add uses (register and memory references) LOC which will be tracked
     to VTI (bb)->mos.  INSN is instruction which the LOC is part of.  */
  
! static inline void
! add_uses (rtx x, rtx insn)
  {
!   if (REG_P (x))
      {
!       basic_block bb = BLOCK_FOR_INSN (insn);
        micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
  
!       mo->type = ((REG_EXPR (x) && track_expr_p (REG_EXPR (x)))
  		  ? MO_USE : MO_USE_NO_VAR);
!       mo->u.loc = x;
!       mo->insn = insn;
      }
!   else if (MEM_P (x)
! 	   && MEM_EXPR (x)
! 	   && track_expr_p (MEM_EXPR (x)))
      {
!       basic_block bb = BLOCK_FOR_INSN (insn);
        micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
  
        mo->type = MO_USE;
!       mo->u.loc = x;
!       mo->insn = insn;
      }
  }
  
  /* Helper function for finding all uses of REG/MEM in X in insn INSN.  */
*************** add_uses (rtx *loc, void *insn)
*** 1579,1585 ****
  static void
  add_uses_1 (rtx *x, void *insn)
  {
!   for_each_rtx (x, add_uses, insn);
  }
  
  /* Add stores (register and memory references) LOC which will be tracked
--- 1576,1585 ----
  static void
  add_uses_1 (rtx *x, void *insn)
  {
!   rtx_iter iter;  
!   rtx *loc;
!   FOR_EACH_RTX (x, loc, iter)
!     add_uses (*loc, (rtx) insn);
  }
  
  /* Add stores (register and memory references) LOC which will be tracked
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.476
diff -c -p -r1.476 varasm.c
*** varasm.c	16 Jan 2005 15:28:16 -0000	1.476
--- varasm.c	19 Jan 2005 09:49:55 -0000
*************** static int const_desc_eq (const void *, 
*** 131,136 ****
--- 131,138 ----
  static hashval_t const_hash_1 (const tree);
  static int compare_constant (const tree, const tree);
  static tree copy_constant (tree);
+ static void mark_constant (struct rtx_constant_pool *, rtx);
+ static void mark_constants_1 (struct rtx_constant_pool *, rtx);
  static void output_constant_def_contents (rtx);
  static void output_addressed_constants (tree);
  static unsigned HOST_WIDE_INT array_size_for_constructor (tree);
*************** const_desc_rtx_sym_eq (const void *a, co
*** 2829,2909 ****
    return XSTR (x->sym, 0) == XSTR (y->sym, 0);
  }
  
! /* This is the worker function for const_rtx_hash, called via for_each_rtx.  */
  
  static int
! const_rtx_hash_1 (rtx *xp, void *data)
  {
!   unsigned HOST_WIDE_INT hwi;
!   enum machine_mode mode;
!   enum rtx_code code;
!   hashval_t h, *hp;
!   rtx x;
! 
!   x = *xp;
!   code = GET_CODE (x);
!   mode = GET_MODE (x);
!   h = (hashval_t) code * 1048573 + mode;
! 
!   switch (code)
!     {
!     case CONST_INT:
!       hwi = INTVAL (x);
!     fold_hwi:
!       {
! 	const int shift = sizeof (hashval_t) * CHAR_BIT;
! 	const int n = sizeof (HOST_WIDE_INT) / sizeof (hashval_t);
! 	int i;
  
- 	h ^= (hashval_t) hwi;
- 	for (i = 1; i < n; ++i)
- 	  {
- 	    hwi >>= shift;
  	    h ^= (hashval_t) hwi;
! 	  }
!       }
!       break;
! 
!     case CONST_DOUBLE:
!       if (mode == VOIDmode)
! 	{
! 	  hwi = CONST_DOUBLE_LOW (x) ^ CONST_DOUBLE_HIGH (x);
! 	  goto fold_hwi;
! 	}
!       else
! 	h ^= real_hash (CONST_DOUBLE_REAL_VALUE (x));
!       break;
! 
!     case SYMBOL_REF:
!       h ^= htab_hash_string (XSTR (x, 0));
!       break;
! 
!     case LABEL_REF:
!       h = h * 251 + CODE_LABEL_NUMBER (XEXP (x, 0));
!       break;
  
!     case UNSPEC:
!     case UNSPEC_VOLATILE:
!       h = h * 251 + XINT (x, 1);
!       break;
  
!     default:
!       break;
      }
! 
!   hp = data;
!   *hp = *hp * 509 + h;
!   return 0;
! }
! 
! /* Compute a hash value for X, which should be a constant.  */
! 
! static hashval_t
! const_rtx_hash (rtx x)
! {
!   hashval_t h = 0;
!   for_each_rtx (&x, const_rtx_hash_1, &h);
!   return h;
  }
  
  
--- 2831,2902 ----
    return XSTR (x->sym, 0) == XSTR (y->sym, 0);
  }
  
! /* Compute a hash value for X, which should be a constant.  */
  
  static int
! const_rtx_hash (rtx exp)
  {
!   hashval_t total = 0, h;
!   rtx_iter iter;
!   rtx *xp;
! 
!   FOR_EACH_RTX (&exp, xp, iter)
!     {
!       unsigned HOST_WIDE_INT hwi;
!       rtx x = *xp;
!       enum machine_mode mode = GET_MODE (x);
!       enum rtx_code code = GET_CODE (x);
!       h = (hashval_t) code * 1048573 + mode;
! 
!       switch (code)
!         {
!         case CONST_INT:
!           hwi = INTVAL (x);
!         fold_hwi:
!           {
! 	    const int shift = sizeof (hashval_t) * CHAR_BIT;
! 	    const int n = sizeof (HOST_WIDE_INT) / sizeof (hashval_t);
! 	    int i;
  
  	    h ^= (hashval_t) hwi;
! 	    for (i = 1; i < n; ++i)
! 	      {
! 	        hwi >>= shift;
! 	        h ^= (hashval_t) hwi;
! 	      }
!           }
!           break;
  
!         case CONST_DOUBLE:
!           if (mode == VOIDmode)
! 	    {
! 	      hwi = CONST_DOUBLE_LOW (x) ^ CONST_DOUBLE_HIGH (x);
! 	      goto fold_hwi;
! 	    }
!           else
! 	    h ^= real_hash (CONST_DOUBLE_REAL_VALUE (x));
!           break;
! 
!         case SYMBOL_REF:
!           h ^= htab_hash_string (XSTR (x, 0));
!           break;
! 
!         case LABEL_REF:
!           h = h * 251 + CODE_LABEL_NUMBER (XEXP (x, 0));
!           break;
! 
!         case UNSPEC:
!         case UNSPEC_VOLATILE:
!           h = h * 251 + XINT (x, 1);
!           break;
! 
!         default:
!           break;
!         }
  
!       total = total * 509 + h;
      }
!   return total;
  }
  
  
*************** output_constant_pool_1 (struct constant_
*** 3210,3227 ****
    return;
  }
  
! /* Given a SYMBOL_REF CURRENT_RTX, mark it and all constants it refers
!    to as used.  Emit referenced deferred strings.  This function can
!    be used with for_each_rtx to mark all SYMBOL_REFs in an rtx.  */
  
! static int
! mark_constant (rtx *current_rtx, void *data)
  {
!   struct rtx_constant_pool *pool = data;
!   rtx x = *current_rtx;
! 
!   if (x == NULL_RTX || GET_CODE (x) != SYMBOL_REF)
!     return 0;
  
    if (CONSTANT_POOL_ADDRESS_P (x))
      {
--- 3203,3216 ----
    return;
  }
  
! /* Given a SYMBOL_REF X, mark it and all constants it refers
!    to as used.  Emit referenced deferred strings.  Compare with
!    mark_constants_1, which marks all SYMBOL_REFs in an rtx.  */
  
! static void
! mark_constant (struct rtx_constant_pool *pool, rtx x)
  {
!   gcc_assert (GET_CODE (x) == SYMBOL_REF);
  
    if (CONSTANT_POOL_ADDRESS_P (x))
      {
*************** mark_constant (rtx *current_rtx, void *d
*** 3229,3235 ****
        if (desc->mark == 0)
  	{
  	  desc->mark = 1;
! 	  for_each_rtx (&desc->constant, mark_constant, pool);
  	}
      }
    else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
--- 3218,3224 ----
        if (desc->mark == 0)
  	{
  	  desc->mark = 1;
! 	  mark_constants_1 (pool, desc->constant);
  	}
      }
    else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
*************** mark_constant (rtx *current_rtx, void *d
*** 3241,3249 ****
  	  output_constant_def_contents (x);
  	}
      }
  
!   return -1;
! } 
  
  /* Look through appropriate parts of INSN, marking all entries in the
     constant pool which are actually being used.  Entries that are only
--- 3230,3249 ----
  	  output_constant_def_contents (x);
  	}
      }
+ }
  
! static void
! mark_constants_1 (struct rtx_constant_pool *pool, rtx x)
! {
!   rtx_iter iter;
!   rtx *loc;
!   FOR_EACH_RTX (&x, loc, iter)
!     if (*loc && GET_CODE (*loc) == SYMBOL_REF)
!       {
! 	mark_constant (pool, *loc);
! 	rtx_iter_skip (&iter);
!       }
! }
  
  /* Look through appropriate parts of INSN, marking all entries in the
     constant pool which are actually being used.  Entries that are only
*************** mark_constants (struct rtx_constant_pool
*** 3267,3277 ****
  	{
  	  rtx subinsn = XVECEXP (seq, 0, i);
  	  if (INSN_P (subinsn))
! 	    for_each_rtx (&PATTERN (subinsn), mark_constant, pool);
  	}
      }
    else
!     for_each_rtx (&PATTERN (insn), mark_constant, pool);
  }
  
  /* Look through the instructions for this function, and mark all the
--- 3267,3277 ----
  	{
  	  rtx subinsn = XVECEXP (seq, 0, i);
  	  if (INSN_P (subinsn))
! 	    mark_constants_1 (pool, PATTERN (subinsn));
  	}
      }
    else
!     mark_constants_1 (pool, PATTERN (insn));
  }
  
  /* Look through the instructions for this function, and mark all the
Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.469
diff -u -p -r1.469 combine.c
--- combine.c	19 Jan 2005 09:31:07 -0000	1.469
+++ combine.c	19 Jan 2005 17:31:16 -0000
@@ -413,7 +413,6 @@ static int insn_cuid (rtx);
 static void record_promoted_value (rtx, rtx);
 static rtx reversed_comparison (rtx, enum machine_mode, rtx, rtx);
 static enum rtx_code combine_reversed_comparison_code (rtx);
-static int unmentioned_reg_p_1 (rtx *, void *);
 static bool unmentioned_reg_p (rtx, rtx);
 
 
@@ -12436,23 +12435,6 @@ distribute_links (rtx links)
 	}
     }
 }
-
-/* Subroutine of unmentioned_reg_p and callback from for_each_rtx.
-   Check whether the expression pointer to by LOC is a register or
-   memory, and if so return 1 if it isn't mentioned in the rtx EXPR.
-   Otherwise return zero.  */
-
-static int
-unmentioned_reg_p_1 (rtx *loc, void *expr)
-{
-  rtx x = *loc;
-
-  if (x != NULL_RTX
-      && (REG_P (x) || MEM_P (x))
-      && ! reg_mentioned_p (x, (rtx) expr))
-    return 1;
-  return 0;
-}
 
 /* Check for any register or memory mentioned in EQUIV that is not
    mentioned in EXPR.  This is used to restrict EQUIV to "specializations"
@@ -12461,7 +12443,17 @@ unmentioned_reg_p_1 (rtx *loc, void *exp
 static bool
 unmentioned_reg_p (rtx equiv, rtx expr)
 {
-  return for_each_rtx (&equiv, unmentioned_reg_p_1, expr);
+  rtx_iter iter;
+  rtx *loc;
+  FOR_EACH_RTX (&equiv, loc, iter)
+    {
+      rtx x = *loc;
+      if (x != NULL_RTX
+          && (REG_P (x) || MEM_P (x))
+          && ! reg_mentioned_p (x, (rtx) expr))
+        return true;
+    }
+  return false;
 }
 
 /* Compute INSN_CUID for INSN, which is an insn made by combine.  */

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