[PATCH] Properly limit backwards label scanning in reorg.

David Miller davem@davemloft.net
Sun Oct 30 09:48:00 GMT 2011


My check-gcc runs are completely dominated by the time it takes to
test compile.exp=20001226-1.c

On sparc when compiling this function at -O1 the lowest hanging fruit
is some sillyness in reorg.  It is trying to test a very specific
condition within a well contained code block, but the label scanning
is not constrained properly so things go haywire for large functions.

Specifically it is looking at:

	INSN SEQ (delay_insn
		  delay_slot_1
		  ...)
	...
	NEXT
LABEL:
	next_active_insn (NEXT)

and wants to scan backwards to find if LABEL exists, starting at
next_active_insn (NEXT), and if so are NEXT and delay_slot_1 equal
instructions (equal meaning rtx_equal_p()).

But it just does a blind prev_label() call which will happily scan all
the way to the beginning of the function.  Compilation of this
testcase at -O1 spends 1/3 of it's time in prev_insn ().

In this specific reorg check, there is no reason to scan further back
than INSN.

So I've added a limited scanning helper function to reorg.c for this
purpose and got rid of prev_insn entirely since there are no longer
any users.

Unfortunately, at -O2 this testcase causes exponential cost problems
which are beyond my skills to fix.  Specifically,
tail_merge_optimize() applies it's clusters and
iterate_fix_dominators() hits the worst case O(n) complexity of
et_splay for a CFG structured like this. :-/  %38 of the compilation
time is spent in et_splay().

Committed to trunk.

gcc/

	* reorg.c (label_before_next_insn): New function.
	(relax_delay_slots): Use it instead of prev_label.
	* rtl.h (prev_label): Delete declaration.
	* emit-rtl.c (prev_label): Remove.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180674 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog  |    7 +++++++
 gcc/emit-rtl.c |   15 ---------------
 gcc/reorg.c    |   17 ++++++++++++++++-
 gcc/rtl.h      |    1 -
 4 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0eb34e5..e9bda2b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2011-10-30  David S. Miller  <davem@davemloft.net>
+
+	* reorg.c (label_before_next_insn): New function.
+	(relax_delay_slots): Use it instead of prev_label.
+	* rtl.h (prev_label): Delete declaration.
+	* emit-rtl.c (prev_label): Remove.
+
 2011-10-30  Revital Eres  <revital.eres@linaro.org>
 
 	* modulo-sched.c (generate_prolog_epilog): Mark prolog and epilog
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 8465237..c2bc56b 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -3330,21 +3330,6 @@ next_label (rtx insn)
   return insn;
 }
 
-/* Return the last CODE_LABEL before the insn INSN, or 0 if there is none.  */
-
-rtx
-prev_label (rtx insn)
-{
-  while (insn)
-    {
-      insn = PREV_INSN (insn);
-      if (insn == 0 || LABEL_P (insn))
-	break;
-    }
-
-  return insn;
-}
-
 /* Return the last label to mark the same position as LABEL.  Return LABEL
    itself if it is null or any return rtx.  */
 
diff --git a/gcc/reorg.c b/gcc/reorg.c
index f77a3a0..40d73a7 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -3349,6 +3349,21 @@ delete_jump (rtx insn)
     delete_computation (insn);
 }
 
+static rtx
+label_before_next_insn (rtx x, rtx scan_limit)
+{
+  rtx insn = next_active_insn (x);
+  while (insn)
+    {
+      insn = PREV_INSN (insn);
+      if (insn == scan_limit || insn == NULL_RTX)
+	return NULL_RTX;
+      if (LABEL_P (insn))
+	break;
+    }
+  return insn;
+}
+
 
 /* Once we have tried two ways to fill a delay slot, make a pass over the
    code to try to improve the results and to do such things as more jump
@@ -3634,7 +3649,7 @@ relax_delay_slots (rtx first)
 	 identical to the one in its delay slot.  In this case, we can just
 	 delete the branch and the insn in its delay slot.  */
       if (next && NONJUMP_INSN_P (next)
-	  && prev_label (next_active_insn (next)) == target_label
+	  && label_before_next_insn (next, insn) == target_label
 	  && simplejump_p (insn)
 	  && XVECLEN (pat, 0) == 2
 	  && rtx_equal_p (PATTERN (next), PATTERN (XVECEXP (pat, 0, 1))))
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 81958a5..41536be 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1812,7 +1812,6 @@ extern rtx next_real_insn (rtx);
 extern rtx prev_active_insn (rtx);
 extern rtx next_active_insn (rtx);
 extern int active_insn_p (const_rtx);
-extern rtx prev_label (rtx);
 extern rtx next_label (rtx);
 extern rtx skip_consecutive_labels (rtx);
 extern rtx next_cc0_user (rtx);
-- 
1.7.6.401.g6a319



More information about the Gcc-patches mailing list