diff options
author | Bernd Schmidt <bernds@cygnus.co.uk> | 1999-12-02 11:27:31 +0000 |
---|---|---|
committer | Bernd Schmidt <crux@gcc.gnu.org> | 1999-12-02 11:27:31 +0000 |
commit | 8571e492c885a36b9eb04ff38033a53158881aa2 (patch) | |
tree | 77565135ad7321c6fba3bc78f157510f95eec563 /gcc | |
parent | 574531f24574d21917a71200ce3ac7850c6d4595 (diff) | |
download | gcc-8571e492c885a36b9eb04ff38033a53158881aa2.zip gcc-8571e492c885a36b9eb04ff38033a53158881aa2.tar.gz gcc-8571e492c885a36b9eb04ff38033a53158881aa2.tar.bz2 |
Prevent invalid transformations
From-SVN: r30758
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/loop.c | 70 |
2 files changed, 71 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6f5959f..0662432 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +1999-12-02 Bernd Schmidt <bernds@cygnus.co.uk> + + * loop.c (note_reg_stored): New function. + (struct note_reg_stored_arg): New structure. + (try_copy_prop): Change to be more conservative; only replace within + one extended basic block and stop replacing if a store to the + replacement reg is seen. + 1999-12-02 Nick Clifton <nickc@cygnus.com> * config/fp-bit.c: Initialise all fields of the NAN @@ -339,6 +339,7 @@ static void load_mems PROTO((rtx, rtx, rtx, rtx)); static int insert_loop_mem PROTO((rtx *, void *)); static int replace_loop_mem PROTO((rtx *, void *)); static int replace_loop_reg PROTO((rtx *, void *)); +static void note_reg_stored PROTO((rtx, rtx, void *)); static void try_copy_prop PROTO((rtx, rtx, rtx, rtx, int)); static int replace_label PROTO((rtx *, void *)); @@ -9944,6 +9945,25 @@ load_mems (scan_start, end, loop_top, start) } } +/* For communication between note_reg_stored and its caller. */ +struct note_reg_stored_arg +{ + int set_seen; + rtx reg; +}; + +/* Called via note_stores, record in SET_SEEN whether X, which is written, + is equal to ARG. */ +static void +note_reg_stored (x, setter, arg) + rtx x, setter; + void *arg; +{ + struct note_reg_stored_arg *t = (struct note_reg_stored_arg *)arg; + if (t->reg == x) + t->set_seen = 1; +} + /* Try to replace every occurrence of pseudo REGNO with REPLACEMENT. There must be exactly one insn that sets this pseudo; it will be deleted if all replacements succeed and we can prove that the register @@ -9954,21 +9974,29 @@ try_copy_prop (scan_start, loop_top, end, replacement, regno) rtx scan_start, loop_top, end, replacement; int regno; { + /* This is the reg that we are copying from. */ + rtx reg_rtx = regno_reg_rtx[regno]; rtx init_insn = 0; rtx insn; + /* These help keep track of whether we replaced all uses of the reg. */ + int replaced_last = 0; + int store_is_first = 0; + for (insn = next_insn_in_loop (scan_start, scan_start, end, loop_top); insn != NULL_RTX; insn = next_insn_in_loop (insn, scan_start, end, loop_top)) { rtx set; - rtx array[3]; - array[0] = regno_reg_rtx[regno]; - array[1] = replacement; - array[2] = insn; + /* Only substitute within one extended basic block from the initializing + insn. */ + if (GET_CODE (insn) == CODE_LABEL && init_insn) + break; if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') continue; + + /* Is this the initializing insn? */ set = single_set (insn); if (set && GET_CODE (SET_DEST (set)) == REG @@ -9976,21 +10004,49 @@ try_copy_prop (scan_start, loop_top, end, replacement, regno) { if (init_insn) abort (); + init_insn = insn; + if (REGNO_FIRST_UID (regno) == INSN_UID (insn)) + store_is_first = 1; + } + + /* Only substitute after seeing the initializing insn. */ + if (init_insn && insn != init_insn) + { + struct note_reg_stored_arg arg; + rtx array[3]; + array[0] = reg_rtx; + array[1] = replacement; + array[2] = insn; + + for_each_rtx (&insn, replace_loop_reg, array); + if (REGNO_LAST_UID (regno) == INSN_UID (insn)) + replaced_last = 1; + + /* Stop replacing when REPLACEMENT is modified. */ + arg.reg = replacement; + arg.set_seen = 0; + note_stores (PATTERN (insn), note_reg_stored, &arg); + if (arg.set_seen) + break; } - for_each_rtx (&insn, replace_loop_reg, array); } if (! init_insn) abort (); if (apply_change_group ()) { - if (uid_luid[REGNO_LAST_UID (regno)] < INSN_LUID (end)) + if (loop_dump_stream) + fprintf (loop_dump_stream, " Replaced reg %d", regno); + if (store_is_first && replaced_last) { PUT_CODE (init_insn, NOTE); NOTE_LINE_NUMBER (init_insn) = NOTE_INSN_DELETED; + if (loop_dump_stream) + fprintf (loop_dump_stream, ", deleting init_insn (%d)", + INSN_UID (init_insn)); } if (loop_dump_stream) - fprintf (loop_dump_stream, " Replaced reg %d.\n", regno); + fprintf (loop_dump_stream, ".\n"); } } |