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]

[dataflow] PATCH more fixes for arm.


This patch fixes two problems that were identified by testing on the arm
simulator:

Combine needs the unmolested output of the UR problem as well as the
unmolested output of the LR, not the two combined.  Much of this patch
is devoted to splitting these two problems and then defining a third
problem CLRUR (Combined LR UR) that is the and of the two problems.

The rest of this patch is to fix more regression in the auto inc/dec
code.  These problems only appeared on a machine with post-inc/dec
instructions.  The powerpc only has the pre-inc/dec so the code was only
half tested when it first went on the branch.

This has been tested on the arm-elf simulator, the powerpc and the
x86-64 (unknown linux variants).

There are still arm regressions, but not other regression on the other
platform. 

Kenny

2006-07-11  Kenneth Zadeck <zadeck@naturalbridge.com>

    * regrename.c (regrename_optimize): Changed df problem
    initialization.
    * sched-ebb.c (schedule_ebbs): Ditto.
    * reorg.c (dbr_schedule): Ditto.
    * mode-switching.c (optimize_mode_switching): Ditto.
    * ifcvt.c (if_convert): Ditto.
    * reorg.c (peephole2_optimize): Ditto.
    * regmove.c (regmove_optimize, rest_of_handle_stack_adjustments):
    Ditto.
    * sched-rgn.c (schedule_insns): Ditto.
    * rtl-factoring.c (rtl_seqabstr): Ditto.
    * bt-load.c (branch_target_load_optimize): Ditto.
    * subregs-init.c (initialize_uninitialized_subregs): Ditto.
    * df-core.c (reset_df): Ditto.
    * flow.c (update_life_info, propagate_one_insn): Renamed UPWARD_LIVE
    to LR.
    (rest_of_handle_life): Changed df problem
    initialization.
    * function.c (keep_stack_depressed): Renamed UPWARD_LIVE to LR.
    * combine.c (set_nonzero_bits_and_sign_copies): Changed DF_LIVE_IN
    to DF_UR_IN or DF_LR_IN.
    (reg_nonzero_bits_for_combine,
    reg_num_sign_bit_copies_for_combine, get_last_value): Changed
    DF_LIVE_IN to DF_UR_IN.
    * reg-stack.c (reg_to_stack): Changed df problem
    initialization. Changed DF_LIVE_IN to DF_LR_IN. str
    * struct-equiv.c (struct_equiv_init): Renamed UPWARD_LIVE
    to LR.
    * dce.c (dce_process_block): Changed DF_UPWARD_LIVE_* to DF_LR_*.
    * df.h: (DF_CLRUR) Added symbol and renamed others in block.
    (DF_CLRUR_BB_INFO): New macro.
    (DF_LIVE_IN, DF_LIVE_OUT): Changed to use output of clrur problem.
    (DF_UPWARD_LIVE_IN): Renamed to DF_LR_IN.
    (DF_UPWARD_LIVE_OUT): Renamed to DF_LR_OUT.
    (df_clrur_bb_info): New structure.
    (df_clrur_add_problem, df_clrur_get_bb_info): New functions.
    * df-problems: (df_get_live_in, df_get_live_out,
    df_lr_simulate_artificial_refs_at_end): Reworked to
    to be consistent with new dataflow problems and naming.
    (df_ur_local_finalize): Deleted function.
    (df_problem problem_UR): Removed ref to df_ur_local_finalize.
    (df_clrur_get_bb_info, df_clrur_set_bb_info,
    df_clrur_free_bb_info, df_clrur_alloc, df_clrur_free,
    df_clrur_dump, df_clrur_add_problem): New functions.
    (df_problem problem_CLRUR): New datastructure.
    * auto-inc-dec.c (reg_next_inc_use): New Array.
    (attempt_change): Added inc_reg parm and boolean result.  Move
    some tests to try_merge.  Added processing for reg_next_inc_use.
    (try_merge): Added boolean result and some test moved from
    attempt_change and parse_add_or_inc.
    (parse_add_or_inc): Move test to try_merge.  Improved debugging,
    and added code to support reg_next_inc_use.  Added more
    correctness tests.
    (rest_of_handle_auto_inc_dec): Changed df problem initialization
    and added code to support reg_next_inc_use.
    

Index: regrename.c
===================================================================
--- regrename.c	(revision 115221)
+++ regrename.c	(working copy)
@@ -195,7 +195,7 @@ regrename_optimize (void)
   char *first_obj;
   struct df * df = df_init (DF_HARD_REGS);
   df_lr_add_problem (df, DF_LR_RUN_DCE);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_ri_add_problem (df, 0);
   df_analyze (df);
 
Index: sched-ebb.c
===================================================================
--- sched-ebb.c	(revision 115221)
+++ sched-ebb.c	(working copy)
@@ -562,7 +562,7 @@ schedule_ebbs (void)
 
   df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES |	DF_SUBREGS);
   df_lr_add_problem (df, DF_LR_RUN_DCE);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_ri_add_problem (df, DF_RI_LIFE);
   df_analyze (df);
   sched_init (df);
Index: reorg.c
===================================================================
--- reorg.c	(revision 115221)
+++ reorg.c	(working copy)
@@ -3539,8 +3539,7 @@ dbr_schedule (rtx first)
   rtx insn, next, epilogue_insn = 0;
   int i;
   struct df *df = df_init (DF_HARD_REGS);
-  df_lr_add_problem (df, 0);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_ri_add_problem (df, 0);
   df_analyze (df);
 
Index: mode-switching.c
===================================================================
--- mode-switching.c	(revision 115221)
+++ mode-switching.c	(working copy)
@@ -422,8 +422,7 @@ optimize_mode_switching (void)
     return 0;
 
   df = df_init (DF_HARD_REGS);
-  df_lr_add_problem (df, 0);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_ri_add_problem (df, 0);
   df_analyze (df);
 
Index: ifcvt.c
===================================================================
--- ifcvt.c	(revision 115221)
+++ ifcvt.c	(working copy)
@@ -3854,7 +3854,7 @@ if_convert (void)
   bitmap modified = BITMAP_ALLOC (NULL);
   struct df * df = df_init (DF_HARD_REGS);
   struct dataflow *lr_dflow = df_lr_add_problem (df, DF_LR_RUN_DCE);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
 
   num_possible_if_blocks = 0;
   num_updated_if_blocks = 0;
Index: recog.c
===================================================================
--- recog.c	(revision 115221)
+++ recog.c	(working copy)
@@ -3048,7 +3048,7 @@ peephole2_optimize (void)
   struct dataflow *dflow = df->problems_by_index [DF_SCAN];
 
   df_lr_add_problem (df, DF_LR_RUN_DCE);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_ru_add_problem (df, 0);
   df_analyze (df);
 
Index: regmove.c
===================================================================
--- regmove.c	(revision 115221)
+++ regmove.c	(working copy)
@@ -1047,7 +1047,7 @@ regmove_optimize (rtx f, int nregs)
   rtx copy_src, copy_dst;
   basic_block bb;
   struct df * df = df_init (DF_HARD_REGS);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_ri_add_problem (df, DF_RI_LIFE);
   df_analyze (df);
 
