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 COMMITTED


This patch is several steps forward and at least one step back. 
Incremental scanning now at least bootstraps for combine and all three
ifcvts on the x86-64.  This patch also makes a lot of progress on the
ia-64.  However we have added some regressions on the x86-64, most
likely due to the changes in regs_ever_live computation.  We will have
our best people working on it, but we are running the risk of having the
west coast and east coast be badly out of sync, so we need to move
forward with this and we will fix the regressions later. 

This patch also adds a new debugging paradigm that was heavily used at
Sun and also on the NaturalBridge compiler (one of the naturalbridge
principles came out of sun). This option allows passes to be stop making
changes after some number (given on the command line) transformations. 
Once it is understood that some pass is creating problems, an
appropriate shell script, can then search to find the Nth transformation
that causes the failure. 

Seongbae can explain this better since he did the implementation here. 
In this patch it is only implemented in dce.  But others will follow as
we need them.

Kenny

2006-11-13  Seongbae Park <seongbae.park@gmail.com>
        Kenneth Zadeck <zadeck@naturalbridge.com>

    * tree-pass.h (TODO_df_verify_scan): New flag.
    * auto-inc-def.c (find_inc): Added code to check for case where
    output of inc is not overwritten by mem to be combined.
    * df-scan.c (df_scan_set_bb_info): Now increases the size of the
    array if necessary.
    (df_scan_blocks): Added flag to avoid recomputing regs_ever_live.
    (df_insn_rescan): Fixed missing case for rescanning.
    (df_insn_refs_collect): Special case for sibling calls.  Changed
    to not set up loc field with address of regno_reg_rtx element.
    (df_entry_block_defs_collect, df_exit_block_uses_collect,
    df_bb_refs_collect): Changed to not set up loc field with address
    of regno_reg_rtx element.
    (df_bb_refs_record): Removed dflow parameter and added scan_insn
    parameter. Changed call to df_bb_refs_record.
    (df_compute_regs_ever_live): New function.
    (df_reg_chain_unmark): Made to accept NULL blocks parameter.
    (df_ref_chain_unmark): New function.
    (df_ref_verify):  Added abort_if_fail parameter.
    (df_insn_refs_verify): Added abort_if_fail and return_refs
    parameter and changed function to return bool.  Added code to
    unmark chains.
    (df_bb_refs_verify): Added abort_if_fail parameter and now returns
    nothing.
    (df_bb_verify): Changed to expect subroutines to abort.
    (df_verify_blocks): Now accepts NULL blocks parameter.
    * ifcvt.c (if_convert): Added more to dump_files.
    * (pass_rtl_ifcvt, pass_if_after_combine, pass_if_after_reload):
    added TODO_df_verify_scan.
    * opts.c (command_handle_option): New flag OPT_fdbg_cnt_
    * recog.c (confirm_change_group): Fixed updating of df scanning.
    * function.c (thread_prologue_and_epilogue_insns):
    Pass DF_NO_REGS_EVER_LIVE in df_init, and
    call df_compute_regs_ever_live after prologue is generated.
        * df.h (enum df_ref_flags): Added DF_REF_ARTIFICIAL.
    (enum df_changeable_flags): Added DF_NO_REGS_EVER_LIVE.
    (DF_REF_IS_ARTIFICIAL): Added checking for the flag DF_REF_ARTIFICIAL.
    * cfgcleanup.c: Fixed typo in comment.
         * common.opt: New flag -fdbg-cnt=
    * combine.c (try_combine): Added calls to keep df_scanning up to
    date.
    (pass_combine): Added TODO_df_verify_scan.
    * Makefile.in: New gcc object file dbgcnt.o
    * passes.c (execute_todo): Added support for TODO_df_verify_scan.
    * config/ia64/ia64.c (ia64_split_return_addr_rtx): Finalize
    the frame layout early.
    (ia64_expand_prologue): Pass DF_NO_REGS_EVER_LIVE to df_init().
    * cfgrtl.c (rtl_delete_block, rtl_merge_blocks,
    cfg_layout_merge_blocks): Added debugging.
    * dbgcnt.c, dbgcnt.h: New files
    * dce.c (delete_unmarked_insns): Use dbg_cnt.

Index: ChangeLog.dataflow
===================================================================
--- ChangeLog.dataflow	(revision 118663)
+++ ChangeLog.dataflow	(working copy)
@@ -1,3 +1,36 @@
+2006-11-13  Seongbae Park <seongbae.park@gmail.com>
+	    Kenneth Zadeck <zadeck@naturalbridge.com>
+
+	* tree-pass.h (TODO_df_verify_scan): New flag.
+	* auto-inc-def.c (find_inc): Added code to check for case where
+	output of inc is not overwritten by mem to be combined.
+        * df.h (enum df_ref_flags): Added DF_REF_ARTIFICIAL.
+	(enum df_changeable_flags): Added DF_NO_REGS_EVER_LIVE.
+	(DF_REF_IS_ARTIFICIAL): Added checking for the flag DF_REF_ARTIFICIAL.
+	* df-scan.c (df_scan_set_bb_info): Now increases the size of the
+	array if necessary. 
+	(df_scan_blocks): Added flag to avoid recomputing regs_ever_live.
+	(df_insn_rescan): Fixed missing case for rescanning.
+	(df_insn_refs_collect): Special case for sibling calls.  Changed
+	to not set up loc field with address of regno_reg_rtx element.
+	(df_entry_block_defs_collect, df_exit_block_uses_collect,
+	df_bb_refs_collect): Changed to not set up loc field with address 
+	of regno_reg_rtx element.
+	(df_bb_refs_record): Removed dflow parameter and added scan_insn 
+	parameter.
+	(df_compute_regs_ever_live): New function.
+	* common.opt: New flag -fdbg-cnt=
+	* opts.c (command_handle_option): New flag OPT_fdbg_cnt_
+	* dbgcnt.c, dbgcnt.h: New files
+	* function.c (thread_prologue_and_epilogue_insns):
+	Pass DF_NO_REGS_EVER_LIVE in df_init, and
+	call df_compute_regs_eveR_live after prologue is generated.
+	* Makefile.in: New gcc object file dbgcnt.o
+	* config/ia64/ia64.c (ia64_split_return_addr_rtx): Finalize
+	the frame layout early.
+	(ia64_expand_prologue): Pass DF_NO_REGS_EVER_LIVE to df_init().
+	* dce.c (delete_unmarked_insns): Use dbg_cnt. 
+
 2006-11-10  Seongbae Park <seongbae.park@gmail.com>
 
 	* fwprop.c (forward_propagate_into): Use DF_REF_IS_ARTIFICIAL()
Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 118663)
+++ tree-pass.h	(working copy)
@@ -222,6 +222,10 @@ struct dump_file_info
    the instance before it is destroyed.  */
 #define TODO_df_finish                  (1 << 15)
 
