Patchwork [cprop.c] Simplify find_used_regs, iterate cprop_insn

login
register
mail settings
Submitter Steven Bosscher
Date April 4, 2011, 7:57 p.m.
Message ID <BANLkTimOaYZgQOijf=0Vdr_rEe1j+UXTNw@mail.gmail.com>
Download mbox | patch
Permalink /patch/89703/
State New
Headers show

Comments

Steven Bosscher - April 4, 2011, 7:57 p.m.
Hi,

This patch has one significant change: cprop_insn would not iterate
after a successful copy propagation, assuming the uses found with
find_used_regs remain the same. This is not true in two cases:

* find_used_regs found multiple uses of the same register, but that
register was replaced by try_replace_reg.

* find_used_regs found regs that have been folded after substitution
in try_replace_reg (which ultimately tries simplify_replace_rtx if all
else fails)

After this patch, cprop_insn starts over after one successful copy
propagation replacement.


The rest of the patch just cleans up a single-member struct reg_use {
rtx reg }. An array of rtx is simpler, although it probably makes no
difference for the generated code for cprop.c.

Bootstrapped & tested on x86_64-unknown-linux-gnu. OK?

Ciao!
Steven
* cprop.c (struct reg_use): Remove.
	(reg_use_table): Make an array of RTX.
	(find_used_regs, constprop_register, local_cprop_pass,
	bypass_block): Simplify users of reg_use_table.
	(cprop_insn): Likewise.  Iterate if copy propagation succeeded
	on one of the uses found by find_used_regs.
Richard Guenther - April 5, 2011, 10:21 a.m.
On Mon, Apr 4, 2011 at 9:57 PM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
> Hi,
>
> This patch has one significant change: cprop_insn would not iterate
> after a successful copy propagation, assuming the uses found with
> find_used_regs remain the same. This is not true in two cases:
>
> * find_used_regs found multiple uses of the same register, but that
> register was replaced by try_replace_reg.
>
> * find_used_regs found regs that have been folded after substitution
> in try_replace_reg (which ultimately tries simplify_replace_rtx if all
> else fails)
>
> After this patch, cprop_insn starts over after one successful copy
> propagation replacement.
>
>
> The rest of the patch just cleans up a single-member struct reg_use {
> rtx reg }. An array of rtx is simpler, although it probably makes no
> difference for the generated code for cprop.c.
>
> Bootstrapped & tested on x86_64-unknown-linux-gnu. OK?

Ok.

Thanks,
Richard.

> Ciao!
> Steven
>

Patch

Index: cprop.c
===================================================================
--- cprop.c	(revision 171947)
+++ cprop.c	(working copy)
@@ -53,8 +53,6 @@  along with GCC; see the file COPYING3.  
 /* An obstack for our working variables.  */
 static struct obstack cprop_obstack;
 
-struct reg_use {rtx reg_rtx; };
-
 /* Occurrence of an expression.
    There is one per basic block.  If a pattern appears more than once the
    last appearance is used.  */
@@ -653,12 +651,12 @@  compute_cprop_data (void)
 /* Maximum number of register uses in an insn that we handle.  */
 #define MAX_USES 8
 
-/* Table of uses found in an insn.
+/* Table of uses (registers, both hard and pseudo) found in an insn.
    Allocated statically to avoid alloc/free complexity and overhead.  */
-static struct reg_use reg_use_table[MAX_USES];
+static rtx reg_use_table[MAX_USES];
 
 /* Index into `reg_use_table' while building it.  */
-static int reg_use_count;
+static unsigned reg_use_count;
 
 /* Set up a list of register numbers used in INSN.  The found uses are stored
    in `reg_use_table'.  `reg_use_count' is initialized to zero before entry,
@@ -687,7 +685,7 @@  find_used_regs (rtx *xptr, void *data AT
       if (reg_use_count == MAX_USES)
 	return;
 
-      reg_use_table[reg_use_count].reg_rtx = x;
+      reg_use_table[reg_use_count] = x;
       reg_use_count++;
     }
 
@@ -997,10 +995,12 @@  constprop_register (rtx insn, rtx from, 
 static int
 cprop_insn (rtx insn)
 {
-  struct reg_use *reg_used;
-  int changed = 0;
+  unsigned i;
+  int changed = 0, changed_this_round;
   rtx note;
 
+retry:
+  changed_this_round = 0;
   reg_use_count = 0;
   note_uses (&PATTERN (insn), find_used_regs, NULL);
 
@@ -1009,16 +1009,16 @@  cprop_insn (rtx insn)
   if (note)
     find_used_regs (&XEXP (note, 0), NULL);
 
-  for (reg_used = &reg_use_table[0]; reg_use_count > 0;
-       reg_used++, reg_use_count--)
+  for (i = 0; i < reg_use_count; i++)
     {
-      unsigned int regno = REGNO (reg_used->reg_rtx);
+      rtx reg_used = reg_use_table[i];
+      unsigned int regno = REGNO (reg_used);
       rtx src;
       struct expr *set;
 
       /* If the register has already been set in this block, there's
 	 nothing we can do.  */