@@ -2520,7 +2520,7 @@ rest_of_handle_stack_adjustments (void)
 #endif
     {
       struct df * df = df_init (DF_HARD_REGS);
-      df_ur_add_problem (df, 0);
+      df_clrur_add_problem (df, 0);
       df_ri_add_problem (df, 0);
       df_analyze (df);
       df_finish (df);
Index: sched-rgn.c
===================================================================
--- sched-rgn.c	(revision 115221)
+++ sched-rgn.c	(working copy)
@@ -2946,7 +2946,7 @@ schedule_insns (void)
 
   df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES |	DF_SUBREGS);
   df_lr_add_problem (df, DF_LR_RUN_DCE);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_ri_add_problem (df, DF_RI_LIFE);
   df_analyze (df);
   sched_init (df);
Index: rtl-factoring.c
===================================================================
--- rtl-factoring.c	(revision 115221)
+++ rtl-factoring.c	(working copy)
@@ -1362,7 +1362,7 @@ rtl_seqabstr (void)
   int iter;
   struct df * df = df_init (DF_HARD_REGS);
   df_lr_add_problem (df, DF_LR_RUN_DCE);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_analyze (df);
 
   /* Create a hash list for COLLECT_PATTERN_SEQS.  */
Index: bt-load.c
===================================================================
--- bt-load.c	(revision 115221)
+++ bt-load.c	(working copy)
@@ -1468,7 +1468,7 @@ branch_target_load_optimize (bool after_
   if (class != NO_REGS)
     {
       struct df * df = df_init (DF_HARD_REGS);
-      df_ur_add_problem (df, 0);
+      df_clrur_add_problem (df, 0);
 
       /* Initialize issue_rate.  */
       if (targetm.sched.issue_rate)
Index: subregs-init.c
===================================================================
--- subregs-init.c	(revision 115221)
+++ subregs-init.c	(working copy)
@@ -108,8 +108,7 @@ initialize_uninitialized_subregs (void)
   edge_iterator ei;
   struct df *df = df_init (DF_HARD_REGS);
 
-  df_lr_add_problem (df, 0);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_analyze (df);
 
   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
Index: flow.c
===================================================================
--- flow.c	(revision 115221)
+++ flow.c	(working copy)
@@ -629,7 +629,7 @@ update_life_info (sbitmap blocks, enum u
 	  FOR_EACH_BB_REVERSE (bb)
 	    {
 	      if (prop_flags & PROP_NO_UNINITIALIZED_LL)
-		COPY_REG_SET (tmp, DF_UPWARD_LIVE_OUT (rtl_df, bb));
+		COPY_REG_SET (tmp, DF_LR_OUT (rtl_df, bb));
 	      else
 		COPY_REG_SET (tmp, df_get_live_out (rtl_df, bb));
 	      changed |= propagate_block (bb, tmp, NULL, NULL,
@@ -803,6 +803,7 @@ delete_noop_moves (void)
 		  rtx new_libcall_insn = next_real_insn (insn);
 		  rtx retval_note = find_reg_note (XEXP (note, 0),
 						   REG_RETVAL, NULL_RTX);
+continue;
 		  REG_NOTES (new_libcall_insn)
 		    = gen_rtx_INSN_LIST (REG_LIBCALL, XEXP (note, 0),
 					 REG_NOTES (new_libcall_insn));
@@ -1165,7 +1166,7 @@ propagate_one_insn (struct propagate_blo
 
 	  sibcall_p = SIBLING_CALL_P (insn);
 	  if (flags & PROP_NO_UNINITIALIZED_LL)
-	    live_at_end = DF_UPWARD_LIVE_IN (rtl_df, EXIT_BLOCK_PTR);
+	    live_at_end = DF_LR_IN (rtl_df, EXIT_BLOCK_PTR);
 	  else
 	    live_at_end = df_get_live_in (rtl_df, EXIT_BLOCK_PTR);
 	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -3885,8 +3886,7 @@ rest_of_handle_life (void)
 {
   regclass_init ();
   rtl_df = df_init (DF_HARD_REGS);
-  df_lr_add_problem (rtl_df, 0);
-  df_ur_add_problem (rtl_df, 0);
+  df_clrur_add_problem (rtl_df, 0);
 
   life_analysis (PROP_FINAL);
   df_finish (rtl_df);
Index: function.c
===================================================================
--- function.c	(revision 115221)
+++ function.c	(working copy)
@@ -4915,7 +4915,7 @@ keep_stack_depressed (rtx insns)
 		    && !fixed_regs[regno]
 		    && TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)
 		    && !REGNO_REG_SET_P
-		    (DF_UPWARD_LIVE_IN (prologue_epilogue_df, EXIT_BLOCK_PTR), regno)
+		    (DF_LR_IN (prologue_epilogue_df, EXIT_BLOCK_PTR), regno)
 		    && !refers_to_regno_p (regno,
 					   regno + hard_regno_nregs[regno]
 								   [Pmode],
Index: combine.c
===================================================================
--- combine.c	(revision 115221)
+++ combine.c	(working copy)
@@ -1040,8 +1040,8 @@ set_nonzero_bits_and_sign_copies (rtx x,
       && REGNO (x) >= FIRST_PSEUDO_REGISTER
       /* If this register is undefined at the start of the file, we can't
 	 say what its contents were.  */
-      && ! REGNO_REG_SET_P
-         (DF_LIVE_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb), REGNO (x))
+      && REGNO_REG_SET_P
+         (DF_UR_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb), REGNO (x))
       && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
     {
       if (set == 0 || GET_CODE (set) == CLOBBER)
@@ -1066,8 +1066,8 @@ set_nonzero_bits_and_sign_copies (rtx x,
 
       if (insn
 	  && reg_referenced_p (x, PATTERN (insn))
-	  && !REGNO_REG_SET_P (DF_LIVE_IN (rtl_df,
-					   BLOCK_FOR_INSN (insn)),
+	  && !REGNO_REG_SET_P (DF_LR_IN (rtl_df,
+					 BLOCK_FOR_INSN (insn)),
 			       REGNO (x)))
 	{
 	  rtx link;
@@ -8286,9 +8286,8 @@ reg_nonzero_bits_for_combine (rtx x, enu
       && (reg_stat[REGNO (x)].last_set_label == label_tick
 	  || (REGNO (x) >= FIRST_PSEUDO_REGISTER
 	      && REG_N_SETS (REGNO (x)) == 1
-	      && ! REGNO_REG_SET_P
-	      (DF_LIVE_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb),
-		  REGNO (x))))
+	      && REGNO_REG_SET_P
+	      (DF_UR_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb), REGNO (x))))
       && INSN_CUID (reg_stat[REGNO (x)].last_set) < subst_low_cuid)
     {
       *nonzero &= reg_stat[REGNO (x)].last_set_nonzero_bits;
@@ -8354,9 +8353,8 @@ reg_num_sign_bit_copies_for_combine (rtx
       && (reg_stat[REGNO (x)].last_set_label == label_tick
 	  || (REGNO (x) >= FIRST_PSEUDO_REGISTER
 	      && REG_N_SETS (REGNO (x)) == 1
-	      && ! REGNO_REG_SET_P
-	      (DF_LIVE_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb),
-	       REGNO (x))))
+	      && REGNO_REG_SET_P
+	      (DF_UR_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb), REGNO (x))))
       && INSN_CUID (reg_stat[REGNO (x)].last_set) < subst_low_cuid)
     {
       *result = reg_stat[REGNO (x)].last_set_sign_bit_copies;
@@ -11245,9 +11243,8 @@ get_last_value_validate (rtx *loc, rtx i
 	       live at the beginning of the function, it is always valid.  */
 	    || (! (regno >= FIRST_PSEUDO_REGISTER
 		   && REG_N_SETS (regno) == 1
-		   && (! REGNO_REG_SET_P
-		       (DF_LIVE_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb),
-			regno)))
+		   && (REGNO_REG_SET_P
+		       (DF_UR_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb), regno)))
 		&& reg_stat[j].last_set_label > tick))
 	  {
 	    if (replace)
@@ -11356,8 +11353,8 @@ get_last_value (rtx x)
       || (reg_stat[regno].last_set_label != label_tick
 	  && (regno < FIRST_PSEUDO_REGISTER
 	      || REG_N_SETS (regno) != 1
-	      || (REGNO_REG_SET_P
-		  (DF_LIVE_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb), regno)))))
+	      || ! (REGNO_REG_SET_P
+		    (DF_UR_IN (rtl_df, ENTRY_BLOCK_PTR->next_bb), regno)))))
     return 0;
 
   /* If the value was set in a later insn than the ones we are processing,
Index: reg-stack.c
===================================================================
--- reg-stack.c	(revision 115221)
+++ reg-stack.c	(working copy)
@@ -3094,8 +3094,7 @@ reg_to_stack (void)
     return false;
 
   df = df_init (DF_HARD_REGS);
-  df_lr_add_problem (df, 0);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_ri_add_problem (df, 0);
   df_analyze (df);
 
@@ -3121,9 +3120,9 @@ reg_to_stack (void)
       /* Copy live_at_end and live_at_start into temporaries.  */
       for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
 	{
-	  if (REGNO_REG_SET_P (DF_UPWARD_LIVE_OUT (df, bb), reg))
+	  if (REGNO_REG_SET_P (DF_LR_OUT (df, bb), reg))
 	    SET_HARD_REG_BIT (bi->out_reg_set, reg);
-	  if (REGNO_REG_SET_P (DF_UPWARD_LIVE_IN (df, bb), reg))
+	  if (REGNO_REG_SET_P (DF_LR_IN (df, bb), reg))
 	    SET_HARD_REG_BIT (bi->stack_in.reg_set, reg);
 	}
     }
