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]

Re: Crossjumping of tablejumps


> by a loop that goes over all insns, checks each insn for references
> to the literal pool, and checks for each such reference whether it
> contains label1; if so, replaces label1 with label2 in the constant, creates 
> a new literal pool entry for the modified constant, and replaces the 
> literal pool reference in the insn accordingly?

Hi,

this patch does the replacement of labels as suggested.
The replacement of the labels in pool constant is done is replace_label ().
The patch fixes the testcase and gcc.dg/20030213-1.c.
I hope it finally is correct.

Bootstrapped/regtested x86-64.
Bootstrapped s390, regtesting in progress.
OK for mainline if it passes regtesting?

Josef

2003-03-14  Josef Zlomek  <zlomekj at suse dot cz>

	* rtl.h (subrtx_p): Renamed to rtx_referenced_p.
	(rtx_pair): Added new element update_label_nuses, renamed to
	replace_label_data.
	* cfgcleanup.c (outgoing_edges_match, try_crossjump_to_edge): Use
	replace_label_data instead of rtx_pair.
	* loop.c (load_mems): Likewise.
	* rtlanal.c (replace_label): Replace label in pool constants and in
	INSN_LIST (in REG_LABEL note).
	(subrtx_p): Renamed to rtx_referenced_p.
	(subrtx_p_1): Renamed to rtx_referenced_p_1, compare the interior of
	LABEL_REF with CODE_LABEL, traverse constants from pool.

Index: cfgcleanup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgcleanup.c,v
retrieving revision 1.77
diff -c -3 -p -r1.77 cfgcleanup.c
*** cfgcleanup.c	10 Mar 2003 18:32:17 -0000	1.77
--- cfgcleanup.c	14 Mar 2003 17:04:08 -0000
*************** outgoing_edges_match (mode, bb1, bb2)
*** 1271,1280 ****
  	     the jump tables are same too. So disable crossjumping of blocks BB1
  	     and BB2 because when deleting the common insns in the end of BB1
  	     by flow_delete_block () the jump table would be deleted too.  */
! 	  /* If LABEL2 is contained in BB1->END do not do anything
  	     because we would loose information when replacing
  	     LABEL1 by LABEL2 and then LABEL2 by LABEL1 in BB1->END.  */