-      if (! reg_not_set_p (reg_used->reg_rtx, insn))
+      if (! reg_not_set_p (reg_used, insn))
 	continue;
 
       /* Find an assignment that sets reg_used and is available
@@ -1032,9 +1032,9 @@  cprop_insn (rtx insn)
       /* Constant propagation.  */
       if (cprop_constant_p (src))
 	{
-          if (constprop_register (insn, reg_used->reg_rtx, src))
+          if (constprop_register (insn, reg_used, src))
 	    {
-	      changed = 1;
+	      changed_this_round = changed = 1;
 	      global_const_prop_count++;
 	      if (dump_file != NULL)
 		{
@@ -1051,9 +1051,9 @@  cprop_insn (rtx insn)
 	       && REGNO (src) >= FIRST_PSEUDO_REGISTER
 	       && REGNO (src) != regno)
 	{
-	  if (try_replace_reg (reg_used->reg_rtx, src, insn))
+	  if (try_replace_reg (reg_used, src, insn))
 	    {
-	      changed = 1;
+	      changed_this_round = changed = 1;
 	      global_copy_prop_count++;
 	      if (dump_file != NULL)
 		{
@@ -1069,6 +1069,11 @@  cprop_insn (rtx insn)
 		 and made things worse.  */
 	    }
 	}
+
+      /* If try_replace_reg simplified the insn, the regs found
+	 by find_used_regs may not be valid anymore.  Start over.  */
+      if (changed_this_round)
+	goto retry;
     }
 
   if (changed && DEBUG_INSN_P (insn))
@@ -1195,8 +1200,8 @@  local_cprop_pass (void)
 {
   basic_block bb;
   rtx insn;
-  struct reg_use *reg_used;
   bool changed = false;
+  unsigned i;
 
   cselib_init (0);
   FOR_EACH_BB (bb)
@@ -1214,10 +1219,9 @@  local_cprop_pass (void)
 		  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--)
+		  for (i = 0; i < reg_use_count; i++)
 		    {
-		      if (do_local_cprop (reg_used->reg_rtx, insn))
+		      if (do_local_cprop (reg_use_table[i], insn))
 			{
 			  changed = true;
 			  break;
@@ -1226,7 +1230,7 @@  local_cprop_pass (void)
 		  if (INSN_DELETED_P (insn))
 		    break;
 		}
-	      while (reg_use_count);
+	      while (i < reg_use_count);
 	    }
 	  cselib_process_insn (insn);
 	}
@@ -1461,9 +1465,10 @@  bypass_block (basic_block bb, rtx setcc,
 {
   rtx insn, note;
   edge e, edest;
-  int i, change;
+  int change;
   int may_be_loop_header;
   unsigned removed_p;
+  unsigned i;
   edge_iterator ei;
 
   insn = (setcc != NULL) ? setcc : jump;
@@ -1513,8 +1518,8 @@  bypass_block (basic_block bb, rtx setcc,
 
       for (i = 0; i < reg_use_count; i++)
 	{
-	  struct reg_use *reg_used = &reg_use_table[i];
-	  unsigned int regno = REGNO (reg_used->reg_rtx);
+	  rtx reg_used = reg_use_table[i];
+	  unsigned int regno = REGNO (reg_used);
 	  basic_block dest, old_dest;
 	  struct expr *set;
 	  rtx src, new_rtx;
@@ -1525,7 +1530,7 @@  bypass_block (basic_block bb, rtx setcc,
 	    continue;
 
 	  /* Check the data flow is valid after edge insertions.  */
-	  if (e->insns.r && reg_killed_on_edge (reg_used->reg_rtx, e))
+	  if (e->insns.r && reg_killed_on_edge (reg_used, e))
 	    continue;
 
 	  src = SET_SRC (pc_set (jump));
@@ -1535,8 +1540,7 @@  bypass_block (basic_block bb, rtx setcc,
 					SET_DEST (PATTERN (setcc)),
 					SET_SRC (PATTERN (setcc)));
 
-	  new_rtx = simplify_replace_rtx (src, reg_used->reg_rtx,
-					  set->src);
+	  new_rtx = simplify_replace_rtx (src, reg_used, set->src);
 
 	  /* Jump bypassing may have already placed instructions on
 	     edges of the CFG.  We can't bypass an outgoing edge that