Index: struct-equiv.c
===================================================================
--- struct-equiv.c	(revision 115221)
+++ struct-equiv.c	(working copy)
@@ -993,8 +993,8 @@ struct_equiv_init (int mode, struct equi
 				      (PROP_DEATH_NOTES
 				       | ((mode & CLEANUP_POST_REGSTACK)
 					  ? PROP_POST_REGSTACK : 0)));
-  if (!REG_SET_EQUAL_P (DF_UPWARD_LIVE_OUT (rtl_df, info->x_block),
-			DF_UPWARD_LIVE_OUT (rtl_df, info->y_block)))
+  if (!REG_SET_EQUAL_P (DF_LR_OUT (rtl_df, info->x_block),
+			DF_LR_OUT (rtl_df, info->y_block)))
     {
 #ifdef STACK_REGS
       unsigned rn;
@@ -1007,11 +1007,11 @@ struct_equiv_init (int mode, struct equi
 	 least makes the regsets comparable.  */
       for (rn = FIRST_STACK_REG; rn <= LAST_STACK_REG; rn++)
 	{
-	  CLEAR_REGNO_REG_SET (DF_UPWARD_LIVE_OUT (rtl_df, info->x_block), rn);
-	  CLEAR_REGNO_REG_SET (DF_UPWARD_LIVE_OUT (rtl_df, info->y_block), rn);
+	  CLEAR_REGNO_REG_SET (DF_LR_OUT (rtl_df, info->x_block), rn);
+	  CLEAR_REGNO_REG_SET (DF_LR_OUT (rtl_df, info->y_block), rn);
 	}
-      if (!REG_SET_EQUAL_P (DF_UPWARD_LIVE_OUT (rtl_df, info->x_block),
-			    DF_UPWARD_LIVE_OUT (rtl_df, info->y_block)))
+      if (!REG_SET_EQUAL_P (DF_LR_OUT (rtl_df, info->x_block),
+			    DF_LR_OUT (rtl_df, info->y_block)))
 #endif
 	return false;
     }
@@ -1033,7 +1033,7 @@ struct_equiv_init (int mode, struct equi
   info->common_live = ALLOC_REG_SET (&reg_obstack);
   info->x_local_live = ALLOC_REG_SET (&reg_obstack);
   info->y_local_live = ALLOC_REG_SET (&reg_obstack);
-  COPY_REG_SET (info->common_live, DF_UPWARD_LIVE_OUT (rtl_df, info->x_block));
+  COPY_REG_SET (info->common_live, DF_LR_OUT (rtl_df, info->x_block));
   struct_equiv_make_checkpoint (&info->best_match, info);
   return true;
 }
Index: dce.c
===================================================================
--- dce.c	(revision 115221)
+++ dce.c	(working copy)
@@ -461,7 +461,7 @@ dce_process_block (basic_block bb, bool 
 	(*con_fun_n) (dflow, e);
     }
 
-  bitmap_copy (local_live, DF_UPWARD_LIVE_OUT (dce_df, bb));
+  bitmap_copy (local_live, DF_LR_OUT (dce_df, bb));
 
   /* Process the artificial defs and uses at the bottom of the block.  */
   for (def = df_get_artificial_defs (dce_df, bb_index); 
@@ -562,11 +562,11 @@ dce_process_block (basic_block bb, bool 
       bitmap_set_bit (local_live, DF_REF_REGNO (use));
 #endif
 
-  block_changed = !bitmap_equal_p (local_live, DF_UPWARD_LIVE_IN (dce_df, bb));
+  block_changed = !bitmap_equal_p (local_live, DF_LR_IN (dce_df, bb));
   if (block_changed)
     {
-      BITMAP_FREE (DF_UPWARD_LIVE_IN (dce_df, bb));
-      DF_UPWARD_LIVE_IN (dce_df, bb) = local_live;
+      BITMAP_FREE (DF_LR_IN (dce_df, bb));
+      DF_LR_IN (dce_df, bb) = local_live;
     }
   else
     BITMAP_FREE (local_live);
Index: df.h
===================================================================
--- df.h	(revision 115221)
+++ df.h	(working copy)
@@ -45,9 +45,10 @@ struct df_link;
 #define DF_RD    2      /* Reaching Defs. */
 #define DF_LR    3      /* Live Registers. */
 #define DF_UR    4      /* Uninitialized Registers. */
-#define DF_UREC  5      /* Uninitialized Registers with Early Clobber. */
-#define DF_CHAIN 6      /* Def-Use and/or Use-Def Chains. */
-#define DF_RI    7      /* Register Info. */
+#define DF_CLRUR 5      /* Live Registers & Uninitialized Registers */
+#define DF_UREC  6      /* Uninitialized Registers with Early Clobber. */
+#define DF_CHAIN 7      /* Def-Use and/or Use-Def Chains. */
+#define DF_RI    8      /* Register Info. */
 #define DF_LAST_PROBLEM_PLUS1 (DF_RI + 1)
 
 
@@ -393,12 +394,12 @@ struct df
 #define DF_LR_BB_INFO(DF, BB) (df_lr_get_bb_info((DF)->problems_by_index[DF_LR],(BB)->index))
 #define DF_UR_BB_INFO(DF, BB) (df_ur_get_bb_info((DF)->problems_by_index[DF_UR],(BB)->index))
 #define DF_UREC_BB_INFO(DF, BB) (df_urec_get_bb_info((DF)->problems_by_index[DF_UREC],(BB)->index))
+#define DF_CLRUR_BB_INFO(DF, BB) (df_clrur_get_bb_info((DF)->problems_by_index[DF_CLRUR],(BB)->index))
 
 /* Most transformations that wish to use live register analysis will
-   use these macros.  The DF_UPWARD_LIVE* macros are only half of the
-   solution.  */
-#define DF_LIVE_IN(DF, BB) (DF_UR_BB_INFO(DF, BB)->in) 
-#define DF_LIVE_OUT(DF, BB) (DF_UR_BB_INFO(DF, BB)->out) 
+   use these macros.  This info is the and of the lr and ur sets.  */
+#define DF_LIVE_IN(DF, BB) (DF_CLRUR_BB_INFO(DF, BB)->in) 
+#define DF_LIVE_OUT(DF, BB) (DF_CLRUR_BB_INFO(DF, BB)->out) 
 
 
 /* Live in for register allocation also takes into account several other factors.  */
@@ -408,8 +409,13 @@ struct df
 /* These macros are currently used by only reg-stack since it is not
    tolerant of uninitialized variables.  This intolerance should be
    fixed because it causes other problems.  */ 
-#define DF_UPWARD_LIVE_IN(DF, BB) (DF_LR_BB_INFO(DF, BB)->in) 
-#define DF_UPWARD_LIVE_OUT(DF, BB) (DF_LR_BB_INFO(DF, BB)->out) 
+#define DF_LR_IN(DF, BB) (DF_LR_BB_INFO(DF, BB)->in) 
+#define DF_LR_OUT(DF, BB) (DF_LR_BB_INFO(DF, BB)->out) 
+
+/* These macros are currently used by only combine which needs to know
+   what is really uninitialized.  */ 
+#define DF_UR_IN(DF, BB) (DF_UR_BB_INFO(DF, BB)->in) 
+#define DF_UR_OUT(DF, BB) (DF_UR_BB_INFO(DF, BB)->out) 
 
 
 /* Macros to access the elements within the ref structure.  */
@@ -569,6 +575,15 @@ struct df_ur_bb_info 
   bitmap out;   /* At the bottom of the block.  */
 };
 
+/* Anded results of LR and UR.  */
+struct df_clrur_bb_info 
+{
+  /* The results of the dataflow problem.  */
+  bitmap in;    /* At the top of the block.  */
+  bitmap out;   /* At the bottom of the block.  */
+};
+
+
 /* Uninitialized registers.  All bitmaps are referenced by the register number.  */
 struct df_urec_bb_info 
 {
@@ -649,10 +664,12 @@ extern struct dataflow *df_rd_add_proble
 extern struct df_rd_bb_info *df_rd_get_bb_info (struct dataflow *, unsigned int);
 extern struct dataflow *df_lr_add_problem (struct df *, int);
 extern struct df_lr_bb_info *df_lr_get_bb_info (struct dataflow *, unsigned int);
-extern struct dataflow *df_ur_add_problem (struct df *, int);
 extern void df_lr_simulate_artificial_refs_at_end (struct df *, basic_block, bitmap);
 extern void df_lr_simulate_one_insn (struct df *, basic_block, rtx, bitmap);
+extern struct dataflow *df_ur_add_problem (struct df *, int);
 extern struct df_ur_bb_info *df_ur_get_bb_info (struct dataflow *, unsigned int);
+extern struct dataflow *df_clrur_add_problem (struct df *, int);
+extern struct df_clrur_bb_info *df_clrur_get_bb_info (struct dataflow *, unsigned int);
 extern struct dataflow *df_urec_add_problem (struct df *, int);
 extern struct df_urec_bb_info *df_urec_get_bb_info (struct dataflow *, unsigned int);
 extern struct dataflow *df_chain_add_problem (struct df *, int);
Index: df-core.c
===================================================================
--- df-core.c	(revision 115221)
+++ df-core.c	(working copy)
@@ -1451,8 +1451,7 @@ static unsigned int 
 reset_df (void)
 {
   rtl_df = df_init (DF_HARD_REGS);
-  df_lr_add_problem (rtl_df, 0);
-  df_ur_add_problem (rtl_df, 0);
+  df_clrur_add_problem (rtl_df, 0);
   df_ri_add_problem (rtl_df, DF_RI_LIFE);
   update_life_info (NULL, UPDATE_LIFE_GLOBAL, PROP_LOG_LINKS);
   return 0;
Index: df-problems.c
===================================================================
--- df-problems.c	(revision 115221)
+++ df-problems.c	(working copy)
@@ -152,12 +152,12 @@ df_get_live_in (struct df *df, basic_blo
 {
   gcc_assert (df->problems_by_index[DF_LR]);
 
-  if (df->problems_by_index[DF_UREC])
-    return DF_RA_LIVE_IN (df, bb);
-  else if (df->problems_by_index[DF_UR])
+  if (df->problems_by_index[DF_CLRUR])
     return DF_LIVE_IN (df, bb);
+  else if (df->problems_by_index[DF_UREC])
+    return DF_RA_LIVE_IN (df, bb);
   else 
-    return DF_UPWARD_LIVE_IN (df, bb);
+    return DF_LR_IN (df, bb);
 }
 
 
@@ -169,12 +169,12 @@ df_get_live_out (struct df *df, basic_bl
 {
   gcc_assert (df->problems_by_index[DF_LR]);
 
-  if (df->problems_by_index[DF_UREC])
-    return DF_RA_LIVE_OUT (df, bb);
-  else if (df->problems_by_index[DF_UR])
+  if (df->problems_by_index[DF_CLRUR])
     return DF_LIVE_OUT (df, bb);
+  else if (df->problems_by_index[DF_UREC])
+    return DF_RA_LIVE_OUT (df, bb);
   else 
-    return DF_UPWARD_LIVE_OUT (df, bb);
+    return DF_LR_OUT (df, bb);
 }
 
 
@@ -1759,7 +1759,7 @@ df_lr_simulate_artificial_refs_at_end (s
   struct df_ref *use;
   int bb_index = bb->index;
   
-  bitmap_copy (live, DF_UPWARD_LIVE_OUT (df, bb));
+  bitmap_copy (live, DF_LR_OUT (df, bb));
   for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
     if (((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
 	&& (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))))
@@ -2097,46 +2097,6 @@ df_ur_init (struct dataflow *dflow, bitm
     }
 }
 
-
-/* Or in the stack regs, hard regs and early clobber regs into the the
-   ur_in sets of all of the blocks.  */
-
-static void
-df_ur_local_finalize (struct dataflow *dflow, bitmap all_blocks)
-{
-  struct df *df = dflow->df;
-  struct dataflow *lr_dflow = df->problems_by_index[DF_LR];
-  bitmap tmp = BITMAP_ALLOC (NULL);
-  bitmap_iterator bi;
-  unsigned int bb_index;
-
-  EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
-    {
-      struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb_index);
-      struct df_lr_bb_info *bb_lr_info = df_lr_get_bb_info (lr_dflow, bb_index);
-      
-      /* No register may reach a location where it is not used.  Thus
-	 we trim the rr result to the places where it is used.  */
-      bitmap_and_into (bb_info->in, bb_lr_info->in);
-      bitmap_and_into (bb_info->out, bb_lr_info->out);
-    }
-  
-#if 0
-      /* Hard registers may still stick in the ur_out set, but not
-	 be in the ur_in set, if their only mention was in a call
-	 in this block.  This is because a call kills in the lr
-	 problem but does not kill in the ur problem.  To clean
-	 this up, we execute the transfer function on the lr_in
-	 set and then use that to knock bits out of ur_out.  */
-      bitmap_ior_and_compl (tmp, bb_info->gen, bb_lr_info->in, 
-			    bb_info->kill);
-      bitmap_and_into (bb_info->out, tmp);
-#endif
-
-  BITMAP_FREE (tmp);
-}
-
-
 /* Confluence function that ignores fake edges.  */
 
 static void
@@ -2242,7 +2202,7 @@ static struct df_problem problem_UR =
   NULL,                       /* Confluence operator 0.  */ 
   df_ur_confluence_n,         /* Confluence operator n.  */ 
   df_ur_transfer_function,    /* Transfer function.  */
-  df_ur_local_finalize,       /* Finalize function.  */
+  NULL,                       /* Finalize function.  */
   df_ur_free,                 /* Free all of the problem information.  */
   df_ur_dump,                 /* Debugging.  */
   df_lr_add_problem,          /* Dependent problem.  */
@@ -2261,6 +2221,197 @@ df_ur_add_problem (struct df *df, int fl
 }
 
 
+/* Or in the stack regs, hard regs and early clobber regs into the the
+   ur_in sets of all of the blocks.  */
+
+
+/*----------------------------------------------------------------------------
+   COMBINED LIVE REGISTERS AND UNINITIALIZED REGISTERS.
+
+   The in and out sets here are the anded results of the in and out sets from the 
+   lr and ur problems.
+   ----------------------------------------------------------------------------*/
+
+/* Get basic block info.  */
+
+struct df_clrur_bb_info *
+df_clrur_get_bb_info (struct dataflow *dflow, unsigned int index)
+{
+  gcc_assert (dflow);
+  gcc_assert (index < dflow->block_info_size);
+  return (struct df_clrur_bb_info *) dflow->block_info[index];
+}
+
+
+/* Set basic block info.  */
+
+static void
+df_clrur_set_bb_info (struct dataflow *dflow, unsigned int index, 
+		   struct df_clrur_bb_info *bb_info)
+{
+  gcc_assert (dflow);
+  gcc_assert (index < dflow->block_info_size);
+  dflow->block_info[index] = bb_info;
+}
+
+
+/* Free basic block info.  */
+
+static void
+df_clrur_free_bb_info (struct dataflow *dflow, 
+		    basic_block bb ATTRIBUTE_UNUSED, 
+		    void *vbb_info)
+{
+  struct df_clrur_bb_info *bb_info = (struct df_clrur_bb_info *) vbb_info;
+  if (bb_info)
+    {
+      BITMAP_FREE (bb_info->in);
+      BITMAP_FREE (bb_info->out);
+      pool_free (dflow->block_pool, bb_info);
+    }
+}
+
+
+/* Allocate or reset bitmaps for DFLOW blocks. The solution bits are
+   not touched unless the block is new.  */
+
+static void 
+df_clrur_alloc (struct dataflow *dflow, bitmap blocks_to_rescan,
+	     bitmap all_blocks ATTRIBUTE_UNUSED)
+{
+  unsigned int bb_index;
+  bitmap_iterator bi;
+
+  if (!dflow->block_pool)
+    dflow->block_pool = create_alloc_pool ("df_clrur_block pool", 
+					   sizeof (struct df_clrur_bb_info), 100);
+
+  df_grow_bb_info (dflow);
+
+  EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi)
+    {
+      struct df_clrur_bb_info *bb_info = df_clrur_get_bb_info (dflow, bb_index);
+      if (!bb_info)
+	{ 
+	  bb_info = (struct df_clrur_bb_info *) pool_alloc (dflow->block_pool);
+	  df_clrur_set_bb_info (dflow, bb_index, bb_info);
+	  bb_info->in = BITMAP_ALLOC (NULL);
+	  bb_info->out = BITMAP_ALLOC (NULL);
+	}
+    }
+}
+
+/* And the LR and UR info to produce the CLRUR info.  */
+
+static void
+df_clrur_local_finalize (struct dataflow *dflow, bitmap all_blocks)
+{
+  struct df *df = dflow->df;
+  struct dataflow *lr_dflow = df->problems_by_index[DF_LR];
+  struct dataflow *ur_dflow = df->problems_by_index[DF_UR];
+  bitmap_iterator bi;
+  unsigned int bb_index;
+
+  EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
+    {
+      struct df_ur_bb_info *bb_ur_info = df_ur_get_bb_info (ur_dflow, bb_index);
+      struct df_lr_bb_info *bb_lr_info = df_lr_get_bb_info (lr_dflow, bb_index);
+      struct df_clrur_bb_info *bb_clrur_info = df_clrur_get_bb_info (dflow, bb_index);
+      
+      /* No register may reach a location where it is not used.  Thus
+	 we trim the rr result to the places where it is used.  */
+      bitmap_and (bb_clrur_info->in, bb_ur_info->in, bb_lr_info->in);
+      bitmap_and (bb_clrur_info->out, bb_ur_info->out, bb_lr_info->out);
+    }
+}
+
+/* Free all storage associated with the problem.  */
+
+static void
+df_clrur_free (struct dataflow *dflow)
+{
+  if (dflow->block_info)
+    {
+      unsigned int i;
+      
+      for (i = 0; i < dflow->block_info_size; i++)
+	{
+	  struct df_clrur_bb_info *bb_info = df_clrur_get_bb_info (dflow, i);
+	  if (bb_info)
+	    {
+	      BITMAP_FREE (bb_info->in);
+	      BITMAP_FREE (bb_info->out);
+	    }
+	}
+      
+      free_alloc_pool (dflow->block_pool);
+      dflow->block_info_size = 0;
+      free (dflow->block_info);
+    }
+  free (dflow);
+}
+
+
+/* Debugging info.  */
+
+static void
+df_clrur_dump (struct dataflow *dflow, FILE *file)
+{
+  basic_block bb;
+  
+  if (!dflow->block_info) 
+    return;
+
+  fprintf (file, "Combined live and undefined regs:\n");
+ 
+  FOR_ALL_BB (bb)
+    {
+      struct df_clrur_bb_info *bb_info = df_clrur_get_bb_info (dflow, bb->index);
+      df_print_bb_index (bb, file);
+      
+      if (!bb_info->in)
+	continue;
+      
+      fprintf (file, "  in  \t");
+      dump_bitmap (file, bb_info->in);
+      fprintf (file, "  out \t");
+      dump_bitmap (file, bb_info->out);
+    }
+}
+
+/* All of the information associated with every instance of the problem.  */
+
+static struct df_problem problem_CLRUR =
+{
+  DF_CLRUR,                   /* Problem id.  */
+  DF_NONE,                    /* Direction.  */
+  df_clrur_alloc,             /* Allocate the problem specific data.  */
+  NULL,                       /* Reset global information.  */
+  df_clrur_free_bb_info,      /* Free basic block info.  */
+  NULL,                       /* Local compute function.  */
+  NULL,                       /* Init the solution specific data.  */
+  NULL,                       /* Iterative solver.  */
+  NULL,                       /* Confluence operator 0.  */ 
+  NULL,                       /* Confluence operator n.  */ 
+  NULL,                       /* Transfer function.  */
+  df_clrur_local_finalize,    /* Finalize function.  */
+  df_clrur_free,              /* Free all of the problem information.  */
+  df_clrur_dump,              /* Debugging.  */
+  df_ur_add_problem,          /* Dependent problem.  */
+  0                           /* Changeable flags.  */
+};
+
+
+/* Create a new DATAFLOW instance and add it to an existing instance
+   of DF.  The returned structure is what is used to get at the
+   solution.  */
+
+struct dataflow *
+df_clrur_add_problem (struct df *df, int flags)
+{
+  return df_add_problem (df, &problem_CLRUR, flags);
+}
+
 
 /*----------------------------------------------------------------------------
    UNINITIALIZED REGISTERS WITH EARLYCLOBBER
Index: auto-inc-dec.c
===================================================================
--- auto-inc-dec.c	(revision 115221)
+++ auto-inc-dec.c	(working copy)
@@ -434,7 +434,20 @@ dump_mem_insn (FILE *file)
 	     REGNO (mem_insn.reg0), REGNO (mem_insn.reg1));
 }
 
+
+/* The following three arrays contain pointers to instructions. They
+   are indexed by REGNO.  At any point in the basic block where we are
+   looking these three arrays contain, respectively, the next insn
+   that uses REGNO, the next inc or add insn that uses REGNO and the
+   next insn that sets REGNO.
+
+   The arrays are not cleared when we move from block to block so
+   whenever an insn is retrieved from these arrays, it's block number
+   must be comared with the current block.
+*/
+
 static rtx * reg_next_use = NULL;
+static rtx * reg_next_inc_use = NULL;
 static rtx * reg_next_def = NULL;
 static struct df *df = NULL;
 static struct dataflow *scan_dflow = NULL;
@@ -498,8 +511,8 @@ insert_move_insn_before (rtx next_insn, 
    change to the instruction and is this a profitable change to the
    instruction.  */
 
-static void
-attempt_change (rtx new_addr_pat)
+static bool
+attempt_change (rtx new_addr_pat, rtx inc_reg)
 {
   /* There are four cases: For the two cases that involve an add
      instruction, we are going to have to delete the add and insert a
@@ -515,8 +528,6 @@ attempt_change (rtx new_addr_pat)
   int regno;
   rtx mem = *mem_insn.mem_pat;
   enum machine_mode mode = GET_MODE (mem);
-  rtx inc_reg = NULL; 
-  rtx last_insn = NULL;
   rtx new_mem;
   int old_cost = 0;
   int new_cost = 0;
@@ -527,41 +538,13 @@ attempt_change (rtx new_addr_pat)
   old_cost = rtx_cost (mem, 0) 
     + rtx_cost (PATTERN (inc_insn.insn), 0);
   new_cost = rtx_cost (mem_tmp, 0);
-
-  switch (inc_insn.form)
-    {
-    case FORM_PRE_ADD:
-    case FORM_PRE_INC:
-      inc_reg = mem_insn.reg0;
-      last_insn = mem_insn.insn;
-      break;
-    case FORM_POST_INC:
-      inc_reg = mem_insn.reg0;
-      last_insn = inc_insn.insn;
-      break;
-    case FORM_POST_ADD:
-      inc_reg = inc_insn.reg_res;
-      last_insn = inc_insn.insn;
-      break;
-    case FORM_last:
-      gcc_unreachable ();
-    }
-
-  /* Look to see if the inc register is dead after the memory
-     reference.  If it is do not do the combination.  */
-  if (find_regno_note (last_insn, REG_DEAD, REGNO (inc_reg)))
-    {
-      if (dump_file)
-	fprintf (dump_file, "dead failure\n");
-      return;
-    }
-
+  
   /* The first item of business is to see if this is profitable.  */
   if (old_cost < new_cost)
     {
       if (dump_file)
 	fprintf (dump_file, "cost failure old=%d new=%d\n", old_cost, new_cost);
-      return;
+      return false;
     }
 
   /* Jump thru a lot of hoops to keep the attributes up to date.  We
@@ -574,12 +557,12 @@ attempt_change (rtx new_addr_pat)
     {
       if (dump_file)
 	fprintf (dump_file, "validation failure\n"); 
-      return;
+      return false;
     }
 
   /* From here to the end of the function we are committed to the
      change, i.e. nothing fails.  Generate any necessary movs, move
-     any regnotes, and fix up the reg_next_{use,def}.  */
+     any regnotes, and fix up the reg_next_{use,inc_use,def}.  */
   switch (inc_insn.form)
     {
     case FORM_PRE_ADD:
@@ -594,8 +577,13 @@ attempt_change (rtx new_addr_pat)
       reg_next_use [regno] = mov_insn;
       break;
 
-    case FORM_PRE_INC:
     case FORM_POST_INC:
+      regno = REGNO (inc_insn.reg_res);
+      if (reg_next_use [regno] == reg_next_inc_use[regno])
+	reg_next_inc_use[regno] = NULL;
+
+      /* Fallthru.  */
+    case FORM_PRE_INC:
       move_notes (mem_insn.insn, inc_insn.insn, NULL);
       regno = REGNO (inc_insn.reg_res);
       reg_next_def [regno] = mem_insn.insn;
@@ -619,6 +607,8 @@ attempt_change (rtx new_addr_pat)
 
       regno = REGNO (inc_insn.reg0);
       reg_next_use [regno] = mem_insn.insn;
+      if (reg_next_use [regno] == reg_next_inc_use[regno])
+	reg_next_inc_use[regno] = NULL;
       break;
 
     case FORM_last:
@@ -657,6 +647,7 @@ attempt_change (rtx new_addr_pat)
 
   if (dump_file)
     fprintf (dump_file, "****success\n");
+  return true;
 }
 
 
@@ -666,7 +657,7 @@ attempt_change (rtx new_addr_pat)
    Assuming the form is ok, a prototype new address is built which is
    passed to ATTEMPT_CHANGE for final processing.  */
 
-static void 
+static bool 
 try_merge (void)
 {
   enum gen_form gen_form;
@@ -676,6 +667,38 @@ try_merge (void)
 
   /* The width of the mem being access.  */
   int size = GET_MODE_SIZE (GET_MODE (mem));
+  rtx last_insn = NULL;
+
+  switch (inc_insn.form)
+    {
+    case FORM_PRE_ADD:
+    case FORM_PRE_INC:
+      last_insn = mem_insn.insn;
+      break;
+    case FORM_POST_INC:
+    case FORM_POST_ADD:
+      last_insn = inc_insn.insn;
+      break;
+    case FORM_last:
+      gcc_unreachable ();
+    }
+
+  /* Cannot handle auto inc of the stack.  */
+  if (inc_reg == stack_pointer_rtx)
+    {
+      if (dump_file)
+	fprintf (dump_file, "cannot inc stack %d failure\n", REGNO (inc_reg));
+      return false;
+    }
+
+  /* Look to see if the inc register is dead after the memory
+     reference.  If it is do not do the combination.  */
+  if (find_regno_note (last_insn, REG_DEAD, REGNO (inc_reg)))
+    {
+      if (dump_file)
+	fprintf (dump_file, "dead failure %d\n", REGNO (inc_reg));
+      return false;
+    }
 
   mem_insn.reg1_state = (mem_insn.reg1_is_const) 
     ? set_inc_state (mem_insn.reg1_val, size) : INC_REG;
@@ -690,70 +713,74 @@ try_merge (void)
     {
     default:
     case NOTHING:
-      return;
+      return false;
 
     case SIMPLE_PRE_INC:     /* ++size  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_PRE_INC\n");
-      attempt_change (gen_rtx_PRE_INC (Pmode, inc_reg));
+      return attempt_change (gen_rtx_PRE_INC (Pmode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_POST_INC:    /* size++  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_POST_INC\n");
-      attempt_change (gen_rtx_POST_INC (Pmode, inc_reg));
+      return attempt_change (gen_rtx_POST_INC (Pmode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_PRE_DEC:     /* --size  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_PRE_DEC\n");
-      attempt_change (gen_rtx_PRE_DEC (Pmode, inc_reg));
+      return attempt_change (gen_rtx_PRE_DEC (Pmode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_POST_DEC:    /* size--  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_POST_DEC\n");
-      attempt_change (gen_rtx_POST_DEC (Pmode, inc_reg));
+      return attempt_change (gen_rtx_POST_DEC (Pmode, inc_reg), inc_reg);
       break;
       
     case DISP_PRE:           /* ++con   */
       if (dump_file)
 	fprintf (dump_file, "trying DISP_PRE\n");
-      attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
-					  inc_reg,
-					  gen_rtx_PLUS (Pmode,
-							inc_reg,
-							inc_insn.reg1)));
+      return attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
+						 inc_reg,
+						 gen_rtx_PLUS (Pmode,
+							       inc_reg,
+							       inc_insn.reg1)),
+			     inc_reg);
       break;
       
     case DISP_POST:          /* con++   */
       if (dump_file)
 	fprintf (dump_file, "trying POST_DISP\n");
-      attempt_change (gen_rtx_POST_MODIFY (Pmode,
-					   inc_reg,
-					   gen_rtx_PLUS (Pmode,
-							 inc_reg,
-							 inc_insn.reg1)));
+      return attempt_change (gen_rtx_POST_MODIFY (Pmode,
+						  inc_reg,
+						  gen_rtx_PLUS (Pmode,
+								inc_reg,
+								inc_insn.reg1)),
+			     inc_reg);
       break;
       
     case REG_PRE:            /* ++reg   */
       if (dump_file)
 	fprintf (dump_file, "trying PRE_REG\n");
-      attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
-					  inc_reg,
-					  gen_rtx_PLUS (Pmode,
-							inc_reg,
-							inc_insn.reg1)));
+      return attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
+						 inc_reg,
+						 gen_rtx_PLUS (Pmode,
+							       inc_reg,
+							       inc_insn.reg1)),
+			     inc_reg);
       break;
