summaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1992-04-02 06:03:52 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1992-04-02 06:03:52 -0500
commit29ebe69a723a07771383e4cddc917521ee6e82bd (patch)
tree672b626b63ce454b1ae9629f4e26a65581e0e2f3 /gcc/optabs.c
parentd64be5ecc9c27800b5e6cf09ec50a1e1ad1d5d2a (diff)
downloadgcc-29ebe69a723a07771383e4cddc917521ee6e82bd.tar.gz
*** empty log message ***
From-SVN: r666
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index b1578531a50..c345fc9d294 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1315,6 +1315,16 @@ emit_no_conflict_block (insns, target, op0, op1, equiv)
an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
note with an operand of EQUIV.
+ Moving assignments to pseudos outside of the block is done to improve
+ the generated code, but is not required to generate correct code,
+ hence being unable to move an assignment is not grounds for not making
+ a libcall block. There are two reasons why it is safe to leave these
+ insns inside the block: First, we know that these pseudos cannot be
+ used in generated RTL outside the block since they are created for
+ temporary purposes within the block. Second, CSE will not record the
+ values of anything set inside a libcall block, so we know they must
+ be dead at the end of the block.
+
Except for the first group of insns (the ones setting pseudos), the
block is delimited by REG_RETVAL and REG_LIBCALL notes. */
@@ -1328,7 +1338,9 @@ emit_libcall_block (insns, target, result, equiv)
rtx prev, next, first, last, insn;
/* First emit all insns that set pseudos. Remove them from the list as
- we go. */
+ we go. Avoid insns that set pseudo which were referenced in previous
+ insns. These can be generated by move_by_pieces, for example,
+ to update an address. */
for (insn = insns; insn; insn = next)
{
@@ -1337,7 +1349,9 @@ emit_libcall_block (insns, target, result, equiv)
next = NEXT_INSN (insn);
if (set != 0 && GET_CODE (SET_DEST (set)) == REG
- && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
+ && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
+ && ! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
+ && ! reg_used_between_p (SET_DEST (set), insns, insn))
{
if (PREV_INSN (insn))
NEXT_INSN (PREV_INSN (insn)) = next;