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] Don't rescan everything after CSE


This saves ~1% of compilation time.

More ideas that I have, but did not implement are:

1) delay computation of LR/UR until where we did it in the trunk.  fwprop and GCSE do not need it, for example.

2) don't update REG_DEAD/REG_UNUSED notes for patches that don't need it.  Updating them could/should be a changeable flag.

Bootstrapped/regtested i686-pc-linux-gnu.

Paolo
2007-03-06  Paolo Bonzini  <bonzini@gnu.org>

	* cse.c (validate_canon_reg): Don't do anything if *XLOC is NULL.  Assert
	it is only called with insn != 0 and it never resets something non-NULL to
	NULL.  Always use validate_change.
	(cse_insn): Always call canon_reg with an INSN except when it is used on
	a REG.  When processing notes, first canonicalize, then fold, and call
	df_notes_rescan.
	(cse_process_notes): Rename to cse_process_notes_1, add CHANGED parameter.
	(cse_process_notes_1): Wrapper around cse_process_notes to set the CHANGED
	parameter.
	(cse_extended_basic_block): Adjust call to cse_process_notes and use result
	to call df_notes_rescan.
	(cse_main): Set deferred insn rescanning flag, don't rescan on exit.
	(pass_cse2): Add TODO_df_finish.
	* gcse.c (pass_gcse): Likewise.

Index: cse.c
===================================================================
--- cse.c	(revision 122403)
+++ cse.c	(working copy)
@@ -585,7 +585,7 @@ static void record_jump_cond (enum rtx_c
 static void cse_insn (rtx, rtx);
 static void cse_prescan_path (struct cse_basic_block_data *);
 static void invalidate_from_clobbers (rtx);
-static rtx cse_process_notes (rtx, rtx);
+static rtx cse_process_notes (rtx, rtx, bool *);
 static void cse_extended_basic_block (struct cse_basic_block_data *);
 static void count_reg_usage (rtx, int *, rtx, int);
 static int check_for_label_ref (rtx *, void *);
@@ -2642,14 +2642,15 @@ cse_rtx_varies_p (rtx x, int from_alias)
 static void
 validate_canon_reg (rtx *xloc, rtx insn)
 {
-  rtx new = canon_reg (*xloc, insn);
+  if (*xloc)
+    {
+      rtx new = canon_reg (*xloc, insn);
 
-  /* If replacing pseudo with hard reg or vice versa, ensure the
-     insn remains valid.  Likewise if the insn has MATCH_DUPs.  */
-  if (insn != 0 && new != 0)
-    validate_change (insn, xloc, new, 1);
-  else
-    *xloc = new;
+      /* If replacing pseudo with hard reg or vice versa, ensure the
+         insn remains valid.  Likewise if the insn has MATCH_DUPs.  */
+      gcc_assert (insn && new);
+      validate_change (insn, xloc, new, 1);
+    }
 }
 
 /* Canonicalize an expression:
@@ -4119,12 +4120,12 @@ cse_insn (rtx insn, rtx libcall_insn)
 		 This does nothing when a register is clobbered
 		 because we have already invalidated the reg.  */
 	      if (MEM_P (XEXP (y, 0)))
-		canon_reg (XEXP (y, 0), NULL_RTX);
+		canon_reg (XEXP (y, 0), insn);
 	    }
 	  else if (GET_CODE (y) == USE
 		   && ! (REG_P (XEXP (y, 0))
 			 && REGNO (XEXP (y, 0)) < FIRST_PSEUDO_REGISTER))
-	    canon_reg (y, NULL_RTX);
+	    canon_reg (y, insn);
 	  else if (GET_CODE (y) == CALL)
 	    {
 	      /* The result of apply_change_group can be ignored; see
@@ -4138,14 +4139,14 @@ cse_insn (rtx insn, rtx libcall_insn)
   else if (GET_CODE (x) == CLOBBER)
     {
       if (MEM_P (XEXP (x, 0)))
-	canon_reg (XEXP (x, 0), NULL_RTX);
+	canon_reg (XEXP (x, 0), insn);
     }
 
   /* Canonicalize a USE of a pseudo register or memory location.  */
   else if (GET_CODE (x) == USE
 	   && ! (REG_P (XEXP (x, 0))
 		 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER))
-    canon_reg (XEXP (x, 0), NULL_RTX);
+    canon_reg (XEXP (x, 0), insn);
   else if (GET_CODE (x) == CALL)
     {
       /* The result of apply_change_group can be ignored; see canon_reg.  */
@@ -4163,8 +4164,12 @@ cse_insn (rtx insn, rtx libcall_insn)
       && (! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl))
 	  || GET_CODE (SET_DEST (sets[0].rtl)) == STRICT_LOW_PART))
     {
-      src_eqv = fold_rtx (canon_reg (XEXP (tem, 0), NULL_RTX), insn);
+      /* The result of apply_change_group can be ignored; see canon_reg.  */
+      canon_reg (XEXP (tem, 0), insn);
+      apply_change_group ();
+      src_eqv = fold_rtx (XEXP (tem, 0), insn);
       XEXP (tem, 0) = src_eqv;
+      df_notes_rescan (insn);
     }
 
   /* Canonicalize sources and addresses of destinations.
@@ -4829,6 +4834,7 @@ cse_insn (rtx insn, rtx libcall_insn)
 		    XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0),
 							   sets[i].orig_src,
 							   copy_rtx (new));
+		  df_notes_rescan (libcall_insn);
 		}
 
 	      /* The result of apply_change_group can be ignored; see
@@ -4947,6 +4953,7 @@ cse_insn (rtx insn, rtx libcall_insn)
 	      /* Record the actual constant value in a REG_EQUAL note,
 		 making a new one if one does not already exist.  */
 	      set_unique_reg_note (insn, REG_EQUAL, src_const);