-	
+      
     case REG_POST:            /* reg++   */
       if (dump_file)
 	fprintf (dump_file, "trying POST_REG\n");
-      attempt_change (gen_rtx_POST_MODIFY (Pmode, 
-					   inc_reg,
-					   gen_rtx_PLUS (Pmode,
-							 inc_reg,
-							 inc_insn.reg1)));
+      return attempt_change (gen_rtx_POST_MODIFY (Pmode, 
+						  inc_reg,
+						  gen_rtx_PLUS (Pmode,
+								inc_reg,
+								inc_insn.reg1)),
+			     inc_reg);
       break;
     }
 }
@@ -822,10 +849,6 @@ parse_add_or_inc (rtx insn, bool before_
   if (!REG_P (SET_DEST (pat)))
     return false;
 
-  /* Cannot handle auto inc of the stack.  */
-  if (SET_DEST (pat) == stack_pointer_rtx)
-    return false;
-
   if ((GET_CODE (SET_SRC (pat)) != PLUS)
       && (GET_CODE (SET_SRC (pat)) != MINUS))
     return false;
@@ -1002,25 +1025,28 @@ find_inc (bool first_try)
 {
   rtx insn;
   basic_block bb = BASIC_BLOCK (BLOCK_NUM (mem_insn.insn));
+  rtx other_insn;
 
   /* Make sure this reg appears only once in this insn.  */
   if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg0, 1) != 1)
     {
       if (dump_file)
-	fprintf (dump_file, "mem count failure"); 
+	fprintf (dump_file, "mem count failure\n"); 
       return;
     }
 
   if (dump_file)
     dump_mem_insn (dump_file);
 
