[38/50] rtlanal.c:replace_label
diff mbox

Message ID 87egwx7iqk.fsf@googlemail.com
State New
Headers show

Commit Message

Richard Sandiford Aug. 3, 2014, 2:25 p.m. UTC
The main change here is to handle ADDR_VEC and ADDR_DIFF_VECs specially,
since they can have many elements and are a relatively important case
for this function.  This is for speed rather than correctness.


gcc/
	* rtl.h (replace_label_data): Delete.
	(replace_label): Take the old label, new label and update-nuses flag
	as direct arguments.  Return void.
	* cfgcleanup.c (outgoing_edges_match): Update accordingly.
	* rtlanal.c (replace_label): Update interface as above.  Handle
	JUMP_TABLE_DATA as a special case.  Handle JUMPs outside the
	iterator.  Use FOR_EACH_SUBRTX_PTR.

Comments

Jeff Law Aug. 5, 2014, 10:11 p.m. UTC | #1
On 08/03/14 08:25, Richard Sandiford wrote:
> The main change here is to handle ADDR_VEC and ADDR_DIFF_VECs specially,
> since they can have many elements and are a relatively important case
> for this function.  This is for speed rather than correctness.
>
>
> gcc/
> 	* rtl.h (replace_label_data): Delete.
> 	(replace_label): Take the old label, new label and update-nuses flag
> 	as direct arguments.  Return void.
> 	* cfgcleanup.c (outgoing_edges_match): Update accordingly.
> 	* rtlanal.c (replace_label): Update interface as above.  Handle
> 	JUMP_TABLE_DATA as a special case.  Handle JUMPs outside the
> 	iterator.  Use FOR_EACH_SUBRTX_PTR.
OK.
jeff

Patch
diff mbox

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2014-08-03 11:25:30.447157195 +0100
+++ gcc/rtl.h	2014-08-03 11:25:30.745160142 +0100
@@ -2211,14 +2211,6 @@  #define single_set(I) (INSN_P (I) \
 		       : NULL_RTX)
 #define single_set_1(I) single_set_2 (I, PATTERN (I))
 
-/* Structure used for passing data to REPLACE_LABEL.  */
-struct replace_label_data
-{
-  rtx r1;
-  rtx r2;
-  bool update_label_nuses;
-};
-
 extern enum machine_mode get_address_mode (rtx mem);
 extern int rtx_addr_can_trap_p (const_rtx);
 extern bool nonzero_address_p (const_rtx);
@@ -2287,7 +2279,7 @@  extern void copy_reg_eh_region_note_forw
 extern void copy_reg_eh_region_note_backward (rtx, rtx, rtx);
 extern int inequality_comparisons_p (const_rtx);
 extern rtx replace_rtx (rtx, rtx, rtx);
-extern int replace_label (rtx *, void *);
+extern void replace_label (rtx *, rtx, rtx, bool);
 extern bool rtx_referenced_p (const_rtx, const_rtx);
 extern bool tablejump_p (const_rtx, rtx *, rtx *);
 extern int computed_jump_p (const_rtx);
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c	2014-08-03 11:25:22.602079634 +0100
+++ gcc/cfgcleanup.c	2014-08-03 11:25:30.745160142 +0100
@@ -1716,15 +1716,11 @@  outgoing_edges_match (int mode, basic_bl
 
 	      if (identical)
 		{
-		  replace_label_data rr;
 		  bool match;
 
 		  /* Temporarily replace references to LABEL1 with LABEL2
 		     in BB1->END so that we could compare the instructions.  */
-		  rr.r1 = label1;
-		  rr.r2 = label2;
-		  rr.update_label_nuses = false;
-		  for_each_rtx (&BB_END (bb1), replace_label, &rr);
+		  replace_label (&BB_END (bb1), label1, label2, false);
 
 		  match = (old_insns_match_p (mode, BB_END (bb1), BB_END (bb2))
 			   == dir_both);
@@ -1736,9 +1732,7 @@  outgoing_edges_match (int mode, basic_bl
 		  /* Set the original label in BB1->END because when deleting
 		     a block whose end is a tablejump, the tablejump referenced
 		     from the instruction is deleted too.  */
-		  rr.r1 = label2;
-		  rr.r2 = label1;
-		  for_each_rtx (&BB_END (bb1), replace_label, &rr);
+		  replace_label (&BB_END (bb1), label2, label1, false);
 
 		  return match;
 		}
@@ -1985,20 +1979,16 @@  #define SWAP(T, X, Y) do { T tmp = (X);
 	  && tablejump_p (BB_END (osrc2), &label2, &table2)
 	  && label1 != label2)
 	{
-	  replace_label_data rr;
 	  rtx insn;
 
 	  /* Replace references to LABEL1 with LABEL2.  */
-	  rr.r1 = label1;
-	  rr.r2 = label2;
-	  rr.update_label_nuses = true;
 	  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
 	    {
 	      /* Do not replace the label in SRC1->END because when deleting
 		 a block whose end is a tablejump, the tablejump referenced
 		 from the instruction is deleted too.  */
 	      if (insn != BB_END (osrc1))
-		for_each_rtx (&insn, replace_label, &rr);
+		replace_label (&insn, label1, label2, true);
 	    }
 	}
     }
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	2014-08-03 11:25:30.448157205 +0100
+++ gcc/rtlanal.c	2014-08-03 11:25:30.746160151 +0100
@@ -2770,65 +2770,79 @@  replace_rtx (rtx x, rtx from, rtx to)
   return x;
 }
 
