diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e206ac6ae25..e1093ca49ef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +Thu Nov 26 00:19:19 1998 Richard Henderson + + * rtlanal.c (regs_set_between_p): New function. + * rtl.h (regs_set_between_p): Prototype it. + * jump.c (jump_optimize): Use it instead of modified_between_p + in the Sep 2 change. + Wed Nov 25 23:32:02 1998 Ian Dall Matthias Pfaller diff --git a/gcc/jump.c b/gcc/jump.c index 25cae32b3c7..784e63dab71 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -521,7 +521,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan) || ! modified_between_p (SET_SRC (temp4), p, temp2)) /* Verify that registers used by the jump are not clobbered by the instruction being moved. */ - && ! modified_between_p (PATTERN (temp), temp2, + && ! regs_set_between_p (PATTERN (temp), temp2, NEXT_INSN (temp2))) { emit_insn_after_with_line_notes (PATTERN (temp2), p, temp2); @@ -622,7 +622,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan) && ! modified_between_p (SET_SRC (temp4), insert_after, temp) /* Verify that registers used by the jump are not clobbered by the instruction being moved. */ - && ! modified_between_p (PATTERN (temp), temp3, + && ! regs_set_between_p (PATTERN (temp), temp3, NEXT_INSN (temp3)) && invert_jump (temp, JUMP_LABEL (insn))) { diff --git a/gcc/rtl.h b/gcc/rtl.h index c5b816d79dd..1bff7d3d916 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -982,6 +982,7 @@ extern int reg_referenced_p PROTO((rtx, rtx)); extern int reg_used_between_p PROTO((rtx, rtx, rtx)); extern int reg_referenced_between_p PROTO((rtx, rtx, rtx)); extern int reg_set_between_p PROTO((rtx, rtx, rtx)); +extern int regs_set_between_p PROTO((rtx, rtx, rtx)); extern int modified_between_p PROTO((rtx, rtx, rtx)); extern int no_labels_between_p PROTO((rtx, rtx)); extern int modified_in_p PROTO((rtx, rtx)); diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 031d103b34e..0abe2447165 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -499,6 +499,52 @@ reg_set_p (reg, insn) return reg_set_flag; } +/* Similar to reg_set_between_p, but check all registers in X. Return 0 + only if none of them are modified between START and END. Do not + consider non-registers one way or the other. */ + +int +regs_set_between_p (x, start, end) + rtx x; + rtx start, end; +{ + enum rtx_code code = GET_CODE (x); + char *fmt; + int i, j; + + switch (code) + { + case CONST_INT: + case CONST_DOUBLE: + case CONST: + case SYMBOL_REF: + case LABEL_REF: + case PC: + case CC0: + return 0; + + case REG: + return reg_set_between_p (x, start, end); + + default: + break; + } + + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e' && regs_set_between_p (XEXP (x, i), start, end)) + return 1; + + else if (fmt[i] == 'E') + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + if (regs_set_between_p (XVECEXP (x, i, j), start, end)) + return 1; + } + + return 0; +} + /* Similar to reg_set_between_p, but check all registers in X. Return 0 only if none of them are modified between START and END. Return 1 if X contains a MEM; this routine does not perform any memory aliasing. */