+  /* Find the next use that is an inc.  */
   insn = get_next_ref (REGNO (mem_insn.reg0), 
-			   BASIC_BLOCK (BLOCK_NUM (mem_insn.insn)), 
-			   reg_next_use);
+		       BASIC_BLOCK (BLOCK_NUM (mem_insn.insn)), 
+		       reg_next_inc_use);
   if (!insn)
     return;
 
-  /* Is insn an add or inc?  */
+  /* Even though we know the next use is an add or inc because it came
+     from the reg_next_inc_use, we must still reparse.  */
   if (!parse_add_or_inc (insn, false))
     {
       /* Next use was not an add.  Look for one extra case. It could be
@@ -1060,12 +1086,15 @@ find_inc (bool first_try)
 	{
 	  if (!inc_insn.reg1_is_const)
 	    {
+	      /* The mem looks like *r0 and the rhs of the add has two
+		 registers.  */
 	      int luid = DF_INSN_LUID (df, inc_insn.insn);
-	      rtx other_insn;
 	      if (inc_insn.form == FORM_POST_ADD)
 		{
-		  /* For this trick to be correct, the result reg of the inc
-		     must be a valid addressing reg.  */
+		  /* The trick is that we are not going to increment r0, 
+		     we are going to increment the result of the add insn.
+		     For this trick to be correct, the result reg of
+		     the inc must be a valid addressing reg.  */
 		  if (GET_MODE (inc_insn.reg_res) != Pmode)
 		    {
 		      if (dump_file)
@@ -1073,17 +1102,25 @@ find_inc (bool first_try)
 		      return;
 		    }
 
+		  /* We also need to make sure that the next use of
+		     inc result is after the inc.  */
+		  other_insn 
+		    = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_use);
+		  if (other_insn && luid > DF_INSN_LUID (df, other_insn))
+		    return;
+		  
 		  if (!rtx_equal_p (mem_insn.reg0, inc_insn.reg0))
-		    reverse_inc ();
+		    reverse_inc (); 
 		}
