aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@pierdol.cobaltmicro.com>1998-07-13 03:34:12 +0000
committerDavid S. Miller <davem@gcc.gnu.org>1998-07-12 20:34:12 -0700
commitf903b91f37ac738712b8a6494ce261ebccaad9c1 (patch)
tree13bf604991dc573e48b0831d75446e37541a2e97
parent1b07eafaae2a861b9afe080be61cbfc4cdf75c66 (diff)
downloadgcc-f903b91f37ac738712b8a6494ce261ebccaad9c1.zip
gcc-f903b91f37ac738712b8a6494ce261ebccaad9c1.tar.gz
gcc-f903b91f37ac738712b8a6494ce261ebccaad9c1.tar.bz2
More efficient version of Jul 10 bugfix of mine, as discussed on egcs-patches.
More efficient version of Jul 10 bugfix of mine, as discussed on egcs-patches. * regclass.c (reg_scan_mark_refs): New arg min_regno. Only update regscan information for REGs with numbers greater than or equal to this. All callers changed. (reg_scan_update): New function to efficiently update regscan information on the fly. * rtl.h: Add prototype. * jump.c (jump_optimize): Call it when we make a transformation which generates new pseudo-REGs. From-SVN: r21096
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/jump.c54
-rw-r--r--gcc/regclass.c70
-rw-r--r--gcc/rtl.h1
4 files changed, 108 insertions, 28 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index be1ed8b..2ea1526 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+Mon Jul 13 02:24:08 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * regclass.c (reg_scan_mark_refs): New arg min_regno. Only update
+ regscan information for REGs with numbers greater than or equal to
+ this. All callers changed.
+ (reg_scan_update): New function to efficiently update regscan
+ information on the fly.
+ * rtl.h: Add prototype.
+ * jump.c (jump_optimize): Call it when we make a transformation
+ which generates new pseudo-REGs.
+
Sun Jul 12 13:08:14 1998 Jeffrey A Law (law@cygnus.com)
* collect2.c (main): Use "-x c" instead of "-lang-c" for force the
diff --git a/gcc/jump.c b/gcc/jump.c
index 9956789..fce3dc0 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -605,15 +605,6 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
int this_is_simplejump, this_is_condjump, reversep = 0;
int this_is_condjump_in_parallel;
- /* If one of our transformations has created more REGs we
- must rerun reg_scan or else we risk missed optimizations,
- erroneous optimizations, or even worse a crash. */
- if (after_regscan &&
- old_max_reg < max_reg_num ())
- {
- reg_scan (f, max_reg_num (), 0);
- old_max_reg = max_reg_num ();
- }
#if 0
/* If NOT the first iteration, if this is the last jump pass
(just before final), do the special peephole optimizations.
@@ -987,7 +978,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
We set:
TEMP to the "x = exp;" insn.
- TEMP1 to the single set in the "x = exp; insn.
+ TEMP1 to the single set in the "x = exp;" insn.
TEMP2 to "x". */
if (! reload_completed
@@ -1021,6 +1012,12 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
PREV_INSN (temp3), temp);
delete_insn (temp);
reallabelprev = prev_active_insn (JUMP_LABEL (insn));
+
+ if (after_regscan)
+ {
+ reg_scan_update (temp3, NEXT_INSN (next), old_max_reg);
+ old_max_reg = max_reg_num ();
+ }
}
}
@@ -1073,6 +1070,12 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
delete_insn (temp);
delete_insn (temp3);
reallabelprev = prev_active_insn (JUMP_LABEL (insn));
+
+ if (after_regscan)
+ {
+ reg_scan_update (temp6, NEXT_INSN (next), old_max_reg);
+ old_max_reg = max_reg_num ();
+ }
}
}
@@ -1133,6 +1136,12 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
delete_insn (temp);
delete_insn (temp3);
reallabelprev = prev_active_insn (JUMP_LABEL (insn));
+
+ if (after_regscan)
+ {
+ reg_scan_update (temp6, NEXT_INSN (next), old_max_reg);
+ old_max_reg = max_reg_num ();
+ }
}
}
#endif /* HAVE_cc0 */
@@ -1244,7 +1253,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
if (target)
{
- rtx seq1,seq2;
+ rtx seq1,seq2,last;
/* Save the conditional move sequence but don't emit it
yet. On some machines, like the alpha, it is possible
@@ -1266,13 +1275,20 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
emit_insns_before (seq1, temp5);
/* Insert conditional move after insn, to be sure that
the jump and a possible compare won't be separated */
- emit_insns_after (seq2, insn);
+ last = emit_insns_after (seq2, insn);
/* ??? We can also delete the insn that sets X to A.
Flow will do it too though. */
delete_insn (temp);
next = NEXT_INSN (insn);
delete_jump (insn);
+
+ if (after_regscan)
+ {
+ reg_scan_update (seq1, NEXT_INSN (last), old_max_reg);
+ old_max_reg = max_reg_num ();
+ }
+
changed = 1;
continue;
}
@@ -1455,6 +1471,13 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
delete_insn (temp);
next = NEXT_INSN (insn);
delete_jump (insn);
+
+ if (after_regscan)
+ {
+ reg_scan_update (seq, NEXT_INSN (next), old_max_reg);
+ old_max_reg = max_reg_num ();
+ }
+
changed = 1;
continue;
}
@@ -1574,6 +1597,13 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
delete_insn (prev_nonnote_insn (insn));
#endif
delete_insn (insn);
+
+ if (after_regscan)
+ {
+ reg_scan_update (seq, NEXT_INSN (next), old_max_reg);
+ old_max_reg = max_reg_num ();
+ }
+
changed = 1;
continue;
}
diff --git a/gcc/regclass.c b/gcc/regclass.c
index 2bb6b42..256d92b 100644
--- a/gcc/regclass.c
+++ b/gcc/regclass.c
@@ -673,7 +673,7 @@ static void record_address_regs PROTO((rtx, enum reg_class, int));
#ifdef FORBIDDEN_INC_DEC_CLASSES
static int auto_inc_dec_reg_p PROTO((rtx, enum machine_mode));
#endif
-static void reg_scan_mark_refs PROTO((rtx, rtx, int));
+static void reg_scan_mark_refs PROTO((rtx, rtx, int, int));
/* Return the reg_class in which pseudo reg number REGNO is best allocated.
This function is sometimes called before the info has been computed.
@@ -1939,21 +1939,54 @@ reg_scan (f, nregs, repeat)
if (GET_CODE (PATTERN (insn)) == PARALLEL
&& XVECLEN (PATTERN (insn), 0) > max_parallel)
max_parallel = XVECLEN (PATTERN (insn), 0);
- reg_scan_mark_refs (PATTERN (insn), insn, 0);
+ reg_scan_mark_refs (PATTERN (insn), insn, 0, 0);
if (REG_NOTES (insn))
- reg_scan_mark_refs (REG_NOTES (insn), insn, 1);
+ reg_scan_mark_refs (REG_NOTES (insn), insn, 1, 0);
+ }
+}
+
+/* Update 'regscan' information by looking at the insns
+ from FIRST to LAST. Some new REGs have been created,
+ and any REG with number greater than OLD_MAX_REGNO is
+ such a REG. We only update information for those. */
+
+void
+reg_scan_update(first, last, old_max_regno)
+ rtx first;
+ rtx last;
+ int old_max_regno;
+{
+ register rtx insn;
+
+ allocate_reg_info (max_reg_num (), FALSE, FALSE);
+
+ for (insn = first; insn != last; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN
+ || GET_CODE (insn) == CALL_INSN
+ || GET_CODE (insn) == JUMP_INSN)
+ {
+ if (GET_CODE (PATTERN (insn)) == PARALLEL
+ && XVECLEN (PATTERN (insn), 0) > max_parallel)
+ max_parallel = XVECLEN (PATTERN (insn), 0);
+ reg_scan_mark_refs (PATTERN (insn), insn, 0, old_max_regno);
+
+ if (REG_NOTES (insn))
+ reg_scan_mark_refs (REG_NOTES (insn), insn, 1, old_max_regno);
}
}
/* X is the expression to scan. INSN is the insn it appears in.
- NOTE_FLAG is nonzero if X is from INSN's notes rather than its body. */
+ NOTE_FLAG is nonzero if X is from INSN's notes rather than its body.
+ We should only record information for REGs with numbers
+ greater than or equal to MIN_REGNO. */
static void
-reg_scan_mark_refs (x, insn, note_flag)
+reg_scan_mark_refs (x, insn, note_flag, min_regno)
rtx x;
rtx insn;
int note_flag;
+ int min_regno;
{
register enum rtx_code code = GET_CODE (x);
register rtx dest;
@@ -1976,24 +2009,27 @@ reg_scan_mark_refs (x, insn, note_flag)
{
register int regno = REGNO (x);
- REGNO_LAST_NOTE_UID (regno) = INSN_UID (insn);
- if (!note_flag)
- REGNO_LAST_UID (regno) = INSN_UID (insn);
- if (REGNO_FIRST_UID (regno) == 0)
- REGNO_FIRST_UID (regno) = INSN_UID (insn);
+ if (regno >= min_regno)
+ {
+ REGNO_LAST_NOTE_UID (regno) = INSN_UID (insn);
+ if (!note_flag)
+ REGNO_LAST_UID (regno) = INSN_UID (insn);
+ if (REGNO_FIRST_UID (regno) == 0)
+ REGNO_FIRST_UID (regno) = INSN_UID (insn);
+ }
}
break;
case EXPR_LIST:
if (XEXP (x, 0))
- reg_scan_mark_refs (XEXP (x, 0), insn, note_flag);
+ reg_scan_mark_refs (XEXP (x, 0), insn, note_flag, min_regno);
if (XEXP (x, 1))
- reg_scan_mark_refs (XEXP (x, 1), insn, note_flag);
+ reg_scan_mark_refs (XEXP (x, 1), insn, note_flag, min_regno);
break;
case INSN_LIST:
if (XEXP (x, 1))
- reg_scan_mark_refs (XEXP (x, 1), insn, note_flag);
+ reg_scan_mark_refs (XEXP (x, 1), insn, note_flag, min_regno);
break;
case SET:
@@ -2004,7 +2040,8 @@ reg_scan_mark_refs (x, insn, note_flag)
dest = XEXP (dest, 0))
;
- if (GET_CODE (dest) == REG)
+ if (GET_CODE (dest) == REG
+ && REGNO (dest) >= min_regno)
REG_N_SETS (REGNO (dest))++;
/* If this is setting a pseudo from another pseudo or the sum of a
@@ -2021,6 +2058,7 @@ reg_scan_mark_refs (x, insn, note_flag)
if (GET_CODE (SET_DEST (x)) == REG
&& REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER
+ && REGNO (SET_DEST (x)) >= min_regno
/* If the destination pseudo is set more than once, then other
sets might not be to a pointer value (consider access to a
union in two threads of control in the presense of global
@@ -2063,12 +2101,12 @@ reg_scan_mark_refs (x, insn, note_flag)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- reg_scan_mark_refs (XEXP (x, i), insn, note_flag);
+ reg_scan_mark_refs (XEXP (x, i), insn, note_flag, min_regno);
else if (fmt[i] == 'E' && XVEC (x, i) != 0)
{
register int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag);
+ reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag, min_regno);
}
}
}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 7515dcf..4aa25b2 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1449,6 +1449,7 @@ extern void regset_release_memory PROTO ((void));
extern void regclass_init PROTO ((void));
extern void regclass PROTO ((rtx, int));
extern void reg_scan PROTO ((rtx, int, int));
+extern void reg_scan_update PROTO ((rtx, rtx, int));
extern void fix_register PROTO ((char *, int, int));
/* In regmove.c */