This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] gcse.c cleanups


Hi,

This makes gcse never walk the insn chain across basic block
boundaries.  This is a prerequisite for making it work in
cfglayout mode.  The old loop optimizer and CSE are still the
major obstackles for using cfglayout mode in the entire RTL
optimization path, but I'm trying to eliminate other problems
when I see them...

Bootstrapped and tested on x86_64-unknown-linux-gnu.
OK for mainline?

Gr.
Steven

	* cselib.c (clear_table): Rename to cselib_clear_table.
	* cselib.h (cselib_clear_table): Add prototype.
	* gcse.c (gcse_main): Make 'f' argument unused.
	(alloc_gcse_mem): Do not walk the insn chain, walk the contents
	of each basic block instead.
	(compute_sets, compute_hash_table_work): Likewise.
	(constprop_register): Change int 'alter_jumps' argument to bool.
	(do_local_cprop): Likewise.
	(local_cprop_pass): Likewise.  Also walk basic blocks instead of
	the insn chain.  Explicitly clear the cselib tables after finishing
	one basic block.  Make sure there are no unterminated libcall blocks.
	Update compute_sets call.
	(cprop): Walk basic blocks instead of the insn chain.
	(one_cprop_pass, compute_ld_motion_mems, compute_store_table):
	Likewise.
	(bypass_jumps): Update alloc_gcse_mem, compute_sets, and
	one_cprop_pass calls.

Index: cselib.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cselib.c,v
retrieving revision 1.59
diff -u -3 -p -r1.59 cselib.c
--- cselib.c	6 Mar 2005 20:02:46 -0000	1.59
+++ cselib.c	10 Apr 2005 00:53:01 -0000
@@ -50,7 +50,6 @@ static struct elt_loc_list *new_elt_loc_
 static void unchain_one_value (cselib_val *);
 static void unchain_one_elt_list (struct elt_list **);
 static void unchain_one_elt_loc_list (struct elt_loc_list **);
-static void clear_table (void);
 static int discard_useless_locs (void **, void *);
 static int discard_useless_values (void **, void *);
 static void remove_useless_values (void);
@@ -106,11 +105,11 @@ static unsigned int reg_values_size;
 #define REG_VALUES(i) reg_values[i]
 
 /* The largest number of hard regs used by any entry added to the
-   REG_VALUES table.  Cleared on each clear_table() invocation.  */
+   REG_VALUES table.  Cleared on each cselib_clear_table() invocation.  */
 static unsigned int max_value_regs;
 
 /* Here the set of indices I with REG_VALUES(I) != 0 is saved.  This is used
-   in clear_table() for fast emptying.  */
+   in cselib_clear_table() for fast emptying.  */
 static unsigned int *used_regs;
 static unsigned int n_used_regs;
 
@@ -200,8 +199,8 @@ unchain_one_value (cselib_val *v)
    initialization.  If CLEAR_ALL isn't set, then only clear the entries
    which are known to have been used.  */
 