-
+	      
 	      other_insn 
 		= get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
 	      if (other_insn && luid > DF_INSN_LUID (df, other_insn))
 		return;
 	    }
 	}
-      /* Need to check that the constants are ok. */
+      /* Both the inc/add and the mem have a constant.  Need to check
+	 that the constants are ok. */
       else if ((mem_insn.reg1_val != inc_insn.reg1_val)
 	       && (mem_insn.reg1_val != -inc_insn.reg1_val))
 	return;
@@ -1127,6 +1164,8 @@ find_inc (bool first_try)
 		  return;
 		}
 
+	      /* Need to check that there are no assignemnts to b
+		 before the add insn.  */
 	      other_insn 
 		= get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
 	      if (other_insn && luid > DF_INSN_LUID (df, other_insn))
@@ -1159,6 +1198,13 @@ find_inc (bool first_try)
 	      if (other_insn && luid > DF_INSN_LUID (df, other_insn))
 		return;
 	    }
+
+	  /* Need to check that the next use of the add result is later than
+	     add insn since this will be the reg incremented.  */
+	  other_insn 
+	    = get_next_ref (REGNO (inc_insn.reg_res), bb, reg_next_use);
+	  if (other_insn && luid > DF_INSN_LUID (df, other_insn))
+	    return;
 	}
       else /* FORM_POST_INC.  There is less to check here because we
 	      know that operands must line up.  */ 