+/* Verify that all the incremental scanning of the df infomation is
+   correct.  */
+#define TODO_df_verify_scan             (1 << 16)
+
 #define TODO_update_ssa_any		\
     (TODO_update_ssa			\
      | TODO_update_ssa_no_phi		\
Index: auto-inc-dec.c
===================================================================
--- auto-inc-dec.c	(revision 118663)
+++ auto-inc-dec.c	(working copy)
@@ -1014,6 +1014,7 @@ find_inc (bool first_try)
   rtx insn;
   basic_block bb = BASIC_BLOCK (BLOCK_NUM (mem_insn.insn));
   rtx other_insn;
+  struct df_ref *def;
 
   /* Make sure this reg appears only once in this insn.  */
   if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg0, 1) != 1)
@@ -1055,6 +1056,18 @@ find_inc (bool first_try)
 	return false;
     }
 
+  /* Need to assure that none of the operands of the inc instruction are 
+     assigned to by the mem insn.  */
+  for (def = DF_INSN_DEFS (df, mem_insn.insn); def; def = def->next_ref)
+    {
+      unsigned int regno = DF_REF_REGNO (def);
+      if ((regno == REGNO (inc_insn.reg0)) 
+	  || (regno == REGNO (inc_insn.reg_res)))
+	return false;
+      if (!inc_insn.reg1_is_const && (regno == REGNO (inc_insn.reg1)))
+	return false;
+    }
+
   if (dump_file)
     dump_inc_insn (dump_file);
 
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 118663)
+++ df-scan.c	(working copy)
@@ -98,7 +98,6 @@ static struct df_ref * df_uses_record (s
                                        rtx *, enum df_ref_type,
 			               basic_block, rtx, enum df_ref_flags);
 
-static void df_bb_refs_record (struct dataflow *, basic_block);
 static void df_refs_record (struct dataflow *, bitmap);
 static struct df_ref *df_ref_create_structure (struct dataflow *, rtx, rtx *, 
 					       basic_block, rtx, enum df_ref_type, 
@@ -134,10 +133,13 @@ static void df_ref_add_to_chains (struct
                                   struct df_mw_hardreg *);
 static void df_refs_add_to_chains (struct dataflow *, rtx insn, struct df_ref *);
 
-static struct df_ref * df_insn_refs_verify (struct dataflow *, 
-                                            struct df_reg_chains *,
-                                            basic_block, 
-                                            rtx);
+static bool df_insn_refs_verify (struct dataflow *, 
+				 struct df_reg_chains *,
+				 basic_block, 
+				 rtx,
+				 struct df_ref **,
+				 bool);
+static struct df_ref * df_exit_block_uses_collect (struct dataflow *);
 
 #define DEBUG_DF_RESCAN
 #ifdef DEBUG_DF_RESCAN
@@ -239,7 +241,7 @@ df_scan_set_bb_info (struct dataflow *df
 		     struct df_scan_bb_info *bb_info)
 {
   gcc_assert (dflow);
-  gcc_assert (index < dflow->block_info_size);
+  df_grow_bb_info (dflow);
   dflow->block_info[index] = (void *) bb_info;
 }
 
@@ -583,7 +585,8 @@ df_scan_blocks (struct df *df)
 
   BITMAP_FREE (local_blocks_to_scan);
 
-  df_compute_regs_ever_live (df, regs_ever_live);
+  if ((df->changeable_flags & DF_NO_REGS_EVER_LIVE) == 0)
+    df_compute_regs_ever_live (df, regs_ever_live);
 }
 
 
@@ -960,16 +963,24 @@ df_insn_rescan (rtx insn)
 
   if (insn_info)
     {
-      refs = df_insn_refs_verify (dflow, NULL, bb, insn);
+      bool the_same = df_insn_refs_verify (dflow, NULL, bb, insn, &refs, false);
       /* If there's no change, return false. */
-      if (refs == NULL)
-	return false;
+      if (the_same)
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "verify found no changes in insn with uid = %d.\n", uid);
+	  return false;
+	}
 
-      /* There's change We need to delete the existing info. */
+      /* There's change - we need to delete the existing info. */
       df_insn_delete (insn);
+      df_insn_create_insn_record (dflow, insn);
+    }
+  else
+    {
+      df_insn_create_insn_record (dflow, insn);
+      df_insn_refs_verify (dflow, NULL, bb, insn, &refs, false);
     }
-
-  df_insn_create_insn_record (dflow, insn);
 
   df_insn_refs_record (dflow, insn, refs); 
 
@@ -1165,7 +1176,6 @@ df_ref_is_pointer_equal (struct df_ref *
   return ref1 == ref2;
 }
 
-
 /* Return true if the first ref should be recorded in regs_ever_live .  */
 
 static bool