-static void
-clear_table (void)
+void
+cselib_clear_table (void)
 {
   unsigned int i;
 
@@ -1362,7 +1361,7 @@ cselib_process_insn (rtx insn)
     {
       if (find_reg_note (insn, REG_RETVAL, NULL))
         cselib_current_insn_in_libcall = false;
-      clear_table ();
+      cselib_clear_table ();
       return;
     }
 
@@ -1464,7 +1463,7 @@ cselib_finish (void)
   free_alloc_pool (elt_loc_list_pool);
   free_alloc_pool (cselib_val_pool);
   free_alloc_pool (value_pool);
-  clear_table ();
+  cselib_clear_table ();
   htab_delete (hash_table);
   free (used_regs);
   used_regs = 0;
Index: cselib.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cselib.h,v
retrieving revision 1.16
diff -u -3 -p -r1.16 cselib.h
--- cselib.h	13 Sep 2004 09:05:31 -0000	1.16
+++ cselib.h	10 Apr 2005 00:53:01 -0000
@@ -64,6 +64,7 @@ struct elt_list GTY(())
 
 extern cselib_val *cselib_lookup (rtx, enum machine_mode, int);
 extern void cselib_init (bool record_memory);
+extern void cselib_clear_table (void);
 extern void cselib_finish (void);
 extern void cselib_process_insn (rtx);
 extern enum machine_mode cselib_reg_set_mode (rtx);
Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.338
diff -u -3 -p -r1.338 gcse.c
--- gcse.c	1 Apr 2005 03:42:40 -0000	1.338
+++ gcse.c	10 Apr 2005 00:53:02 -0000
@@ -522,13 +522,13 @@ static void *gmalloc (size_t) ATTRIBUTE_
 static void *gcalloc (size_t, size_t) ATTRIBUTE_MALLOC;
 static void *grealloc (void *, size_t);
 static void *gcse_alloc (unsigned long);
-static void alloc_gcse_mem (rtx);
+static void alloc_gcse_mem (void);
 static void free_gcse_mem (void);
 static void alloc_reg_set_mem (int);
 static void free_reg_set_mem (void);
 static void record_one_set (int, rtx);
 static void record_set_info (rtx, rtx, void *);
-static void compute_sets (rtx);
+static void compute_sets (void);
 static void hash_scan_insn (rtx, struct hash_table *, int);
 static void hash_scan_set (rtx, rtx, struct hash_table *);
 static void hash_scan_clobber (rtx, rtx, struct hash_table *);
@@ -578,8 +578,8 @@ static void canon_list_insert (rtx, rtx,
 static int cprop_insn (rtx, int);
 static int cprop (int);
 static void find_implicit_sets (void);
-static int one_cprop_pass (int, int, int);
-static bool constprop_register (rtx, rtx, rtx, int);
+static int one_cprop_pass (int, bool, bool);
+static bool constprop_register (rtx, rtx, rtx, bool);
 static struct expr *find_bypass_set (int, int);
 static bool reg_killed_on_edge (rtx, edge);
 static int bypass_block (basic_block, rtx, rtx);
@@ -645,9 +645,9 @@ static void clear_modify_mem_tables (voi
 static void free_modify_mem_tables (void);
 static rtx gcse_emit_move_after (rtx, rtx, rtx);
 static void local_cprop_find_used_regs (rtx *, void *);
-static bool do_local_cprop (rtx, rtx, int, rtx*);
+static bool do_local_cprop (rtx, rtx, bool, rtx*);
 static bool adjust_libcall_notes (rtx, rtx, rtx, rtx*);
-static void local_cprop_pass (int);
+static void local_cprop_pass (bool);
 static bool is_too_expensive (const char *);
 
 
@@ -656,7 +656,7 @@ static bool is_too_expensive (const char
    change is mode.  */
 
 int
-gcse_main (rtx f, FILE *file)
+gcse_main (rtx f ATTRIBUTE_UNUSED, FILE *file)
 {
   int changed, pass;
   /* Bytes used at start of pass.  */
@@ -704,7 +704,7 @@ gcse_main (rtx f, FILE *file)
      information about memory sets when we build the hash tables.  */
 
   alloc_reg_set_mem (max_gcse_regno);
-  compute_sets (f);
+  compute_sets ();
 
   pass = 0;
   initial_bytes_used = bytes_used;
@@ -724,12 +724,12 @@ gcse_main (rtx f, FILE *file)
       /* Each pass may create new registers, so recalculate each time.  */
       max_gcse_regno = max_reg_num ();
 
-      alloc_gcse_mem (f);
+      alloc_gcse_mem ();
 
       /* Don't allow constant propagation to modify jumps
 	 during this pass.  */
       timevar_push (TV_CPROP1);
-      changed = one_cprop_pass (pass + 1, 0, 0);
+      changed = one_cprop_pass (pass + 1, false, false);
       timevar_pop (TV_CPROP1);
 
       if (optimize_size)
@@ -749,7 +749,7 @@ gcse_main (rtx f, FILE *file)
 	    }
 	  free_reg_set_mem ();
 	  alloc_reg_set_mem (max_reg_num ());
-	  compute_sets (f);
+	  compute_sets ();
 	  run_jump_opt_after_gcse = 1;
 	  timevar_pop (TV_PRE);
 	}
@@ -771,7 +771,7 @@ gcse_main (rtx f, FILE *file)
 	{
 	  timevar_push (TV_HOIST);
 	  max_gcse_regno = max_reg_num ();
-	  alloc_gcse_mem (f);
+	  alloc_gcse_mem ();
 	  changed |= one_code_hoisting_pass ();
 	  free_gcse_mem ();
 
@@ -794,10 +794,10 @@ gcse_main (rtx f, FILE *file)
      conditional jumps.  */
 
   max_gcse_regno = max_reg_num ();
-  alloc_gcse_mem (f);
+  alloc_gcse_mem ();
   /* This time, go ahead and allow cprop to alter jumps.  */
   timevar_push (TV_CPROP2);
-  one_cprop_pass (pass + 1, 1, 0);
+  one_cprop_pass (pass + 1, true, false);
   timevar_pop (TV_CPROP2);
   free_gcse_mem ();
 
@@ -923,32 +923,39 @@ gcse_alloc (unsigned long size)
    This is called at the start of each pass.  */
 
 static void
-alloc_gcse_mem (rtx f)
+alloc_gcse_mem (void)
 {
   int i;
+  basic_block bb;
   rtx insn;
 
   /* Find the largest UID and create a mapping from UIDs to CUIDs.
      CUIDs are like UIDs except they increase monotonically, have no gaps,
-     and only apply to real insns.  */
+     and only apply to real insns.
+     (Actually, there are gaps, for insn that are not inside a basic block.
+     but we should never see those anyway, so this is OK.)  */
 
   max_uid = get_max_uid ();
   uid_cuid = gcalloc (max_uid + 1, sizeof (int));
-  for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
-    {
-      if (INSN_P (insn))
-	uid_cuid[INSN_UID (insn)] = i++;
-      else
-	uid_cuid[INSN_UID (insn)] = i;
-    }
+  i = 0;
+  FOR_EACH_BB (bb)
+    FOR_BB_INSNS (bb, insn)
+      {
+	if (INSN_P (insn))
+	  uid_cuid[INSN_UID (insn)] = i++;
+	else
+	  uid_cuid[INSN_UID (insn)] = i;
+      }
 
   /* Create a table mapping cuids to insns.  */
 
   max_cuid = i;
   cuid_insn = gcalloc (max_cuid + 1, sizeof (rtx));
-  for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
-    if (INSN_P (insn))
-      CUID_INSN (i++) = insn;
+  i = 0;
+  FOR_EACH_BB (bb)
+    FOR_BB_INSNS (bb, insn)
+      if (INSN_P (insn))
+	CUID_INSN (i++) = insn;
 
   /* Allocate vars to track sets of regs.  */
   reg_set_bitmap = BITMAP_ALLOC (NULL);
@@ -1141,13 +1148,15 @@ record_set_info (rtx dest, rtx setter AT
    `reg_set_table' for further documentation.  */
 
 static void
-compute_sets (rtx f)
+compute_sets (void)
 {
+  basic_block bb;
   rtx insn;
 
-  for (insn = f; insn != 0; insn = NEXT_INSN (insn))
-    if (INSN_P (insn))
-      note_stores (PATTERN (insn), record_set_info, insn);
+  FOR_EACH_BB (bb)
+    FOR_BB_INSNS (bb, insn)
+      if (INSN_P (insn))
+	note_stores (PATTERN (insn), record_set_info, insn);
 }
 
 /* Hash table support.  */
@@ -2038,9 +2047,7 @@ compute_hash_table_work (struct hash_tab
 	 ??? hard-reg reg_set_in_block computation
 	 could be moved to compute_sets since they currently don't change.  */
 
-      for (insn = BB_HEAD (current_bb);
-	   insn && insn != NEXT_INSN (BB_END (current_bb));
-	   insn = NEXT_INSN (insn))
+      FOR_BB_INSNS (current_bb, insn)
 	{
 	  if (! INSN_P (insn))
 	    continue;
@@ -2064,10 +2071,8 @@ compute_hash_table_work (struct hash_tab
 		       BB_HEAD (current_bb), table);
 
       /* The next pass builds the hash table.  */
-
-      for (insn = BB_HEAD (current_bb), in_libcall_block = 0;
-	   insn && insn != NEXT_INSN (BB_END (current_bb));
-	   insn = NEXT_INSN (insn))
+      in_libcall_block = 0;
+      FOR_BB_INSNS (current_bb, insn)
 	if (INSN_P (insn))
 	  {
 	    if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
@@ -2852,7 +2857,7 @@ cprop_jump (basic_block bb, rtx setcc, r
 }
 
 static bool
-constprop_register (rtx insn, rtx from, rtx to, int alter_jumps)
+constprop_register (rtx insn, rtx from, rtx to, bool alter_jumps)
 {
   rtx sset;
 
@@ -3030,7 +3035,7 @@ local_cprop_find_used_regs (rtx *xptr, v
    their REG_EQUAL notes need updating.  */
 
 static bool
-do_local_cprop (rtx x, rtx insn, int alter_jumps, rtx *libcall_sp)
+do_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp)
 {
   rtx newreg = NULL, newcnst = NULL;
 
@@ -3148,9 +3153,14 @@ adjust_libcall_notes (rtx oldreg, rtx ne
 
 #define MAX_NESTED_LIBCALLS 9
 
+/* Do local const/copy propagation (i.e. within each basic block).
+   If ALTER_JUMPS is true, allow propagating into jump insns, which
+   could modify the CFG.  */
+
 static void
-local_cprop_pass (int alter_jumps)
+local_cprop_pass (bool alter_jumps)
 {
+  basic_block bb;
   rtx insn;
   struct reg_use *reg_used;
   rtx libcall_stack[MAX_NESTED_LIBCALLS + 1], *libcall_sp;
@@ -3159,51 +3169,62 @@ local_cprop_pass (int alter_jumps)
   cselib_init (false);
   libcall_sp = &libcall_stack[MAX_NESTED_LIBCALLS];
   *libcall_sp = 0;
-  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+  FOR_EACH_BB (bb)
     {
-      if (INSN_P (insn))
+      FOR_BB_INSNS (bb, insn)
 	{
-	  rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
-
-	  if (note)
-	    {
-	      gcc_assert (libcall_sp != libcall_stack);
-	      *--libcall_sp = XEXP (note, 0);
-	    }
-	  note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
-	  if (note)
-	    libcall_sp++;
-	  note = find_reg_equal_equiv_note (insn);
-	  do
+	  if (INSN_P (insn))
 	    {
-	      reg_use_count = 0;
-	      note_uses (&PATTERN (insn), local_cprop_find_used_regs, NULL);
-	      if (note)
-		local_cprop_find_used_regs (&XEXP (note, 0), NULL);
+	      rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
 
-	      for (reg_used = &reg_use_table[0]; reg_use_count > 0;
-		   reg_used++, reg_use_count--)
-		if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
-		    libcall_sp))
-		  {
-		    changed = true;
+	      if (note)
+		{
+		  gcc_assert (libcall_sp != libcall_stack);
+		  *--libcall_sp = XEXP (note, 0);
+		}
+	      note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
+	      if (note)
+		libcall_sp++;
+	      note = find_reg_equal_equiv_note (insn);
+	      do
+		{
+		  reg_use_count = 0;
+		  note_uses (&PATTERN (insn), local_cprop_find_used_regs,
+			     NULL);
+		  if (note)
+		    local_cprop_find_used_regs (&XEXP (note, 0), NULL);
+
+		  for (reg_used = &reg_use_table[0]; reg_use_count > 0;
+		       reg_used++, reg_use_count--)
+		    if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
+			libcall_sp))
+		      {
+			changed = true;
+			break;
+		      }
+		  if (INSN_DELETED_P (insn))
 		    break;
-		  }
-	      if (INSN_DELETED_P (insn))
-		break;
+		}
+	      while (reg_use_count);
 	    }
-	  while (reg_use_count);
+	  cselib_process_insn (insn);
 	}
-      cselib_process_insn (insn);
+
+      /* Forget everything at the end of a basic block.  Make sure we are
+	 not inside a libcall, they should never cross basic blocks.  */
+      cselib_clear_table ();
+      gcc_assert (libcall_sp == &libcall_stack[MAX_NESTED_LIBCALLS]);
     }
+
   cselib_finish ();
+
   /* Global analysis may get into infinite loops for unreachable blocks.  */
   if (changed && alter_jumps)
     {
       delete_unreachable_blocks ();
       free_reg_set_mem ();
       alloc_reg_set_mem (max_reg_num ());
-      compute_sets (get_insns ());
+      compute_sets ();
     }
 }
 
@@ -3232,9 +3253,7 @@ cprop (int alter_jumps)
 	 start of the block].  */
       reset_opr_set_tables ();
 
-      for (insn = BB_HEAD (bb);
-	   insn != NULL && insn != NEXT_INSN (BB_END (bb));
-	   insn = NEXT_INSN (insn))
+      FOR_BB_INSNS (bb, insn)
 	if (INSN_P (insn))
 	  {
 	    changed |= cprop_insn (insn, alter_jumps);
@@ -3358,7 +3377,7 @@ find_implicit_sets (void)
    perform conditional jump bypassing optimizations.  */
 
 static int
-one_cprop_pass (int pass, int cprop_jumps, int bypass_jumps)
+one_cprop_pass (int pass, bool cprop_jumps, bool bypass_jumps)
 {
   int changed = 0;
 
@@ -3665,9 +3684,7 @@ bypass_conditional_jumps (void)
       if (!single_pred_p (bb))
 	{
 	  setcc = NULL_RTX;
-	  for (insn = BB_HEAD (bb);
-	       insn != NULL && insn != NEXT_INSN (BB_END (bb));
-	       insn = NEXT_INSN (insn))
+	  FOR_BB_INSNS (bb, insn)
 	    if (NONJUMP_INSN_P (insn))
 	      {
 		if (setcc)
@@ -5221,9 +5238,7 @@ compute_ld_motion_mems (void)
 
   FOR_EACH_BB (bb)
     {
-      for (insn = BB_HEAD (bb);
-	   insn && insn != NEXT_INSN (BB_END (bb));
-	   insn = NEXT_INSN (insn))
+      FOR_BB_INSNS (bb, insn)
 	{
 	  if (INSN_P (insn))
 	    {
@@ -5678,9 +5693,7 @@ compute_store_table (void)
       /* First compute the registers set in this block.  */
       regvec = last_set_in;
 
-      for (insn = BB_HEAD (bb);
-	   insn != NEXT_INSN (BB_END (bb));
-	   insn = NEXT_INSN (insn))
+      FOR_BB_INSNS (bb, insn)
 	{
 	  if (! INSN_P (insn))
 	    continue;
@@ -5703,9 +5716,7 @@ compute_store_table (void)
       /* Now find the stores.  */
       memset (already_set, 0, sizeof (int) * max_gcse_regno);
       regvec = already_set;
-      for (insn = BB_HEAD (bb);
-	   insn != NEXT_INSN (BB_END (bb));
-	   insn = NEXT_INSN (insn))
+      FOR_BB_INSNS (bb, insn)
 	{
 	  if (! INSN_P (insn))
 	    continue;
@@ -6477,11 +6488,11 @@ bypass_jumps (FILE *file)
      information about memory sets when we build the hash tables.  */
 
   alloc_reg_set_mem (max_gcse_regno);
-  compute_sets (get_insns ());
+  compute_sets ();
 
   max_gcse_regno = max_reg_num ();
-  alloc_gcse_mem (get_insns ());
-  changed = one_cprop_pass (MAX_GCSE_PASSES + 2, 1, 1);
+  alloc_gcse_mem ();
+  changed = one_cprop_pass (MAX_GCSE_PASSES + 2, true, true);
   free_gcse_mem ();
 
   if (file)


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