@@ -1189,6 +1235,19 @@ find_inc (bool first_try)
 	}
     }
 
+  if (inc_insn.form == FORM_POST_INC)
+    {
+      other_insn 
+	= get_next_ref (REGNO (inc_insn.reg0), bb, reg_next_use);
+      /* When we found inc_insn, we were looking for the
+	 next add or inc, not the next insn that used the
+	 reg.  Because we are going to increment the reg
+	 in this form, we need to make sure that there
+	 were no interveining uses of reg.  */
+      if (inc_insn.insn != other_insn)
+	return;
+    }
+
   try_merge ();
 }
 
@@ -1273,6 +1332,7 @@ merge_in_block (basic_block bb)
   FOR_BB_INSNS_REVERSE_SAFE (bb, insn, curr)
     {
       unsigned int uid = INSN_UID (insn);
+      bool insn_is_add_or_inc = false;
 
       if (!INSN_P (insn))
 	continue;	
@@ -1306,44 +1366,56 @@ merge_in_block (basic_block bb)
 		  int luid = DF_INSN_LUID (df, mem_insn.insn);
 		  rtx other_insn 
 		    = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_use);
-
+		  
 		  if (other_insn && luid > DF_INSN_LUID (df, other_insn))
 		    ok = false;
-
+		  
 		  other_insn 
 		    = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