! 	  if (label1 != label2 && !subrtx_p (label2, bb1->end))
  	    {
  	      /* Set IDENTICAL to true when the tables are identical.  */
  	      bool identical = false;
--- 1271,1280 ----
  	     the jump tables are same too. So disable crossjumping of blocks BB1
  	     and BB2 because when deleting the common insns in the end of BB1
  	     by flow_delete_block () the jump table would be deleted too.  */
! 	  /* If LABEL2 is referenced in BB1->END do not do anything
  	     because we would loose information when replacing
  	     LABEL1 by LABEL2 and then LABEL2 by LABEL1 in BB1->END.  */
! 	  if (label1 != label2 && !rtx_referenced_p (label2, bb1->end))
  	    {
  	      /* Set IDENTICAL to true when the tables are identical.  */
  	      bool identical = false;
*************** outgoing_edges_match (mode, bb1, bb2)
*** 1301,1313 ****
  
  	      if (identical)
  		{
! 		  rtx_pair 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;
  		  for_each_rtx (&bb1->end, replace_label, &rr);
  
  		  match = insns_match_p (mode, bb1->end, bb2->end);
--- 1301,1314 ----
  
  	      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 (&bb1->end, replace_label, &rr);
  
  		  match = insns_match_p (mode, bb1->end, bb2->end);
*************** try_crossjump_to_edge (mode, e1, e2)
*** 1459,1470 ****
  	  && tablejump_p (src2->end, &label2, &table2)
  	  && label1 != label2)
  	{
! 	  rtx_pair rr;
  	  rtx insn;
  
  	  /* Replace references to LABEL1 with LABEL2.  */
  	  rr.r1 = label1;
  	  rr.r2 = label2;
  	  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
  	    {
  	      /* Do not replace the label in SRC1->END because when deleting
--- 1460,1472 ----
  	  && tablejump_p (src2->end, &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
Index: loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop.c,v
retrieving revision 1.447
diff -c -3 -p -r1.447 loop.c
*** loop.c	10 Mar 2003 17:23:44 -0000	1.447
--- loop.c	14 Mar 2003 17:04:09 -0000
*************** load_mems (loop)
*** 10137,10145 ****
      {
        /* Now, we need to replace all references to the previous exit
  	 label with the new one.  */
!       rtx_pair rr;
        rr.r1 = end_label;
        rr.r2 = label;
  
        for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
  	{
--- 10137,10146 ----
      {
        /* Now, we need to replace all references to the previous exit
  	 label with the new one.  */
!       replace_label_data rr;
        rr.r1 = end_label;
        rr.r2 = label;
+       rr.update_label_nuses = true;
  
        for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
  	{
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.387
diff -c -3 -p -r1.387 rtl.h
*** rtl.h	10 Mar 2003 17:23:44 -0000	1.387
--- rtl.h	14 Mar 2003 17:04:09 -0000
*************** extern rtx set_unique_reg_note		PARAMS (
*** 1596,1606 ****
  #define single_set_1(I) single_set_2 (I, PATTERN (I))
  
  /* Structure used for passing data to REPLACE_LABEL.  */
! typedef struct rtx_pair
  {
    rtx r1;
    rtx r2;
! } rtx_pair;
  
  extern int rtx_addr_can_trap_p		PARAMS ((rtx));
  extern bool nonzero_address_p		PARAMS ((rtx));
--- 1596,1607 ----
  #define single_set_1(I) single_set_2 (I, PATTERN (I))
  
  /* Structure used for passing data to REPLACE_LABEL.  */
! typedef struct replace_label_data
  {
    rtx r1;
    rtx r2;
!   bool update_label_nuses;
! } replace_label_data;
  
  extern int rtx_addr_can_trap_p		PARAMS ((rtx));
  extern bool nonzero_address_p		PARAMS ((rtx));
*************** extern rtx replace_rtx			PARAMS ((rtx, r
*** 1662,1668 ****
  extern rtx replace_regs			PARAMS ((rtx, rtx *, unsigned int,
  						 int));
  extern int replace_label		PARAMS ((rtx *, void *));
! extern int subrtx_p			PARAMS ((rtx, rtx));
  extern bool tablejump_p			PARAMS ((rtx, rtx *, rtx *));
  extern int computed_jump_p		PARAMS ((rtx));
  typedef int (*rtx_function)             PARAMS ((rtx *, void *));
--- 1663,1669 ----
  extern rtx replace_regs			PARAMS ((rtx, rtx *, unsigned int,
  						 int));
  extern int replace_label		PARAMS ((rtx *, void *));
! extern int rtx_referenced_p		PARAMS ((rtx, rtx));
  extern bool tablejump_p			PARAMS ((rtx, rtx *, rtx *));
  extern int computed_jump_p		PARAMS ((rtx));
  typedef int (*rtx_function)             PARAMS ((rtx *, void *));
Index: rtlanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtlanal.c,v
retrieving revision 1.148
diff -c -3 -p -r1.148 rtlanal.c
*** rtlanal.c	10 Mar 2003 17:23:44 -0000	1.148
--- rtlanal.c	14 Mar 2003 17:04:09 -0000
*************** Software Foundation, 59 Temple Place - S
*** 38,44 ****
  static int global_reg_mentioned_p_1 PARAMS ((rtx *, void *));
  static void set_of_1		PARAMS ((rtx, rtx, void *));
  static void insn_dependent_p_1	PARAMS ((rtx, rtx, void *));
! static int subrtx_p_1		PARAMS ((rtx *, void *));
  static int computed_jump_p_1	PARAMS ((rtx));
  static void parms_set 		PARAMS ((rtx, rtx, void *));
  static bool hoist_test_store		PARAMS ((rtx, rtx, regset));
--- 38,44 ----
  static int global_reg_mentioned_p_1 PARAMS ((rtx *, void *));
  static void set_of_1		PARAMS ((rtx, rtx, void *));
  static void insn_dependent_p_1	PARAMS ((rtx, rtx, void *));
! static int rtx_referenced_p_1	PARAMS ((rtx *, void *));
  static int computed_jump_p_1	PARAMS ((rtx));
  static void parms_set 		PARAMS ((rtx, rtx, void *));
  static bool hoist_test_store		PARAMS ((rtx, rtx, regset));
*************** replace_regs (x, reg_map, nregs, replace
*** 2793,2799 ****
  }
  
  /* Replace occurrences of the old label in *X with the new one.
!    DATA is an rtx_pair containing the old and new labels, respectively.  */
  
  int
  replace_label (x, data)
--- 2793,2799 ----
  }
  
  /* Replace occurrences of the old label in *X with the new one.
!    DATA is a REPLACE_LABEL_DATA containing the old and new labels.  */
  
  int
  replace_label (x, data)
*************** replace_label (x, data)
*** 2801,2851 ****
       void *data;
  {
    rtx l = *x;
!   rtx old_label = ((rtx_pair *) data)->r1;
!   rtx new_label = ((rtx_pair *) data)->r2;
  
    if (l == NULL_RTX)
      return 0;
  
    /* 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
       handle unprinted ('0') fields.  */
    if (GET_CODE (l) == JUMP_INSN && JUMP_LABEL (l) == old_label)
      JUMP_LABEL (l) = new_label;
-   
-   if (GET_CODE (l) != LABEL_REF)
-     return 0;
- 
-   if (XEXP (l, 0) != old_label)
-     return 0;
  
!   XEXP (l, 0) = new_label;
!   ++LABEL_NUSES (new_label);
!   --LABEL_NUSES (old_label);
  
    return 0;
  }
  
! /* Return RTX_EQUAL_P (*PX, SUBX).  If *PX and SUBX are not equal
!    FOR_EACH_RTX continues traversing, if they are equal FOR_EACH_RTX
!    stops traversing and returns the same value as this function.  */
  
  static int
! subrtx_p_1 (px, subx)
!      rtx *px;
!      void *subx;
  {
!   return rtx_equal_p (*px, (rtx) subx);
  }
  
! /* Return true if SUBX is equal to some subexpression of X.  */
  
  int
! subrtx_p (subx, x)
!      rtx subx;
       rtx x;
  {
!   return for_each_rtx (&x, subrtx_p_1, subx);
  }
  
  /* If INSN is a jump to jumptable insn rturn true and store the label (which
--- 2801,2898 ----
       void *data;
  {
    rtx l = *x;
!   rtx tmp;
!   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) == MEM
+       && (tmp = XEXP (l, 0)) != NULL_RTX
+       && GET_CODE (tmp) == SYMBOL_REF
+       && CONSTANT_POOL_ADDRESS_P (tmp))
+     {
+       rtx c = get_pool_constant (tmp);
+       if (rtx_referenced_p (old_label, c))
+ 	{
+ 	  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 = force_const_mem (get_pool_mode (tmp), new_c);
+ 	  *x = replace_rtx (l, l, new_l);
+ 	}
+       return 0;
+     }
+ 
    /* 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
       handle unprinted ('0') fields.  */
    if (GET_CODE (l) == JUMP_INSN && JUMP_LABEL (l) == old_label)
      JUMP_LABEL (l) = new_label;
  
!   if ((GET_CODE (l) == LABEL_REF
!        || GET_CODE (l) == INSN_LIST)
!       && XEXP (l, 0) == old_label)
!     {
!       XEXP (l, 0) = new_label;
!       if (update_label_nuses)
! 	{
! 	  ++LABEL_NUSES (new_label);
! 	  --LABEL_NUSES (old_label);
! 	}
!       return 0;
!     }
  
    return 0;
  }
  
! /* When *BODY is equal to X or X is directly referenced by *BODY
!    return nonzero, thus FOR_EACH_RTX stops traversing and returns nonzero
!    too, otherwise FOR_EACH_RTX continues traversing *BODY.  */
  
  static int
! rtx_referenced_p_1 (body, x)
!      rtx *body;
!      void *x;
  {
!   rtx y = (rtx) x;
! 
!   if (*body == NULL_RTX)
!     return y == NULL_RTX;
! 
!   /* Return true if a label_ref *BODY refers to label Y.  */
!   if (GET_CODE (*body) == LABEL_REF && GET_CODE (y) == CODE_LABEL)
!     return XEXP (*body, 0) == y;
! 
!   /* If *BODY is a reference to pool constant traverse the constant.  */
!   if (GET_CODE (*body) == SYMBOL_REF
!       && CONSTANT_POOL_ADDRESS_P (*body))
!     return rtx_referenced_p (y, get_pool_constant (*body));
! 
!   /* By default, compare the RTL expressions.  */
!   return rtx_equal_p (*body, y);
  }
  
! /* Return true if X is referenced in BODY.  */
  
  int
! rtx_referenced_p (x, body)
       rtx x;
+      rtx body;
  {
!   return for_each_rtx (&body, rtx_referenced_p_1, x);
  }
  
  /* If INSN is a jump to jumptable insn rturn true and store the label (which


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