@@ -1903,6 +1913,7 @@ df_insn_refs_collect (struct dataflow *d
       rtx note;
       bitmap_iterator bi;
       unsigned int ui;
+      bool is_sibling_call;
 
       /* Record the registers used to pass arguments, and explicitly
          noted as clobbered.  */
@@ -1920,23 +1931,53 @@ df_insn_refs_collect (struct dataflow *d
         }
 
       /* The stack ptr is used (honorarily) by a CALL insn.  */
-      insn_refs = df_uses_record (dflow, insn_refs,
-                                  &regno_reg_rtx[STACK_POINTER_REGNUM],
-                                  DF_REF_REG_USE, bb, insn, 
-                                  DF_REF_CALL_STACK_USAGE);
+      insn_refs = df_ref_record (dflow, insn_refs,
+				 regno_reg_rtx[STACK_POINTER_REGNUM], NULL,
+				 bb, insn, DF_REF_REG_USE,
+				 DF_REF_CALL_STACK_USAGE);
 
       /* Calls may also reference any of the global registers,
          so they are recorded as used.  */
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
         if (global_regs[i])
-          insn_refs = df_uses_record (dflow, insn_refs,
-                                      &regno_reg_rtx[i],
-                                      DF_REF_REG_USE, bb, insn, 0);
+          insn_refs = df_ref_record (dflow, insn_refs,
+				     regno_reg_rtx[i], NULL,
+				     bb, insn, DF_REF_REG_USE, 0);
+
+      is_sibling_call = SIBLING_CALL_P (insn);
       EXECUTE_IF_SET_IN_BITMAP (df_invalidated_by_call, 0, ui, bi)
-        insn_refs = df_ref_record (dflow, insn_refs,
-                                   regno_reg_rtx[ui], &regno_reg_rtx[ui], 
-                                   bb, insn, DF_REF_REG_DEF, 
-                                   DF_REF_MAY_CLOBBER);
+        {
+          if (!is_sibling_call
+              || !bitmap_bit_p (dflow->df->exit_block_uses, ui)
+              || refers_to_regno_p (ui, ui+1, 
+                                    current_function_return_rtx, NULL))
+            insn_refs = df_ref_record (dflow, insn_refs,
+                                       regno_reg_rtx[ui], NULL, 
+                                       bb, insn, DF_REF_REG_DEF, 
+                                       DF_REF_MAY_CLOBBER);
+        }
+#if 0
+      if (SIBLING_CALL_P (insn))
+        {
+          struct df_ref *extra_refs = df_exit_block_uses_collect (dflow);
+          struct df_ref *ref;
+
+          /* Attach extra_refs at the end of insn_refs.  */
+          DF_REF_NEXT_REF (insn_refs) = extra_refs;
+
+          for (ref = extra_refs; ref; ref = DF_REF_NEXT_REF (ref))
+            {
+              /* This has implication on regs_ever_live marking,
+                 because what used to be only artificial uses are 
+                 now non-artificial uses. */
+              DF_REF_BB (ref) = bb;
+              DF_REF_INSN (ref) = insn;
+              DF_REF_FLAGS_SET (ref, DF_REF_ARTIFICIAL);
+              insn_refs = ref;
+            }
+          /* insn_refs now points to the last ref in the ref chain. */
+        }
+#endif
     }
 
   /* Record the register uses.  */