-
+		  
 		  if (other_insn && luid > DF_INSN_LUID (df, other_insn))
 		    ok = false;
 		}
-
+	      
 	      if (dump_file)
 		dump_inc_insn (dump_file);
-
+	      
 	      if (ok && find_address (&PATTERN (mem_insn.insn)) == -1)
 		{
 		  if (dump_file)
 		    dump_mem_insn (dump_file);
-		  try_merge ();
+		  if (!try_merge ())
+		    insn_is_add_or_inc = true;
 		}
+	      else 
+		insn_is_add_or_inc = true;
+	      
 	    }
+	  else 
+	    insn_is_add_or_inc = true;
 	}
       else
 	{
 	  mem_insn.insn = insn;
 	  find_mem (&PATTERN (insn));
 	}
-
+      
       /* Need to update next use.  */
       for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref)
 	{
 	  reg_next_use[DF_REF_REGNO (def)] = NULL;
+	  reg_next_inc_use[DF_REF_REGNO (def)] = NULL;
 	  reg_next_def[DF_REF_REGNO (def)] = insn;
 	}
-
+      
       for (use = DF_INSN_UID_USES (df, uid); use; use = use->next_ref)
-	reg_next_use[DF_REF_REGNO (use)] = insn;
-    }  
+	{
+	  reg_next_use[DF_REF_REGNO (use)] = insn;
+	  reg_next_use[DF_REF_REGNO (use)] = insn;
+	  if (insn_is_add_or_inc)
+	    reg_next_inc_use[DF_REF_REGNO (use)] = insn;
+	}  
+    }
 }
 
 #endif
@@ -1361,21 +1433,24 @@ rest_of_handle_auto_inc_dec (void)
   mem_tmp = gen_rtx_MEM (Pmode, NULL_RTX);
 
   df = df_init (DF_HARD_REGS);
-  df_lr_add_problem (df, 0);
-  df_ur_add_problem (df, 0);
+  df_clrur_add_problem (df, 0);
   df_ri_add_problem (df, 0);
   scan_dflow = df->problems_by_index[DF_SCAN];
   df_analyze (df);
+  if (dump_file)
+    df_dump (df, dump_file);
 
   reg_next_use = XCNEWVEC (rtx, max_reg);
+  reg_next_inc_use = XCNEWVEC (rtx, max_reg);
   reg_next_def = XCNEWVEC (rtx, max_reg);
   FOR_EACH_BB (bb)
     merge_in_block (bb);
 
   free (reg_next_use);
+  free (reg_next_inc_use);
   free (reg_next_def);
 
-  mem_tmp = 0;
+  mem_tmp = NULL;
   df_finish (df);
 #endif
   return 0;

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