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]

FOR_EACH_RTX



Hi
This patch adds macro equivalent of for_each_rtx function.  It's advantage
is the fact, that it is not recursive and manage it's own stack instead,
so it is usually faster and allows you to drop in code directly, instead
of writing separate function and on i386 even usually results in shorter
code (that was quite surprise to me).

Also FOR_EACH_RTX_PUSH macro is provided that allows you to push new
expressions to the stack while processing.

The disadvantage is that it works by pushing all arguments first and
then processing, so when you have ADDR_VEC with 1000 elements, you get
them all to the stack first.  In practice this don't seems to be problem
and I am getting noticable speedups by converting the most expensive
recursive rtx walking functions to use this macro.

Wed Sep 20 21:08:26 CEST 2000  Jan Hubicka  <jh@suse.cz>
	* rtl.h (FOR_EACH_RTX, FOR_EACH_RTXP, FOR_EACH_RTX_PUSH,
	FOR_EACH_RTXP_PUSH, FOR_EACH_RTX_STACK): New macros.

--- ../../egcs-20000918.orig/gcc/rtl.h	Wed Sep 20 11:18:04 2000
+++ rtl.h	Wed Sep 20 12:23:23 2000
@@ -414,6 +414,143 @@
 
 #define REG_NOTES(INSN)	XEXP(INSN, 6)
 
+/* Execute BODY for PAT and for pointer to each subexpression of PATP
+   if RECURSE is 1.  RTX is used to hold pointer to current rtx and
+   RECURSE is always evaulated after BODY.
+ 
+   We manage our own stack to speed up recursion.  Since rtx expressions
+   are usually small, we do have stack of size 256 allocated on the
+   runtime stack.  In case the stack overflow, we allocate secondary
+   stack on the heap and double it every time the new stack overflows.
+   This should be rare, but there are large expressions (such as ADDR_VECs
+   that stress even this part.  */
+#define FOR_EACH_RTX_STACK 256
+#define FOR_EACH_RTX(PAT,RTX,BODY,RECURSE) \
+{									\
+  rtx stack_[FOR_EACH_RTX_STACK];					\
+  rtx *stack2_ = NULL;							\
+  int pos_ = 1;								\
+  rtx RTX;								\
+  stack_[0] = PAT;							\
+  while (pos_)								\
+    {									\
+      if (pos_ <= FOR_EACH_RTX_STACK)					\
+	RTX = stack_[--pos_];						\
+      else								\
+	RTX = stack2_[--pos_];						\
+      BODY;								\
+      if (!RTX)								\
+        continue;							\
+      if (RECURSE)							\
+	{								\
+	  RTX_CODE code_ = GET_CODE (RTX);				\
+	  int length_ = GET_RTX_LENGTH (code_), i_;			\
+	  const char *fmt_ = GET_RTX_FORMAT (code_);			\
+	  for (i_ = 0; i_ < length_; i_++)				\
+	    switch (fmt_[i_])						\
+	      {								\
+	      case 'e':							\
+		FOR_EACH_RTX_PUSH (XEXP (RTX, i_));			\
+		break;							\
+	      case 'V':							\
+	      case 'E':							\
+		if (XVEC (RTX, i_) != 0)				\
+		  {							\
+		    int j_, l_ = XVECLEN (RTX, i_);			\
+		    for (j_ = 0; j_ < l_; j_++)				\
+		      FOR_EACH_RTX_PUSH (XVECEXP (RTX, i_, j_));       	\
+		  }							\
+		break;							\
+	      default:							\
+		break;							\
+	      }								\
+	}								\
+    }									\
+  if (stack2_)								\
+   free (stack2_);							\
+}
+/* FOR_EACH_RTX_PUSH is used to push expressions onto FOR_EACH_RTX stack.  */
+#define FOR_EACH_RTX_PUSH(exp)						\
+{									\
+  if (pos_ < FOR_EACH_RTX_STACK)					\
+    stack_[pos_++] = (exp);						\
+  else									\
+    {									\
+      if (!stack2_)							\
+	stack2_ = (rtx *)xmalloc (FOR_EACH_RTX_STACK * 2		\
+				   * sizeof (*stack2_));		\
+      /* True only for the power of 2.  */				\
+      else if (!((pos_ - 1) & pos_))					\
+	stack2_ = (rtx *)xrealloc (stack2_, pos_ * 2			\
+				    * sizeof (*stack2_));		\
+      stack2_[pos_++] = (exp);						\
+    }									\
+}
+/* Same as FOR_EACH_RTX, but keep track of pointer to the expressions.
+   PATP is now pointer to the pattern we want to explore and RTXP holds
+   pointer to the subexpressions, so it can be substituted.  */
+#define FOR_EACH_RTXP(PATP,RTXP,BODY,RECURSE) \
+{									\
+  rtx *stack_[FOR_EACH_RTX_STACK];					\
+  rtx **stack2_ = NULL;							\
+  int pos_ = 1;								\
+  rtx *RTXP;								\
+  stack_[0] = PATP;							\
+  while (pos_)								\
+    {									\
+      if (pos_ <= FOR_EACH_RTX_STACK)					\
+	RTXP = stack_[--pos_];						\
+      else								\
+	RTXP = stack2_[--pos_];						\
+      BODY;								\
+      if (!*RTXP)							\
+        continue;							\
+      if (RECURSE)							\
+	{								\
+	  RTX_CODE code_ = GET_CODE (*RTXP);				\
+	  int length_ = GET_RTX_LENGTH (code_), i_;			\
+	  const char *fmt_ = GET_RTX_FORMAT (code_);			\
+	  for (i_ = 0; i_ < length_; i_++)				\
+	    switch (fmt_[i_])						\
+	      {								\
+	      case 'e':							\
+		FOR_EACH_RTXP_PUSH (&XEXP (*RTXP, i_));			\
+		break;							\
+	      case 'V':							\
+	      case 'E':							\
+		if (XVEC (*RTXP, i_) != 0)				\
+		  {							\
+		    int j_, l_ = XVECLEN (*RTXP, i_);			\
+		    for (j_ = 0; j_ < l_; j_++)				\
+		      FOR_EACH_RTXP_PUSH (&XVECEXP (*RTXP, i_, j_));	\
+		  }							\
+		break;							\
+	      default:							\
+		break;							\
+	      }								\
+	}								\
+    }									\
+  if (stack2_)								\
+   free (stack2_);							\
+}
+/* FOR_EACH_RTX_PUSH is used to push expressions onto FOR_EACH_RTXP stack.  */
+#define FOR_EACH_RTXP_PUSH(exp)						\
+{									\
+  if (pos_ < FOR_EACH_RTX_STACK)					\
+    stack_[pos_++] = (exp);						\
+  else									\
+    {									\
+      if (!stack2_)							\
+	stack2_ = (rtx **)xmalloc (FOR_EACH_RTX_STACK * 2		\
+				   * sizeof (*stack2_));		\
+      /* True only for the power of 2.  */				\
+      else if (!((pos_ - 1) & pos_))					\
+	stack2_ = (rtx **)xrealloc (stack2_, pos_ * 2			\
+				    * sizeof (*stack2_));		\
+      stack2_[pos_++] = (exp);						\
+    }									\
+}
+
 /* Don't forget to change reg_note_name in rtl.c.  */
 enum reg_note
 {

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