-/* Replace occurrences of the old label in *X with the new one.
-   DATA is a REPLACE_LABEL_DATA containing the old and new labels.  */
+/* Replace occurrences of the OLD_LABEL in *LOC with NEW_LABEL.  Also track
+   the change in LABEL_NUSES if UPDATE_LABEL_NUSES.  */
 
-int
-replace_label (rtx *x, void *data)
+void
+replace_label (rtx *loc, rtx old_label, rtx new_label, bool update_label_nuses)
 {
-  rtx l = *x;
-  rtx old_label = ((replace_label_data *) data)->r1;
-  rtx new_label = ((replace_label_data *) data)->r2;
-  bool update_label_nuses = ((replace_label_data *) data)->update_label_nuses;
-
-  if (l == NULL_RTX)
-    return 0;
-
-  if (GET_CODE (l) == SYMBOL_REF
-      && CONSTANT_POOL_ADDRESS_P (l))
+  /* Handle jump tables specially, since ADDR_{DIFF_,}VECs can be long.  */
+  rtx x = *loc;
+  if (JUMP_TABLE_DATA_P (x))
     {
-      rtx c = get_pool_constant (l);
-      if (rtx_referenced_p (old_label, c))
+      x = PATTERN (x);
+      rtvec vec = XVEC (x, GET_CODE (x) == ADDR_DIFF_VEC);
+      int len = GET_NUM_ELEM (vec);
+      for (int i = 0; i < len; ++i)
 	{
-	  rtx new_c, new_l;
-	  replace_label_data *d = (replace_label_data *) data;
-
-	  /* Create a copy of constant C; replace the label inside
-	     but do not update LABEL_NUSES because uses in constant pool
-	     are not counted.  */
-	  new_c = copy_rtx (c);
-	  d->update_label_nuses = false;
-	  for_each_rtx (&new_c, replace_label, data);
-	  d->update_label_nuses = update_label_nuses;
-
-	  /* Add the new constant NEW_C to constant pool and replace
-	     the old reference to constant by new reference.  */
-	  new_l = XEXP (force_const_mem (get_pool_mode (l), new_c), 0);
-	  *x = replace_rtx (l, l, new_l);
+	  rtx ref = RTVEC_ELT (vec, i);
+	  if (XEXP (ref, 0) == old_label)
+	    {
+	      XEXP (ref, 0) = new_label;
+	      if (update_label_nuses)
+		{
+		  ++LABEL_NUSES (new_label);
+		  --LABEL_NUSES (old_label);
+		}
+	    }
 	}
-      return 0;
+      return;
     }
 
   /* If this is a JUMP_INSN, then we also need to fix the JUMP_LABEL
-     field.  This is not handled by for_each_rtx because it doesn't
+     field.  This is not handled by the iterator because it doesn't
      handle unprinted ('0') fields.  */
-  if (JUMP_P (l) && JUMP_LABEL (l) == old_label)
-    JUMP_LABEL (l) = new_label;
+  if (JUMP_P (x) && JUMP_LABEL (x) == old_label)
+    JUMP_LABEL (x) = new_label;
 
-  if ((GET_CODE (l) == LABEL_REF
-       || GET_CODE (l) == INSN_LIST)
-      && XEXP (l, 0) == old_label)
+  subrtx_ptr_iterator::array_type array;
+  FOR_EACH_SUBRTX_PTR (iter, array, loc, ALL)
     {
-      XEXP (l, 0) = new_label;
-      if (update_label_nuses)
+      rtx *loc = *iter;
+      if (rtx x = *loc)
 	{
-	  ++LABEL_NUSES (new_label);
-	  --LABEL_NUSES (old_label);
+	  if (GET_CODE (x) == SYMBOL_REF
+	      && CONSTANT_POOL_ADDRESS_P (x))
+	    {
+	      rtx c = get_pool_constant (x);
+	      if (rtx_referenced_p (old_label, c))
+		{
+		  /* Create a copy of constant C; replace the label inside
+		     but do not update LABEL_NUSES because uses in constant pool
+		     are not counted.  */
+		  rtx new_c = copy_rtx (c);
+		  replace_label (&new_c, old_label, new_label, false);
+
+		  /* Add the new constant NEW_C to constant pool and replace
+		     the old reference to constant by new reference.  */
+		  rtx new_mem = force_const_mem (get_pool_mode (x), new_c);
+		  *loc = replace_rtx (x, x, XEXP (new_mem, 0));
+		}
+	    }
+
+	  if ((GET_CODE (x) == LABEL_REF
+	       || GET_CODE (x) == INSN_LIST)
+	      && XEXP (x, 0) == old_label)
+	    {
+	      XEXP (x, 0) = new_label;
+	      if (update_label_nuses)
+		{
+		  ++LABEL_NUSES (new_label);
+		  --LABEL_NUSES (old_label);
+		}
+	    }
 	}
-      return 0;
     }
-
-  return 0;
 }
 
 /* Return true if X is referenced in BODY.  */