aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload1.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2010-03-02 11:56:50 -0700
committerJeff Law <law@gcc.gnu.org>2010-03-02 11:56:50 -0700
commitf6c86fab11ce055b9ba4604b26ae6d7f18a62766 (patch)
tree80025d6478b1b1df18e8c90787c4addeda028ef9 /gcc/reload1.c
parent500cdcb007a8d5238dc60b62e2c3adc1e5cd6697 (diff)
downloadgcc-f6c86fab11ce055b9ba4604b26ae6d7f18a62766.zip
gcc-f6c86fab11ce055b9ba4604b26ae6d7f18a62766.tar.gz
gcc-f6c86fab11ce055b9ba4604b26ae6d7f18a62766.tar.bz2
reload1.c (rtx_p, [...]): Declare.
* reload1.c (rtx_p, substitute_stack): Declare. (substitute): Record addresses of changed rtxs. (gen_reload_chain_without_interm_reg_p): Don't use copy_rtx anymore. Restore the original rtx when complete. (reload): Free subsitute_stack when complete. From-SVN: r157168
Diffstat (limited to 'gcc/reload1.c')
-rw-r--r--gcc/reload1.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c
index ee90f35..02fef2d 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -378,6 +378,21 @@ static int first_label_num;
static char *offsets_known_at;
static HOST_WIDE_INT (*offsets_at)[NUM_ELIMINABLE_REGS];
+/* Stack of addresses where an rtx has been changed. We can undo the
+ changes by popping items off the stack and restoring the original
+ value at each location.
+
+ We use this simplistic undo capability rather than copy_rtx as copy_rtx
+ will not make a deep copy of a normally sharable rtx, such as
+ (const (plus (symbol_ref) (const_int))). If such an expression appears
+ as R1 in gen_reload_chain_without_interm_reg_p, then a shared
+ rtx expression would be changed. See PR 42431. */
+
+typedef rtx *rtx_p;
+DEF_VEC_P(rtx_p);
+DEF_VEC_ALLOC_P(rtx_p,heap);
+static VEC(rtx_p,heap) *substitute_stack;
+
/* Number of labels in the current function. */
static int num_labels;
@@ -1448,6 +1463,8 @@ reload (rtx first, int global)
REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = BITS_PER_UNIT;
#endif
+ VEC_free (rtx_p, heap, substitute_stack);
+
return failure;
}
@@ -5147,9 +5164,8 @@ reloads_unique_chain_p (int r1, int r2)
return true;
}
-
/* The recursive function change all occurrences of WHAT in *WHERE
- onto REPL. */
+ to REPL. */
static void
substitute (rtx *where, const_rtx what, rtx repl)
{
@@ -5162,6 +5178,8 @@ substitute (rtx *where, const_rtx what, rtx repl)
if (*where == what || rtx_equal_p (*where, what))
{
+ /* Record the location of the changed rtx. */
+ VEC_safe_push (rtx_p, heap, substitute_stack, where);
*where = repl;
return;
}
@@ -5209,7 +5227,9 @@ substitute (rtx *where, const_rtx what, rtx repl)
static bool
gen_reload_chain_without_interm_reg_p (int r1, int r2)
{
- bool result;
+ /* Assume other cases in gen_reload are not possible for
+ chain reloads or do need an intermediate hard registers. */
+ bool result = true;
int regno, n, code;
rtx out, in, tem, insn;
rtx last = get_last_insn ();
@@ -5225,7 +5245,7 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
regno = rld[r1].regno >= 0 ? rld[r1].regno : rld[r2].regno;
gcc_assert (regno >= 0);
out = gen_rtx_REG (rld[r1].mode, regno);
- in = copy_rtx (rld[r1].in);
+ in = rld[r1].in;
substitute (&in, rld[r2].in, gen_rtx_REG (rld[r2].mode, regno));
/* If IN is a paradoxical SUBREG, remove it and try to put the
@@ -5259,12 +5279,16 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
}
delete_insns_since (last);
- return result;
}
- /* It looks like other cases in gen_reload are not possible for
- chain reloads or do need an intermediate hard registers. */
- return true;
+ /* Restore the original value at each changed address within R1. */
+ while (!VEC_empty (rtx_p, substitute_stack))
+ {
+ rtx *where = VEC_pop (rtx_p, substitute_stack);
+ *where = rld[r2].in;
+ }
+
+ return result;
}
/* Return 1 if the reloads denoted by R1 and R2 cannot share a register.