+	      df_notes_rescan (insn);
 	    }
 	}
 
@@ -5683,7 +5690,7 @@ invalidate_from_clobbers (rtx x)
    Return the replacement for X.  */
 
 static rtx
-cse_process_notes (rtx x, rtx object)
+cse_process_notes_1 (rtx x, rtx object, bool *changed)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt = GET_RTX_FORMAT (code);
@@ -5704,22 +5711,22 @@ cse_process_notes (rtx x, rtx object)
 
     case MEM:
       validate_change (x, &XEXP (x, 0),
-		       cse_process_notes (XEXP (x, 0), x), 0);
+		       cse_process_notes (XEXP (x, 0), x, changed), 0);
       return x;
 
     case EXPR_LIST:
     case INSN_LIST:
       if (REG_NOTE_KIND (x) == REG_EQUAL)
-	XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX);
+	XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX, changed);
       if (XEXP (x, 1))
-	XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX);
+	XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX, changed);
       return x;
 
     case SIGN_EXTEND:
     case ZERO_EXTEND:
     case SUBREG:
       {
-	rtx new = cse_process_notes (XEXP (x, 0), object);
+	rtx new = cse_process_notes (XEXP (x, 0), object, changed);
 	/* We don't substitute VOIDmode constants into these rtx,
 	   since they would impede folding.  */
 	if (GET_MODE (new) != VOIDmode)
@@ -5755,10 +5762,20 @@ cse_process_notes (rtx x, rtx object)
   for (i = 0; i < GET_RTX_LENGTH (code); i++)
     if (fmt[i] == 'e')
       validate_change (object, &XEXP (x, i),
-		       cse_process_notes (XEXP (x, i), object), 0);
+		       cse_process_notes (XEXP (x, i), object, changed), 0);
 
   return x;
 }
+
+static rtx
+cse_process_notes (rtx x, rtx object, bool *changed)
+{
+  rtx new = cse_process_notes_1 (x, object, changed);
+  if (new != x)
+    *changed = true;
+  return new;
+}
+
 
 /* Find a path in the CFG, starting with FIRST_BB to perform CSE on.
 
@@ -6006,8 +6023,13 @@ cse_extended_basic_block (struct cse_bas
 	      /* Process notes first so we have all notes in canonical forms
 		 when looking for duplicate operations.  */
 	      if (REG_NOTES (insn))
-		REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn),
-						      NULL_RTX);
+		{
+		  bool changed = false;
+		  REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn),
+						        NULL_RTX, &changed);
+		  if (changed)
+		    df_notes_rescan (insn);
+		}
 
 	      /* Track when we are inside in LIBCALL block.  Inside such
 		 a block we do not want to record destinations.  The last
@@ -6181,7 +6203,10 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nr
   int i, n_blocks;
 
   if (df)
-    df_set_flags (DF_NO_INSN_RESCAN);
+    {
+      df_analyze ();
+      df_set_flags (DF_DEFER_INSN_RESCAN);
+    }
 
   init_cse_reg_info (nregs);
 
@@ -6264,11 +6289,6 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nr
   sbitmap_free (reg_used_in_multiple_bb);
   free (rc_order);
   rtl_hooks = general_rtl_hooks;
-  if (df)
-    {
-      df_clear_flags (DF_NO_INSN_RESCAN);
-      df_insn_rescan_all ();
-    }
 
   return cse_jumps_altered || recorded_label_ref;
 }
@@ -7080,6 +7100,7 @@ struct tree_opt_pass pass_cse2 =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
+  TODO_df_finish |
   TODO_dump_func |
   TODO_ggc_collect |
   TODO_verify_flow,                     /* todo_flags_finish */
Index: gcse.c
===================================================================
--- gcse.c	(revision 122403)
+++ gcse.c	(working copy)
@@ -6731,6 +6731,7 @@ struct tree_opt_pass pass_gcse =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
+  TODO_df_finish |
   TODO_dump_func |
   TODO_verify_flow | TODO_ggc_collect,  /* todo_flags_finish */
   'G'                                   /* letter */

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