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
This commit is contained in:
parent
1b07eafaae
commit
f903b91f37
|
@ -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
|
||||
|
|
54
gcc/jump.c
54
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue