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


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:

Fri Nov 30 13:08:02 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	Fri Nov 30 12:59:33 2001
--- gcc/rtlanal.c	Fri Nov 30 13:02:42 2001
*************** get_related_value (x)
*** 339,344 ****
--- 339,502 ----
    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 x;
+   rtx old_x;
+   int i;
+   int j;
+   rtx current_insn;
+   rtx current_x;
+ 
+   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++)
+ 	if (XEXP (x, i) == pc_rtx
+ 	    || XEXP (x, i) == pic_offset_table_rtx
+ 	    || (GET_CODE (XEXP (x, i)) == LABEL_REF
+ 		&& XEXP (XEXP (x, i), 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.  */
+ 
+   current_insn = insn;
+   current_x = x;
+ 
+   for (i = 0; i < 2; i++)
+     {
+       x = XEXP (current_x, i);
+       insn = current_insn;
+ 
+       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 (GET_CODE (x) == LO_SUM)
+ 	{
+ 	  for (j = 0; j < 2; j++)
+ 	    if ((GET_CODE (XEXP (x, j)) == CONST
+ 		 || GET_CODE (XEXP (x, j)) == LABEL_REF)
+ 		&& reg_mentioned_p (label, XEXP (x, j)))
+ 	      break;
+ 
+ 	  if (j >= 2)
+ 	    continue;
+ 
+ 	  x = XEXP (x, 1 - j);
+ 
+ 	  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 (GET_CODE (x) != HIGH)
+ 	    continue;
+ 
+ 	  x = XEXP (x, 0);
+ 	}
+ 
+       if ((GET_CODE (x) == CONST || GET_CODE (x) == LABEL_REF)
+ 	  && reg_mentioned_p (label, x))
+ 	break;
+     }
+ 
+   if (i >= 2)
+     return NULL_RTX;
+ 
+   x = XEXP (current_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 = current_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]