aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@cygnus.co.uk>1999-12-02 11:27:31 +0000
committerBernd Schmidt <crux@gcc.gnu.org>1999-12-02 11:27:31 +0000
commit8571e492c885a36b9eb04ff38033a53158881aa2 (patch)
tree77565135ad7321c6fba3bc78f157510f95eec563 /gcc
parent574531f24574d21917a71200ce3ac7850c6d4595 (diff)
downloadgcc-8571e492c885a36b9eb04ff38033a53158881aa2.zip
gcc-8571e492c885a36b9eb04ff38033a53158881aa2.tar.gz
gcc-8571e492c885a36b9eb04ff38033a53158881aa2.tar.bz2
Prevent invalid transformations
From-SVN: r30758
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/loop.c70
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
diff --git a/gcc/loop.c b/gcc/loop.c
index 88cf77a..5921e5e 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -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");
}
}