@@ -2151,7 +2192,7 @@ df_entry_block_defs_collect (struct data
   EXECUTE_IF_SET_IN_BITMAP (df->entry_block_defs, 0, i, bi)
     {
       bb_refs = df_ref_record (dflow, bb_refs, 
-                               regno_reg_rtx[i], &regno_reg_rtx[i], 
+                               regno_reg_rtx[i], NULL, 
                                ENTRY_BLOCK_PTR, NULL, 
                                DF_REF_REG_DEF, 0);
     }
@@ -2175,9 +2216,9 @@ df_exit_block_uses_collect (struct dataf
   DF_REF_NEXT_REF (bb_refs) = NULL;
 
   EXECUTE_IF_SET_IN_BITMAP (df->exit_block_uses, 0, i, bi)
-    bb_refs = df_uses_record (dflow, bb_refs, &regno_reg_rtx[i], 
-                              DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL,
-                              0);
+    bb_refs = df_ref_record (dflow, bb_refs, regno_reg_rtx[i], NULL,
+			     EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE,
+			     0);
 
 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
   /* It is deliberate that this is not put in the exit block uses but
@@ -2185,10 +2226,10 @@ df_exit_block_uses_collect (struct dataf
   if (reload_completed 
       && df_has_eh_preds (EXIT_BLOCK_PTR)
       && fixed_regs[ARG_POINTER_REGNUM])
-    bb_refs = df_uses_record (dflow, bb_refs,
-                              &regno_reg_rtx[ARG_POINTER_REGNUM], 
-                              DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL,
-                              0);
+    bb_refs = df_ref_record (dflow, bb_refs,
+			     regno_reg_rtx[ARG_POINTER_REGNUM], NULL,
+			     EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, 
+			     0);
 #endif
 
   return DF_REF_NEXT_REF (&dummy);
@@ -2223,7 +2264,7 @@ df_bb_refs_collect (struct dataflow *dfl
 	  if (regno == INVALID_REGNUM)
 	    break;
 	  bb_refs = df_ref_record (dflow, bb_refs,
-                                   regno_reg_rtx[regno], &regno_reg_rtx[regno],
+                                   regno_reg_rtx[regno], NULL,
 			           bb, NULL,
 			           DF_REF_REG_DEF, DF_REF_AT_TOP);
 	}
@@ -2248,10 +2289,10 @@ df_bb_refs_collect (struct dataflow *dfl
          eh-receiver for all of the edges at once. */
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
 	if (EH_USES (i))
-	  bb_refs = df_uses_record (dflow, bb_refs,
-                                    &regno_reg_rtx[i], 
-			            DF_REF_REG_USE, bb, NULL,
-			            DF_REF_AT_TOP);
+	  bb_refs = df_ref_record (dflow, bb_refs,
+				   regno_reg_rtx[i], NULL,
+				   bb, NULL, DF_REF_REG_USE, 
+				   DF_REF_AT_TOP);
     }
 #endif
 
@@ -2265,9 +2306,9 @@ df_bb_refs_collect (struct dataflow *dfl
 
       EXECUTE_IF_SET_IN_BITMAP (au, 0, regno, bi)
 	{
-	  bb_refs = df_uses_record (dflow, bb_refs,
-                                    &regno_reg_rtx[regno],
-                                    DF_REF_REG_USE, bb, NULL, 0);
+	  bb_refs = df_ref_record (dflow, bb_refs,
+				   regno_reg_rtx[regno], NULL,
+				   bb, NULL, DF_REF_REG_USE, 0);
 	}
     }
 
@@ -2275,39 +2316,48 @@ df_bb_refs_collect (struct dataflow *dfl
 }
 
 
-/* Record all the refs within the basic block BB.  */
+/* Record all the refs within the basic block BB_INDEX and scan the instructions if SCAN_INSNS.  */
 
-static void
-df_bb_refs_record (struct dataflow *dflow, basic_block bb)
+void
+df_bb_refs_record (int bb_index, bool scan_insns)
 {
-  struct df *df = dflow->df;
+  struct df *df = df_current_instance;
+  basic_block bb = BASIC_BLOCK (bb_index);
   rtx insn;
   int luid = 0;
-  struct df_scan_bb_info *bb_info = df_scan_get_bb_info (dflow, bb->index);
   struct df_ref *bb_refs;
+  struct dataflow *dflow;
+  struct df_scan_bb_info *bb_info;
+
+  if (!df)
+    return;
+
+  dflow = df->problems_by_index[DF_SCAN];
+  bb_info = df_scan_get_bb_info (dflow, bb_index);
 
   /* Need to make sure that there is a record in the basic block info. */  
   if (!bb_info)
     {
       bb_info = (struct df_scan_bb_info *) pool_alloc (dflow->block_pool);
-      df_scan_set_bb_info (dflow, bb->index, bb_info);
+      df_scan_set_bb_info (dflow, bb_index, bb_info);
       bb_info->artificial_defs = NULL;
       bb_info->artificial_uses = NULL;
     }
 
-  /* Scan the block an insn at a time from beginning to end.  */
-  FOR_BB_INSNS (bb, insn)
-    {
-      df_insn_create_insn_record (dflow, insn);
-      if (INSN_P (insn))
-	{
-	  /* Record refs within INSN.  */
-	  DF_INSN_LUID (df, insn) = luid++;
-	  df_insn_refs_record (dflow, insn, 
-                               df_insn_refs_collect (dflow, bb, insn));
-	}
-      DF_INSN_LUID (df, insn) = luid;
-    }
+  if (scan_insns)
+    /* Scan the block an insn at a time from beginning to end.  */
+    FOR_BB_INSNS (bb, insn)
+      {
+	df_insn_create_insn_record (dflow, insn);
+	if (INSN_P (insn))
+	  {
+	    /* Record refs within INSN.  */
+	    DF_INSN_LUID (df, insn) = luid++;
+	    df_insn_refs_record (dflow, insn, 
+				 df_insn_refs_collect (dflow, bb, insn));
+	  }
+	DF_INSN_LUID (df, insn) = luid;
+      }
 
   /* Other block level artificial refs */
   bb_refs = df_bb_refs_collect (dflow, bb);
@@ -2411,8 +2461,7 @@ df_refs_record (struct dataflow *dflow, 
   /* Regular blocks */
   EXECUTE_IF_SET_IN_BITMAP (blocks, 0, bb_index, bi)
     {
-      basic_block bb = BASIC_BLOCK (bb_index);
-      df_bb_refs_record (dflow, bb);
+      df_bb_refs_record (bb_index, true);
     }
 
 #if 0
@@ -2463,7 +2512,6 @@ df_record_entry_block_defs (struct dataf
   df_refs_add_to_chains (dflow, NULL, refs);
 }
 
-
 /* Set the bit for regs that are considered being used at the exit. */
 
 static void
@@ -2650,16 +2698,16 @@ df_compute_regs_ever_live (struct df *df
   Dataflow ref information verification functions.
 
 
-  df_ref_verify (dflow, ref)
+  df_ref_verify (dflow, reg_chains, ref, hardreg, bool)
   df_ref_chain_mark_duplicate (src_refs, dest_refs)
   df_ref_chain_unmark (refs)
   df_ref_chain_free (refs)
-  df_insn_refs_verify (dflow, bb, insn)
-  df_bb_refs_verify (dflow, bb, refs)
-  df_bb_verify (dflow, bb)
+  df_insn_refs_verify (dflow, reg_chains, bb, insn, refs, bool)
+  df_bb_refs_verify (dflow, reg_chains, bb, refs, bool)
+  df_bb_verify (dflow, bb, bool)
   df_exit_block_verify (dflow)
   df_entry_block_verify (dflow)
-  df_verify_blocks (dflow)
+  df_verify_blocks (dflow, blocks)
 ----------------------------------------------------------------------------*/
 
 
@@ -2673,16 +2721,36 @@ df_reg_chain_unmark (struct df_ref *refs
   struct df_ref *ref;
   for (ref = refs; ref; ref = DF_REF_NEXT_REG (ref))
     {
-      gcc_assert (!bitmap_bit_p (blocks, DF_REF_BB (ref)->index) 
+      if (blocks)
+	gcc_assert (!bitmap_bit_p (blocks, DF_REF_BB (ref)->index) 
                     || DF_REF_IS_MARKED (ref));
+      else 
+	gcc_assert (DF_REF_IS_MARKED (ref));
+
       DF_REF_UNMARK (ref);
     }
   return true;
 }
 
 
-/* Free all refs inthe chain.  */
+/* Unmark all refs in the ref chain 
+   and return true if all refs are DF_REF_IS_MARKED. */
 
+static bool
+df_ref_chain_unmark (struct df_ref *refs)
+{
+  struct df_ref *ref;
+  bool ret = true;
+  for (ref = refs; ref; ref = DF_REF_NEXT_REF (ref))
+    {
+      ret = ret && DF_REF_IS_MARKED (ref);
+      DF_REF_UNMARK (ref);
+    }
+  return ret;
+}
+
+
+/* Free all refs inthe chain.  */
 static void
 df_ref_chain_free (struct dataflow *dflow, struct df_ref *ref)
 {
@@ -2700,13 +2768,15 @@ df_ref_chain_free (struct dataflow *dflo
 
 /* Find the matching identical ref in the existing ref chain,
    and return it if it is in various other chains/places that 
-   it's supposed to be in. Otherwise return NULL.   */
+   it's supposed to be in. Otherwise return NULL.
+   Mark the original ref with DF_REF_MARK() if it was found. */
 
 static struct df_ref *
 df_ref_verify (struct dataflow *dflow,
                struct df_reg_chains *reg_chains,
                struct df_ref *this_ref,
-               struct df_mw_hardreg *hardreg)
+               struct df_mw_hardreg *hardreg,
+	       bool abort_if_fail)
 {
   struct df_chains chains = df_ref_find_chains (dflow, this_ref);
   struct df_ref **ref_chain = chains.ref_chain;
@@ -2717,8 +2787,13 @@ df_ref_verify (struct dataflow *dflow,
 
   /* Verify the ref chain.  */
   old_ref = df_ref_chain_find_ref (*ref_chain, this_ref, df_ref_is_equal);
-  if (!old_ref) 
-    return NULL;
+  if (!old_ref)
+    {
+      if (abort_if_fail)
+	gcc_assert (0);
+      else
+	return NULL;
+    }
 
   /* collected ref chain may contain duplicate entries,
      in which case the reference is already verified. */
@@ -2742,7 +2817,6 @@ df_ref_verify (struct dataflow *dflow,
                                        old_ref, df_ref_is_pointer_equal);
       if (old_ref)
         {
-          DF_REF_MARK (old_ref);
           while (*reg_chain && DF_REF_IS_MARKED (*reg_chain))
             *reg_chain = DF_REF_NEXT_REG (*reg_chain);
         }
@@ -2752,13 +2826,25 @@ df_ref_verify (struct dataflow *dflow,
                                        old_ref, df_ref_is_pointer_equal);
 
   if (!old_ref) 
-    return NULL;
+    {
+      if (abort_if_fail)
+	gcc_assert (0);
+      else
+	return NULL;
+    }
+
+  DF_REF_MARK (old_ref);
 
   /* Verify ref_info->refs array.  */
   if (ref_info->add_refs_inline
       && (DF_REF_ID (old_ref) >= ref_info->refs_size
           || ref_info->refs[DF_REF_ID (old_ref)] != old_ref))
-    return NULL;
+    {
+      if (abort_if_fail)
+	gcc_assert (0);
+      else
+	return NULL;
+    }
 
   /* mw_hardreg has to be in the hardreg chain as well. */
   if (DF_REF_INSN (this_ref) && DF_REF_FLAGS_IS_SET (this_ref, DF_REF_MW_HARDREG))
@@ -2772,24 +2858,36 @@ df_ref_verify (struct dataflow *dflow,
           break;
 
       if (link == NULL)
-        return NULL;
+	{
+	  if (abort_if_fail)
+	    gcc_assert (0);
+	  else
+	    return NULL;
+	}
     }
 
   return old_ref;
 }
 
 
-/* Return NULL if the existing insn refs information is complete and correct. 
-   Otherwise (i.e. if there's any missing or extra refs), return
-   the correct df_ref chain.
-   If REG_CHAINS is not null, mark the refs that are verified
-   (already in the ref chain).  */
+/* Return true if the existing insn refs information is complete and
+   correct. Otherwise (i.e. if there's any missing or extra refs),
+   return the correct df_ref chain in REFS_RETURN.  
+
+   If REG_CHAINS is not null, leave the refs that are verified
+   (already in the ref chain) as DF_REF_MARKED(). If it's NULL, then
+   it's a per-insn verification mode instead of the whole function, so
+   unmark everything. 
 
-static struct df_ref *
+   If ABORT_IF_FAIL is set, this function never returns false.  */
+
+static bool
 df_insn_refs_verify (struct dataflow *dflow, 
                      struct df_reg_chains *reg_chains,
                      basic_block bb, 
-                     rtx insn)
+                     rtx insn,
+		     struct df_ref **refs_return,
+		     bool abort_if_fail)
 {
   struct df *df = dflow->df;
   struct df_ref *refs = df_insn_refs_collect (dflow, bb, insn);
@@ -2810,19 +2908,50 @@ df_insn_refs_verify (struct dataflow *df
                   && hardreg->mw_reg == DF_REF_REG (ref))
                 break;
             }
-          if (hardreg == NULL) 
-            return refs;
+          if (hardreg == NULL)
+	    {
+	      if (abort_if_fail)
+		gcc_assert (0);
+	      else 
+		{
+		  *refs_return = refs;
+		  return false;
+		}
+	    }
         }
       else 
         {
-          struct df_ref *oref = df_ref_verify (dflow, reg_chains, ref, hardreg);
+          struct df_ref *oref = df_ref_verify (dflow, reg_chains, ref, hardreg, abort_if_fail);
           if (oref == NULL)
-            return refs;
+	    {
+	      *refs_return = refs;
+	      return false;
+	    }
         }
     }
 
+  if (reg_chains == NULL)
+    {
+      bool ret1, ret2, ret3;
+      ret1 = df_ref_chain_unmark (DF_INSN_DEFS (df, insn));
+      ret2 = df_ref_chain_unmark (DF_INSN_USES (df, insn));
+      ret3 = df_ref_chain_unmark (DF_INSN_EQ_USES (df, insn));
+
+      if (!ret1 || !ret2 || !ret3)
+	{
+	  if (abort_if_fail)
+	    gcc_assert (0);
+	  else 
+	    {
+	      *refs_return = refs;
+	      return false;
+	    }
+	}
+    }
+
+  *refs_return = NULL;
   df_ref_chain_free (dflow, refs);
-  return NULL;
+  return true;
 }
 
 
@@ -2832,23 +2961,20 @@ df_insn_refs_verify (struct dataflow *df
    The returned ref chain may have partially MARKed refs 
    - it's the caller's responsibility to clean up the marking.  */
 
-static struct df_ref *
+static void
 df_bb_refs_verify (struct dataflow *dflow, 
                    struct df_reg_chains *reg_chains,
-                   basic_block bb)
+                   basic_block bb,
+		   bool abort_if_fail)
 {
   struct df_ref *refs = df_bb_refs_collect (dflow, bb);
   struct df_ref *ref;
 
   for (ref = refs; ref; ref = DF_REF_NEXT_REF (ref))
-    {
-      struct df_ref *oref = df_ref_verify (dflow, reg_chains, ref, NULL);
-      if (oref == NULL)
-        return refs;
-    }
+    df_ref_verify (dflow, reg_chains, ref, NULL, abort_if_fail);
 
   df_ref_chain_free (dflow, refs);
-  return NULL;
+  return;
 }
 
 
@@ -2859,7 +2985,8 @@ df_bb_refs_verify (struct dataflow *dflo
 static bool
 df_bb_verify (struct dataflow *dflow, 
               struct df_reg_chains *reg_chains,
-              basic_block bb)
+              basic_block bb,
+	      bool abort_if_fail)
 {
   rtx insn;
   struct df_scan_bb_info *bb_info = df_scan_get_bb_info (dflow, bb->index);
@@ -2872,15 +2999,11 @@ df_bb_verify (struct dataflow *dflow, 
     {
       if (!INSN_P (insn))
         continue;
-      refs = df_insn_refs_verify (dflow, reg_chains, bb, insn);
-
-      gcc_assert (refs == NULL);
+      if (!df_insn_refs_verify (dflow, reg_chains, bb, insn, &refs, abort_if_fail))
+	return false;
     }
 
-  refs = df_bb_refs_verify (dflow, reg_chains, bb);
-  /* If we find any difference, free the chain and return false.  */
-  gcc_assert (refs == NULL);
-
+  df_bb_refs_verify (dflow, reg_chains, bb, abort_if_fail);
   return true;
 }
 
@@ -2927,8 +3050,9 @@ df_entry_block_bitmap_verify (struct dat
 }
 
 
-/* Return true if df_ref information for all insns 
-   in all blocks are correct and complete.  */
+/* Return true if df_ref information for all insns in all BLOCKS are
+   correct and complete.  If BLOCKS is null, all blocks are
+   checked.  */
 
 bool
 df_verify_blocks (struct dataflow *dflow, bitmap blocks)
@@ -2956,11 +3080,11 @@ df_verify_blocks (struct dataflow *dflow
   gcc_assert (is_eq);
 
   /* Verify entry block. */
-  if (bitmap_bit_p (blocks, ENTRY_BLOCK))
+  if (!blocks || bitmap_bit_p (blocks, ENTRY_BLOCK))
     gcc_assert (df_entry_block_bitmap_verify (dflow));
 
   /* Verify exit block. */
-  if (bitmap_bit_p (blocks, EXIT_BLOCK))
+  if (!blocks || bitmap_bit_p (blocks, EXIT_BLOCK))
     gcc_assert (df_exit_block_bitmap_verify (dflow));
 
 
@@ -3011,8 +3135,12 @@ df_verify_blocks (struct dataflow *dflow
   bb_index = last_basic_block_for_function (cfun) - 1;
   do
     {
-      if (bitmap_bit_p (blocks, bb_index))
-        gcc_assert (df_bb_verify (dflow, &reg_chains, BASIC_BLOCK (bb_index)));
+      if (BASIC_BLOCK (bb_index))
+	gcc_assert ((unsigned)BASIC_BLOCK (bb_index)->index == bb_index);
+
+      if (BASIC_BLOCK (bb_index) 
+	  && (!blocks || bitmap_bit_p (blocks, bb_index)))
+        df_bb_verify (dflow, &reg_chains, BASIC_BLOCK (bb_index), true);
     }
   while (bb_index-- > 0);
 
Index: ifcvt.c
===================================================================
--- ifcvt.c	(revision 118663)
+++ ifcvt.c	(working copy)
@@ -69,6 +69,8 @@
 #define MAX_CONDITIONAL_EXECUTE   (BRANCH_COST + 1)
 #endif
 
+#define IFCVT_MULTIPLE_DUMPS 1
+
 #define NULL_BLOCK	((basic_block) NULL)
 
 /* # of IF-THEN or IF-THEN-ELSE blocks we looked at  */
@@ -3860,10 +3862,14 @@ if_convert (void)
 	  || !targetm.have_named_sections))
     {
       struct loops loops;
+      if (dump_file)
+	fprintf (dump_file, "starting loop analysis.\n");
       flow_loops_find (&loops);
       mark_loop_exit_edges (&loops);
       flow_loops_free (&loops);
       free_dominance_info (CDI_DOMINATORS);
+      if (dump_file)
+	fprintf (dump_file, "ending loop analysis.\n");
     }
 
   /* Compute postdominators if we think we'll use them.  */
@@ -3981,7 +3987,7 @@ struct tree_opt_pass pass_rtl_ifcvt =
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_df_finish |
-  TODO_verify_flow |
+  TODO_df_verify_scan |
   TODO_dump_func,                       /* todo_flags_finish */
   'C'                                   /* letter */
 };
@@ -4019,7 +4025,7 @@ struct tree_opt_pass pass_if_after_combi
   0,                                    /* todo_flags_start */
   TODO_df_finish |
   TODO_dump_func |
-  TODO_verify_flow |
+  TODO_df_verify_scan |
   TODO_ggc_collect,                     /* todo_flags_finish */
   'C'                                   /* letter */
 };
@@ -4055,7 +4061,7 @@ struct tree_opt_pass pass_if_after_reloa
   0,                                    /* todo_flags_start */
   TODO_df_finish |
   TODO_dump_func |
-  TODO_verify_flow |
+  TODO_df_verify_scan |
   TODO_ggc_collect,                     /* todo_flags_finish */
   'E'                                   /* letter */
 };
Index: opts.c
===================================================================
--- opts.c	(revision 118663)
+++ opts.c	(working copy)
@@ -39,6 +39,7 @@ Software Foundation, 51 Franklin Street,
 #include "insn-attr.h"		/* For INSN_SCHEDULING.  */
 #include "target.h"
 #include "tree-pass.h"
+#include "dbgcnt.h"
 
 /* Value of the -G xx switch, and whether it was passed or not.  */
 unsigned HOST_WIDE_INT g_switch_value;
@@ -778,6 +779,10 @@ common_handle_option (size_t scode, cons
       fix_register (arg, 0, 0);
       break;
 
+    case OPT_fdbg_cnt_:
+      dbg_cnt_process_opt (arg);
+      break;
+
     case OPT_fdiagnostics_show_location_:
       if (!strcmp (arg, "once"))
 	diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
Index: recog.c
===================================================================
--- recog.c	(revision 118663)
+++ recog.c	(working copy)
@@ -391,13 +391,13 @@ void
 confirm_change_group (void)
 {
   int i;
-  basic_block bb;
 
   for (i = 0; i < num_changes; i++)
-    if (changes[i].object
-	&& INSN_P (changes[i].object)
-	&& (bb = BLOCK_FOR_INSN (changes[i].object)))
-      df_set_bb_dirty (bb);
+    {
+      rtx object = changes[i].object;
+      if (object && INSN_P (object))
+	df_insn_rescan (object);
+    }
 
   num_changes = 0;
 }
Index: dbgcnt.c
===================================================================
--- dbgcnt.c	(revision 0)
+++ dbgcnt.c	(revision 0)
@@ -0,0 +1,69 @@
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+
+#include "dbgcnt.h"
+
+struct string2counter_map {
+  const char *name;
+  enum debug_counter counter;
+};
+
+#define COUNTER(a) { #a , a }
+
+static struct string2counter_map map[debug_counter_number_of_counters] =
+{
+COUNTER(new_dce)
+};
+
+static int count[debug_counter_number_of_counters];
+static int limit[debug_counter_number_of_counters];
+
+bool
+dbg_cnt (enum debug_counter index)
+{
+  count[index]++;
+  return limit[index] == 0 || (count[index] < limit[index]);
+}
+
+static void
+dbg_cnt_set_limit_by_index (enum debug_counter index, int value)
+{
+  limit[index] = value;
+
+  fprintf (stderr, "dbg_cnt '%s' set to %d\n", map[index].name, value);
+}
+
+static void
+dbg_cnt_set_limit_by_name (const char *name, int len, int value)
+{
+  int i;
+  for (i = debug_counter_number_of_counters - 1; i >= 0; i--)
+    if (!strncmp (map[i].name, name, len))
+      break;
+
+  if (i < 0)
+    return;
+
+  dbg_cnt_set_limit_by_index (i, value);
+}
+
+void
+dbg_cnt_process_opt (const char *arg)
+{
+   char *colon = strchr (arg, ':');
+   char *comma;
+   
+   if (colon == NULL)
+     return;
+
+   dbg_cnt_set_limit_by_name (arg, colon - arg, atoi (colon + 1));
+
+   comma = strchr (colon + 1, ',');
+   while (comma)
+     {
+       colon = strchr (comma + 1, ':');
+       dbg_cnt_set_limit_by_name (comma + 1, colon - comma + 1, atoi (colon + 1));
+       comma = strchr (colon + 1, ',');
+     }
+}
Index: dbgcnt.h
===================================================================
--- dbgcnt.h	(revision 0)
+++ dbgcnt.h	(revision 0)
@@ -0,0 +1,7 @@
+enum debug_counter {
+   new_dce,
+   debug_counter_number_of_counters
+};
+
+extern bool dbg_cnt (enum debug_counter index);
+extern void dbg_cnt_process_opt (const char *arg);
Index: function.c
===================================================================
--- function.c	(revision 118663)
+++ function.c	(working copy)
@@ -5093,7 +5093,7 @@ thread_prologue_and_epilogue_insns (void
 #endif
   edge_iterator ei;
 
-  prologue_epilogue_df = df_init (0, 0);
+  prologue_epilogue_df = df_init (0, DF_NO_REGS_EVER_LIVE);
   /* Do not even think about running dce here!!!!  All life, as we
      know it will cease!!!  There is dead code created by the previous
      call to split_all_insns that is resurrected by the prologue and
@@ -5136,6 +5136,7 @@ thread_prologue_and_epilogue_insns (void
       inserted = 1;
     }
 #endif
+   df_compute_regs_ever_live (prologue_epilogue_df, regs_ever_live);
 
   /* If the exit block has no non-fake predecessors, we don't need
      an epilogue.  */
Index: df.h
===================================================================
--- df.h	(revision 118663)
+++ df.h	(working copy)
@@ -128,7 +128,9 @@ enum df_ref_flags
 
     /* This flag is a marker for general purpose use.
        Used for verification of existing refs. */
-    DF_REF_MARKER = 1 << 11
+    DF_REF_MARKER = 1 << 11,
+
+    DF_REF_ARTIFICIAL = 1 << 12
   };
 
 
@@ -326,7 +328,8 @@ enum df_changeable_flags 
   DF_LR_RUN_DCE    = 1,  /* Run DCE.  */
   DF_NO_HARD_REGS  = 2,  /* Skip hard registers in RD and CHAIN Building.  */
   DF_EQ_NOTES      = 4,  /* Build chains with uses present in EQUIV/EQUAL notes. */
-  DF_RI_NO_UPDATE  = 8   /* Do not update the register info when df_analyze is run.  */
+  DF_RI_NO_UPDATE  = 8,  /* Do not update the register info when df_analyze is run.  */
+  DF_NO_REGS_EVER_LIVE = 16 /* Do not compute the regs_ever_live.  */
 };
 
 /* Two of these structures are inline in df, one for the uses and one
@@ -481,7 +484,8 @@ struct df
    but an artificial one created to model 
    always live registers, eh uses, etc.  
    ARTIFICIAL refs has NULL insn.  */
-#define DF_REF_IS_ARTIFICIAL(REF) ((REF)->insn == NULL)
+#define DF_REF_IS_ARTIFICIAL(REF) ((REF)->insn == NULL \
+                        || DF_REF_FLAGS_IS_SET ((REF), DF_REF_ARTIFICIAL))
 #define DF_REF_MARK(REF) (DF_REF_FLAGS_SET ((REF),DF_REF_MARKER))
 #define DF_REF_UNMARK(REF) (DF_REF_FLAGS_CLEAR ((REF),DF_REF_MARKER))
 #define DF_REF_IS_MARKED(REF) (DF_REF_FLAGS_IS_SET ((REF),DF_REF_MARKER))
