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] speedup reg_overlap_mentioned_p


This patch speeds up PR13391 by 5% (though the quadratic bottleneck remains) by speeding up reg_overlap_mentioned_p. Speedup for checking disabled may be higher. It is useless to use CONSTANT_P before a big switch statement. It may be worthwhile adding to the beginner's project page an entry about replacing repeated if's with switch statements.

Ok for mainline? For 3.4? (I don't have CVS access)

Paolo

2004-01-30 Paolo Bonzini <bonzini@gnu.org>

      * rtlanal.c (reg_overlap_mentioned_p):  Reorganize
      control flow.

Index: rtlanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtlanal.c,v
retrieving revision 1.173
diff -u -b -r1.173 rtlanal.c
--- rtlanal.c	22 Jan 2004 12:44:54 -0000	1.173
+++ rtlanal.c	30 Jan 2004 13:09:58 -0000
@@ -1519,18 +1519,23 @@
 {
   unsigned int regno, endregno;
 
-  /* Overly conservative.  */
-  if (GET_CODE (x) == STRICT_LOW_PART
-      || GET_CODE (x) == ZERO_EXTRACT
-      || GET_CODE (x) == SIGN_EXTRACT)
-    x = XEXP (x, 0);
-
-  /* If either argument is a constant, then modifying X can not affect IN.  */
-  if (CONSTANT_P (x) || CONSTANT_P (in))
+  /* If either argument is a constant, then modifying X can not
+     affect IN.  Here we look at IN, we can profitably combine
+     CONSTANT_P (x) with the switch statement below.  */
+  if (CONSTANT_P (in))
     return 0;
 
+  for (;;)
+    {
   switch (GET_CODE (x))
     {
+        case STRICT_LOW_PART:
+        case ZERO_EXTRACT:
+        case SIGN_EXTRACT:
+          /* Overly conservative.  */
+          x = XEXP (x, 0);
+          continue;
+
     case SUBREG:
       regno = REGNO (SUBREG_REG (x));
       if (regno < FIRST_PSEUDO_REGISTER)
@@ -1578,10 +1583,14 @@
       }
 
     default:
-      break;
+#ifdef ENABLE_CHECKING
+          if (CONSTANT_P (x))
+#endif
+            return 0;
     }
 
   abort ();
+    }
 }
 
 /* Return the last value to which REG was set prior to INSN.  If we can't
Index: rtlanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtlanal.c,v
retrieving revision 1.173
diff -u -r1.173 rtlanal.c
--- rtlanal.c	22 Jan 2004 12:44:54 -0000	1.173
+++ rtlanal.c	30 Jan 2004 13:09:51 -0000
@@ -1519,69 +1519,78 @@
 {
   unsigned int regno, endregno;
 
-  /* Overly conservative.  */
-  if (GET_CODE (x) == STRICT_LOW_PART
-      || GET_CODE (x) == ZERO_EXTRACT
-      || GET_CODE (x) == SIGN_EXTRACT)
-    x = XEXP (x, 0);
-
-  /* If either argument is a constant, then modifying X can not affect IN.  */
-  if (CONSTANT_P (x) || CONSTANT_P (in))
+  /* If either argument is a constant, then modifying X can not
+     affect IN.  Here we look at IN, we can profitably combine
+     CONSTANT_P (x) with the switch statement below.  */
+  if (CONSTANT_P (in))
     return 0;
 
-  switch (GET_CODE (x))
+  for (;;)
     {
-    case SUBREG:
-      regno = REGNO (SUBREG_REG (x));
-      if (regno < FIRST_PSEUDO_REGISTER)
-	regno = subreg_regno (x);
-      goto do_reg;
-
-    case REG:
-      regno = REGNO (x);
-    do_reg:
-      endregno = regno + (regno < FIRST_PSEUDO_REGISTER
-			  ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
-      return refers_to_regno_p (regno, endregno, in, (rtx*) 0);
-
-    case MEM:
-      {
-	const char *fmt;
-	int i;
-
-	if (GET_CODE (in) == MEM)
-	  return 1;
-
-	fmt = GET_RTX_FORMAT (GET_CODE (in));
-	for (i = GET_RTX_LENGTH (GET_CODE (in)) - 1; i >= 0; i--)
-	  if (fmt[i] == 'e' && reg_overlap_mentioned_p (x, XEXP (in, i)))
-	    return 1;
-
-	return 0;
-      }
-
-    case SCRATCH:
-    case PC:
-    case CC0:
-      return reg_mentioned_p (x, in);
-
-    case PARALLEL:
-      {
-	int i;
-
-	/* If any register in here refers to it we return true.  */
-	for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
-	  if (XEXP (XVECEXP (x, 0, i), 0) != 0
-	      && reg_overlap_mentioned_p (XEXP (XVECEXP (x, 0, i), 0), in))
+      switch (GET_CODE (x))
+        {
+        case STRICT_LOW_PART:
+        case ZERO_EXTRACT:
+        case SIGN_EXTRACT:
+          /* Overly conservative.  */
+          x = XEXP (x, 0);
+          continue;
+
+        case SUBREG:
+          regno = REGNO (SUBREG_REG (x));
+          if (regno < FIRST_PSEUDO_REGISTER)
+	    regno = subreg_regno (x);
+          goto do_reg;
+
+        case REG:
+          regno = REGNO (x);
+        do_reg:
+          endregno = regno + (regno < FIRST_PSEUDO_REGISTER
+			      ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+          return refers_to_regno_p (regno, endregno, in, (rtx*) 0);
+
+        case MEM:
+          {
+	    const char *fmt;
+	    int i;
+
+	    if (GET_CODE (in) == MEM)
 	      return 1;
-	return 0;
-      }
 
-    default:
-      break;
-    }
+	    fmt = GET_RTX_FORMAT (GET_CODE (in));
+	    for (i = GET_RTX_LENGTH (GET_CODE (in)) - 1; i >= 0; i--)
+	      if (fmt[i] == 'e' && reg_overlap_mentioned_p (x, XEXP (in, i)))
+	        return 1;
+
+	    return 0;
+          }
+
+        case SCRATCH:
+        case PC:
+        case CC0:
+          return reg_mentioned_p (x, in);
+
+        case PARALLEL:
+          {
+	    int i;
+
+	    /* If any register in here refers to it we return true.  */
+	    for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
+	      if (XEXP (XVECEXP (x, 0, i), 0) != 0
+	          && reg_overlap_mentioned_p (XEXP (XVECEXP (x, 0, i), 0), in))
+	          return 1;
+	    return 0;
+          }
+
+        default:
+#ifdef ENABLE_CHECKING
+          if (CONSTANT_P (x))
+#endif
+            return 0;
+        }
 
-  abort ();
+      abort ();
+    }
 }
 
 /* Return the last value to which REG was set prior to INSN.  If we can't

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