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 to implement get_jump_table_offset for VRP (version 2)


[ I commited a slightly tweaked version that has been tested on
  Dec Alpha 4.0f, IBM rs6000 AIX 4.3, Solaris 7 SPARC, and
  Solaris 7 x86.

  Changes:

    1) Renamed a couple of variables.

    2) Removed LO_SUM handling since there's likely to be
       a REG_EQUAL note for the label_ref present which
       will be returned by find_last_value.

    3) Call find_last_value in one more place in order
       to handle the rs6000. ]

get_jump_table_offset is a generic support routine used by VRP
to determine the RTL expression for the offset into the jump
table.  It may be useful elsewhere.

This patch (combined with VRP) passes make bootstrap and make check
on Dec Alpha 4.0f, Solaris 7 SPARC, and Solaris 7 x86.

ChangeLog:

Thu Dec  6 12:24:36 EST 2001  John Wehle  (john@feith.com)

	* rtl.h (get_jump_table_offset): Declare.
	* rtlanal.c (get_jump_table_offset): Implement.

Enjoy!

-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/rtl.h.ORIGINAL	Fri Nov 30 12:59:45 2001
--- gcc/rtl.h	Fri Nov 30 13:03:49 2001
*************** extern int rtx_varies_p			PARAMS ((rtx, 
*** 1428,1433 ****
--- 1428,1434 ----
  extern int rtx_addr_varies_p		PARAMS ((rtx, int));
  extern HOST_WIDE_INT get_integer_term	PARAMS ((rtx));
  extern rtx get_related_value		PARAMS ((rtx));
+ extern rtx get_jump_table_offset	PARAMS ((rtx, rtx *));
  extern int reg_mentioned_p		PARAMS ((rtx, rtx));
  extern int count_occurrences		PARAMS ((rtx, rtx, int));
  extern int reg_referenced_p		PARAMS ((rtx, rtx));
*** gcc/rtlanal.c.ORIGINAL	Thu Dec  6 12:18:19 2001
--- gcc/rtlanal.c	Mon Dec  3 14:07:54 2001
*************** get_related_value (x)
*** 339,344 ****
--- 339,485 ----
    return 0;
  }
  
+ /* Given a tablejump insn INSN, return the RTL expression for the offset
+    into the jump table.  If the offset cannot be determined, then return
+    NULL_RTX.
+ 
+    If EARLIEST is non-zero, it is a pointer to a place where the earliest
+    insn used in locating the offset was found.  */
+ 
+ rtx
+ get_jump_table_offset (insn, earliest)
+      rtx insn;
+      rtx *earliest;
+ {
+   rtx label;
+   rtx table;
+   rtx set;
+   rtx old_insn;
+   rtx x;
+   rtx old_x;
+   rtx y;
+   rtx old_y;
+   int i;
+   int j;
+ 
+   if (GET_CODE (insn) != JUMP_INSN
+       || ! (label = JUMP_LABEL (insn))
+       || ! (table = NEXT_INSN (label))
+       || GET_CODE (table) != JUMP_INSN
+       || (GET_CODE (PATTERN (table)) != ADDR_VEC
+ 	  && GET_CODE (PATTERN (table)) != ADDR_DIFF_VEC)
+       || ! (set = single_set (insn)))
+     return NULL_RTX;
+ 
+   x = SET_SRC (set);
+ 
+   /* Some targets (eg, ARM) emit a tablejump that also
+      contains the out-of-range target.  */
+   if (GET_CODE (x) == IF_THEN_ELSE
+       && GET_CODE (XEXP (x, 2)) == LABEL_REF)
+     x = XEXP (x, 1);
+ 
+   /* Search backwards and locate the expression stored in X.  */
+   for (old_x = NULL_RTX; GET_CODE (x) == REG && x != old_x;
+        old_x = x, x = find_last_value (x, &insn, NULL_RTX, 0))
+     ;
+ 
+   /* If X is an expression using a relative address then strip
+      off the addition / subtraction of PC, PIC_OFFSET_TABLE_REGNUM,
+      or the jump table label.  */
+   if (GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC
+       && (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS))
+     {
+       for (i = 0; i < 2; i++)
+ 	{
+ 	  old_insn = insn;
+ 	  y = XEXP (x, i);
+ 
+ 	  if (y == pc_rtx || y == pic_offset_table_rtx)
+ 	    break;
+ 
+ 	  for (old_y = NULL_RTX; GET_CODE (y) == REG && y != old_y;
+ 	       old_y = y, y = find_last_value (y, &old_insn, NULL_RTX, 0))
+ 	    ;
+ 
+ 	  if ((GET_CODE (y) == LABEL_REF && XEXP (y, 0) == label))
+ 	    break;
+ 	}
+ 
+       if (i >= 2)
+ 	return NULL_RTX;
+ 
+       x = XEXP (x, 1 - i);
+ 
+       for (old_x = NULL_RTX; GET_CODE (x) == REG && x != old_x;
+ 	   old_x = x, x = find_last_value (x, &insn, NULL_RTX, 0))
+ 	;
+     }
+ 
+   /* Strip off any sign or zero extension.  */
+   if (GET_CODE (x) == SIGN_EXTEND || GET_CODE (x) == ZERO_EXTEND)
+     {
+       x = XEXP (x, 0);
+ 
+       for (old_x = NULL_RTX; GET_CODE (x) == REG && x != old_x;
+ 	   old_x = x, x = find_last_value (x, &insn, NULL_RTX, 0))
+ 	;
+     }
+ 
+   /* If X isn't a MEM then this isn't a tablejump we understand.  */
+   if (GET_CODE (x) != MEM)
+     return NULL_RTX;
+ 
+   /* Strip off the MEM.  */
+   x = XEXP (x, 0);
+ 
+   for (old_x = NULL_RTX; GET_CODE (x) == REG && x != old_x;
+        old_x = x, x = find_last_value (x, &insn, NULL_RTX, 0))
+     ;
+ 
+   /* If X isn't a PLUS than this isn't a tablejump we understand.  */
+   if (GET_CODE (x) != PLUS)
+     return NULL_RTX;
+ 
+   /* At this point we should have an expression representing the jump table
+      plus an offset.  Examine each operand in order to determine which one
+      represents the jump table.  Knowing that tells us that the other operand
+      must represent the offset.  */
+   for (i = 0; i < 2; i++)
+     {
+       old_insn = insn;
+       y = XEXP (x, i);
+ 
+       for (old_y = NULL_RTX; GET_CODE (y) == REG && y != old_y;
+ 	   old_y = y, y = find_last_value (y, &old_insn, NULL_RTX, 0))
+ 	;
+ 
+       if ((GET_CODE (y) == CONST || GET_CODE (y) == LABEL_REF)
+ 	  && reg_mentioned_p (label, y))
+ 	break;
+     }
+ 
+   if (i >= 2)
+     return NULL_RTX;
+ 
+   x = XEXP (x, 1 - i);
+ 
+   /* Strip off the addition / subtraction of PIC_OFFSET_TABLE_REGNUM.  */
+   if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS)
+     for (i = 0; i < 2; i++)
+       if (XEXP (x, i) == pic_offset_table_rtx)
+ 	{
+ 	  x = XEXP (x, 1 - i);
+ 	  break;
+ 	}
+ 
+   if (earliest)
+     *earliest = insn;
+ 
+   /* Return the RTL expression representing the offset.  */
+   return x;
+ }
+ 
  /* Return the number of places FIND appears within X.  If COUNT_DEST is
     zero, we do not count occurrences inside the destination of a SET.  */
  
-------------------------------------------------------------------------
|   Feith Systems  |   Voice: 1-215-646-8000  |  Email: john@feith.com  |
|    John Wehle    |     Fax: 1-215-540-5495  |                         |
-------------------------------------------------------------------------


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