@@ -766,6 +770,7 @@ extern struct df_ref *df_reg_chain_unlin
 extern void df_ref_remove (struct df *, struct df_ref *);
 extern void df_insn_create_insn_record (struct dataflow *, rtx);
 extern void df_insn_delete (rtx);
+extern void df_bb_refs_record (int, bool);
 extern void df_bb_delete (unsigned int);
 extern bool df_insn_rescan (rtx);
 extern void df_insn_refs_record (struct dataflow *, rtx, struct df_ref *);
Index: cfgcleanup.c
===================================================================
--- cfgcleanup.c	(revision 118663)
+++ cfgcleanup.c	(working copy)
@@ -2022,7 +2022,7 @@ try_optimize_cfg (int mode)
 		  rtx label = BB_HEAD (b);
 
 		  delete_insn_chain (label, label);
-		  /* In the case label is undeletable, move it after the
+		  /* If the case label is undeletable, move it after the
 		     BASIC_BLOCK note.  */
 		  if (NOTE_LINE_NUMBER (BB_HEAD (b)) == NOTE_INSN_DELETED_LABEL)
 		    {
Index: common.opt
===================================================================
--- common.opt	(revision 118663)
+++ common.opt	(working copy)
@@ -359,6 +359,10 @@ fdata-sections
 Common Report Var(flag_data_sections)
 Place data items into their own section
 
+fdbg-cnt=
+Common RejectNegative Joined
+-fdbg-cnt=<counter>:<limit>             Set the debug counter limit.   
+
 ; Nonzero for -fdefer-pop: don't pop args after each function call
 ; instead save them up to pop many calls' args with one insns.
 fdefer-pop
Index: combine.c
===================================================================
--- combine.c	(revision 118663)
+++ combine.c	(working copy)
@@ -3618,7 +3618,47 @@ try_combine (rtx i3, rtx i2, rtx i1, int
 	&& SET_DEST (newpat) == pc_rtx)
       *new_direct_jump_p = 1;
   }
