From f903b91f37ac738712b8a6494ce261ebccaad9c1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 13 Jul 1998 03:34:12 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 11 ++++++++ gcc/jump.c | 54 +++++++++++++++++++++++++++++--------- gcc/regclass.c | 70 ++++++++++++++++++++++++++++++++++++++------------ gcc/rtl.h | 1 + 4 files changed, 108 insertions(+), 28 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index be1ed8bec49..2ea15267abb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +Mon Jul 13 02:24:08 1998 David S. Miller + + * 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 9956789e5aa..fce3dc02771 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 2bb6b420957..256d92bcc9e 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 7515dcf4c3c..4aa25b2ee0d 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 */ -- 2.30.2