From: Bernd Schmidt Date: Mon, 18 Dec 2000 14:34:03 +0000 (+0000) Subject: Backport some flow fixes for deleting switch tables X-Git-Tag: prereleases/gcc-2.95.3-test1~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=85ccf2e731a9a5b976cc39bb0a7353a1201e75e2;p=thirdparty%2Fgcc.git Backport some flow fixes for deleting switch tables From-SVN: r38349 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8bc4f9f9c90f..9ced870d7e60 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,19 @@ 2000-12-18 Bernd Schmidt + 2000-03-24 Geoff Keating + * flow.c (propagate_block): When we delete an ADDR_VEC, + also delete the BARRIER following it if there is one. + + Wed Oct 27 14:10:27 1999 Geoffrey Keating + * flow.c (propagate_block): When the last reference to a label + before an ADDR_VEC is deleted because the reference is a dead + store, delete the ADDR_VEC. + + 2000-03-19 Richard Henderson + * flow.c (delete_block): Delete the addr_vec along with the block. + (flow_delete_insn): Decrement LABEL_NUSES when deleting insns that + reference labels. + 2000-12-02 Bernd Schmidt * reload1.c (free_for_value_p): New function, frontend to reload_reg_free_for_value_p. All callers of the latter now call diff --git a/gcc/flow.c b/gcc/flow.c index ac8fd6337ff2..75b6ef485759 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -1681,7 +1681,7 @@ delete_block (b) basic_block b; { int deleted_handler = 0; - rtx insn, end; + rtx insn, end, tmp; /* If the head of this block is a CODE_LABEL, then it might be the label for an exception handler which can't be reached. @@ -1728,11 +1728,21 @@ delete_block (b) } } - /* Selectively unlink the insn chain. Include any BARRIER that may - follow the basic block. */ - end = next_nonnote_insn (b->end); - if (!end || GET_CODE (end) != BARRIER) - end = b->end; + /* Include any jump table following the basic block. */ + end = b->end; + if (GET_CODE (end) == JUMP_INSN + && (tmp = JUMP_LABEL (end)) != NULL_RTX + && (tmp = NEXT_INSN (tmp)) != NULL_RTX + && GET_CODE (tmp) == JUMP_INSN + && (GET_CODE (PATTERN (tmp)) == ADDR_VEC + || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC)) + end = tmp; + + /* Include any barrier that may follow the basic block. */ + tmp = next_nonnote_insn (b->end); + if (tmp && GET_CODE (tmp) == BARRIER) + end = tmp; + delete_insn_chain (insn, end); no_delete_insns: @@ -1796,6 +1806,7 @@ flow_delete_insn (insn) { rtx prev = PREV_INSN (insn); rtx next = NEXT_INSN (insn); + rtx note; PREV_INSN (insn) = NULL_RTX; NEXT_INSN (insn) = NULL_RTX; @@ -1815,6 +1826,10 @@ flow_delete_insn (insn) if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn)) LABEL_NUSES (JUMP_LABEL (insn))--; + /* Also if deleting an insn that references a label. */ + else if ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX) + LABEL_NUSES (XEXP (note, 0))--; + return next; } @@ -2721,6 +2736,48 @@ propagate_block (old, first, last, final, significant, bnum, remove_dead_code) can cause trouble for first or last insn in a basic block. */ if (final && insn_is_dead) { + rtx inote; + /* If the insn referred to a label, note that the label is + now less used. */ + for (inote = REG_NOTES (insn); inote; inote = XEXP (inote, 1)) + { + if (REG_NOTE_KIND (inote) == REG_LABEL) + { + rtx label = XEXP (inote, 0); + rtx next; + LABEL_NUSES (label)--; + + /* If this label was attached to an ADDR_VEC, it's + safe to delete the ADDR_VEC. In fact, it's pretty much + mandatory to delete it, because the ADDR_VEC may + be referencing labels that no longer exist. */ + if (LABEL_NUSES (label) == 0 + && (next = next_nonnote_insn (label)) != NULL + && GET_CODE (next) == JUMP_INSN + && (GET_CODE (PATTERN (next)) == ADDR_VEC + || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC)) + { + rtx pat = PATTERN (next); + int diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC; + int len = XVECLEN (pat, diff_vec_p); + int i; + for (i = 0; i < len; i++) + LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0))--; + PUT_CODE (next, NOTE); + NOTE_LINE_NUMBER (next) = NOTE_INSN_DELETED; + NOTE_SOURCE_FILE (next) = 0; + + if ((next = next_nonnote_insn (label)) != NULL + && GET_CODE (next) == BARRIER) + { + PUT_CODE (next, NOTE); + NOTE_LINE_NUMBER (next) = NOTE_INSN_DELETED; + NOTE_SOURCE_FILE (next) = 0; + } + } + } + } + PUT_CODE (insn, NOTE); NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; NOTE_SOURCE_FILE (insn) = 0;