+  
+  if (undobuf.other_insn != NULL_RTX)
+    {
+      if (dump_file)
+	{
+	  fprintf (dump_file, "modifying other_insn ");
+	  dump_insn_slim (dump_file, undobuf.other_insn);
+	}
+      df_insn_rescan (undobuf.other_insn);
+    }
+
+  if (i1 && !(NOTE_P(i1) && (NOTE_LINE_NUMBER (i1) == NOTE_INSN_DELETED)))
+    {
+      if (dump_file)
+	{
+	  fprintf (dump_file, "modifying insn i1 ");
+	  dump_insn_slim (dump_file, i1);
+	}
+      df_insn_rescan (i1);
+    }
 
+  if (i2 && !(NOTE_P(i2) && (NOTE_LINE_NUMBER (i2) == NOTE_INSN_DELETED)))
+    {
+      if (dump_file)
+	{
+	  fprintf (dump_file, "modifying insn i2 ");
+	  dump_insn_slim (dump_file, i2);
+	}
+      df_insn_rescan (i2);
+    }
+
+  if (i3 && !(NOTE_P(i3) && (NOTE_LINE_NUMBER (i3) == NOTE_INSN_DELETED)))
+    {
+      if (dump_file)
+	{
+	  fprintf (dump_file, "modifying insn i3 ");
+	  dump_insn_slim (dump_file, i3);
+	}
+      df_insn_rescan (i3);
+    }
+  
   combine_successes++;
   undo_commit ();
 
@@ -12960,6 +13000,7 @@ struct tree_opt_pass pass_combine =
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_dump_func |
+  TODO_df_verify_scan |
   TODO_df_finish |
   TODO_ggc_collect,                     /* todo_flags_finish */
   'c'                                   /* letter */
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 118663)
+++ Makefile.in	(working copy)
@@ -1020,7 +1020,7 @@ OBJS-common = \
  lambda-trans.o	lambda-code.o tree-loop-linear.o tree-ssa-sink.o 	   \
  tree-vrp.o tree-stdarg.o tree-cfgcleanup.o tree-ssa-reassoc.o		   \
  tree-ssa-structalias.o tree-object-size.o 				   \
- rtl-factoring.o
+ rtl-factoring.o dbgcnt.o
 
 
 OBJS-md = $(out_object_file)
@@ -2655,6 +2655,7 @@ hooks.o: hooks.c $(CONFIG_H) $(SYSTEM_H)
 pretty-print.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h $(PRETTY_PRINT_H) \
    $(TREE_H)
 errors.o : errors.c $(CONFIG_H) $(SYSTEM_H) errors.h $(BCONFIG_H)
+dbgcnt.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h dbgcnt.h
 
 $(out_object_file): $(out_file) $(CONFIG_H) coretypes.h $(TM_H) $(TREE_H) \
    $(RTL_H) $(REGS_H) hard-reg-set.h insn-config.h conditions.h \
