aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload1.c
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2006-11-17 18:15:29 -0500
committerDJ Delorie <dj@gcc.gnu.org>2006-11-17 18:15:29 -0500
commitd2c9375a6d77a910c3696f3e01e0fafafc21c345 (patch)
treecf353ee37fa3fdee81a2f7a5c7fec82e28b4a4b4 /gcc/reload1.c
parent036a2b7a60782739d05a48d9968cdb8e2129b683 (diff)
downloadgcc-d2c9375a6d77a910c3696f3e01e0fafafc21c345.zip
gcc-d2c9375a6d77a910c3696f3e01e0fafafc21c345.tar.gz
gcc-d2c9375a6d77a910c3696f3e01e0fafafc21c345.tar.bz2
reload1.c (reloads_unique_chain): New.
* reload1.c (reloads_unique_chain): New. (reloads_conflict): Call it. From-SVN: r118953
Diffstat (limited to 'gcc/reload1.c')
-rw-r--r--gcc/reload1.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c
index e644322..88b89fe 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -4794,6 +4794,51 @@ reload_reg_reaches_end_p (unsigned int regno, int opnum, enum reload_type type)
}
}
+
+/* Returns whether R1 and R2 are uniquely chained: the value of one
+ is used by the other, and that value is not used by any other
+ reload for this insn. This is used to partially undo the decision
+ made in find_reloads when in the case of multiple
+ RELOAD_FOR_OPERAND_ADDRESS reloads it converts all
+ RELOAD_FOR_OPADDR_ADDR reloads into RELOAD_FOR_OPERAND_ADDRESS
+ reloads. This code tries to avoid the conflict created by that
+ change. It might be cleaner to explicitly keep track of which
+ RELOAD_FOR_OPADDR_ADDR reload is associated with which
+ RELOAD_FOR_OPERAND_ADDRESS reload, rather than to try to detect
+ this after the fact. */
+static bool
+reloads_unique_chain_p (int r1, int r2)
+{
+ int i;
+
+ /* We only check input reloads. */
+ if (! rld[r1].in || ! rld[r2].in)
+ return false;
+
+ /* Avoid anything with output reloads. */
+ if (rld[r1].out || rld[r2].out)
+ return false;
+
+ /* "chained" means one reload is a component of the other reload,
+ not the same as the other reload. */
+ if (rld[r1].opnum != rld[r2].opnum
+ || rtx_equal_p (rld[r1].in, rld[r2].in)
+ || rld[r1].optional || rld[r2].optional
+ || ! (reg_mentioned_p (rld[r1].in, rld[r2].in)
+ || reg_mentioned_p (rld[r2].in, rld[r1].in)))
+ return false;
+
+ for (i = 0; i < n_reloads; i ++)
+ /* Look for input reloads that aren't our two */
+ if (i != r1 && i != r2 && rld[i].in)
+ {
+ /* If our reload is mentioned at all, it isn't a simple chain. */
+ if (reg_mentioned_p (rld[r1].in, rld[i].in))
+ return false;
+ }
+ return true;
+}
+
/* Return 1 if the reloads denoted by R1 and R2 cannot share a register.
Return 0 otherwise.
@@ -4842,7 +4887,8 @@ reloads_conflict (int r1, int r2)
case RELOAD_FOR_OPERAND_ADDRESS:
return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_INSN
- || r2_type == RELOAD_FOR_OPERAND_ADDRESS);
+ || (r2_type == RELOAD_FOR_OPERAND_ADDRESS
+ && !reloads_unique_chain_p (r1, r2)));
case RELOAD_FOR_OPADDR_ADDR:
return (r2_type == RELOAD_FOR_INPUT