This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] speedup reg_overlap_mentioned_p
- From: bonzini <paolo dot bonzini at polimi dot it>
- To: gcc-patches at gcc dot gnu dot org, mark at codesourcery dot com, gerald at pfeifer dot com
- Date: Fri, 30 Jan 2004 14:12:23 +0100
- Subject: [PATCH] speedup reg_overlap_mentioned_p
- Reply-to: bonzini at gnu dot org
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