Index: passes.c
===================================================================
--- passes.c	(revision 118663)
+++ passes.c	(working copy)
@@ -825,6 +825,8 @@ execute_todo (unsigned int flags)
     verify_stmts ();
   if (flags & TODO_verify_loops)
     verify_loop_closed_ssa ();
+  if (flags & TODO_df_verify_scan)
+    df_verify_blocks (df_current_instance->problems_by_index[DF_SCAN], NULL);
 #endif
 
   /* Now that the dumping has been done, we can get rid of the df instance.  */
Index: config/ia64/ia64.c
===================================================================
--- config/ia64/ia64.c	(revision 118663)
+++ config/ia64/ia64.c	(working copy)
@@ -1976,7 +1976,10 @@ ia64_reload_gp (void)
   rtx tmp;
 
   if (current_frame_info.reg_save_gp)
-    tmp = gen_rtx_REG (DImode, current_frame_info.reg_save_gp);
+    {
+      tmp = gen_rtx_REG (DImode, current_frame_info.reg_save_gp);
+      current_frame_info.initialized = 1;
+    }
   else
     {
       HOST_WIDE_INT offset;
@@ -3553,7 +3556,10 @@ ia64_split_return_addr_rtx (rtx dest)
   if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
     {
       if (current_frame_info.reg_save_b0 != 0)
-	src = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
+        {
+	  src = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
+	  current_frame_info.initialized = 1;
+	}
       else
 	{
 	  HOST_WIDE_INT off;
@@ -8541,8 +8547,8 @@ ia64_reorg (void)
   else
     emit_all_insn_group_barriers (dump_file);
 
-  df = df_init (DF_HARD_REGS);
-  df_live_add_problem (df, 0);
+  df = df_init (0, 0);
+  df_live_add_problem (df);
   df_analyze (df);
  
   /* A call must not be the last instruction in a function, so that the
Index: cfgrtl.c
===================================================================
--- cfgrtl.c	(revision 118663)
+++ cfgrtl.c	(working copy)
@@ -304,6 +304,7 @@ create_basic_block_structure (rtx head, 
   bb->flags = BB_NEW | BB_RTL;
   link_block (bb, after);
   SET_BASIC_BLOCK (bb->index, bb);
+  df_bb_refs_record (bb->index, false);
   update_bb_for_insn (bb);
   BB_SET_PARTITION (bb, BB_UNPARTITIONED);
 
@@ -389,6 +390,8 @@ rtl_delete_block (basic_block b)
   BB_HEAD (b) = NULL;
   delete_insn_chain (insn, end);
 
+  if (dump_file)
+    fprintf (dump_file, "deleting block %d\n", b->index);
   df_delete_basic_block (b->index);
 }
 
@@ -555,6 +558,9 @@ rtl_merge_blocks (basic_block a, basic_b
   rtx del_first = NULL_RTX, del_last = NULL_RTX;
   int b_empty = 0;
 
+  if (dump_file)
+    fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index);
+
   /* If there was a CODE_LABEL beginning B, delete it.  */
   if (LABEL_P (b_head))
     {
@@ -2575,6 +2581,9 @@ cfg_layout_merge_blocks (basic_block a, 
   gcc_assert (cfg_layout_can_merge_blocks_p (a, b));
 #endif
 
+  if (dump_file)
+    fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index);
+
   /* If there was a CODE_LABEL beginning B, delete it.  */
   if (LABEL_P (BB_HEAD (b)))
     {
Index: dce.c
===================================================================
--- dce.c	(revision 118663)
+++ dce.c	(working copy)
@@ -33,6 +33,7 @@ Software Foundation, 51 Franklin Street,
 #include "dce.h"
 #include "timevar.h"
 #include "tree-pass.h"
+#include "dbgcnt.h"
 
 DEF_VEC_I(int);
 DEF_VEC_ALLOC_I(int,heap);
@@ -68,6 +69,7 @@ deletable_insn_p (rtx insn)
     case USE:
     case PREFETCH:
     case TRAP_IF:
+    case UNSPEC:
       return false;
 
     case CLOBBER:
@@ -221,7 +223,8 @@ delete_unmarked_insns (void)
   FOR_EACH_BB (bb)
     FOR_BB_INSNS_SAFE (bb, insn, next)
       if (INSN_P (insn) 
-	&& ((!marked_insn_p (insn)) || noop_move_p (insn)))
+	&& ((!marked_insn_p (insn)) || noop_move_p (insn))
+        && dbg_cnt (new_dce))
 	{
 	  if (dump_file)
 	    fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn));

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