This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patches for the 2.95 branch
- To: gcc-patches at gcc dot gnu dot org
- Subject: Patches for the 2.95 branch
- From: Bernd Schmidt <bernds at redhat dot com>
- Date: Thu, 30 Nov 2000 11:44:07 +0000 (GMT)
- cc: Franz dot Sirl-kernel at lauterbach dot com
I'll apply the following patches, one by one, to the 2.95 branch. I've
bootstrapped this set on i686-linux, sparc-sun-solaris2.5.1 and alphaev6-linux
and regression tested it on the same targets against the current testsuite.
These patches are mostly taken from Franz Sirl's patchkit.
Bernd
2000-09-01 Jim Wilson <wilson@cygnus.com>
* loop.c (check_final_value): Check for biv use before checking for
giv use. Check for both biv and giv uses. Always set last_giv_use
if there is a giv use.
Based on a patch from Geoff Keating <geoffk@redhat.com>:
* loop.c (basic_induction_var): If a REG is set from something
that is not a biv, then the REG is not a biv. Even if it is
earlier set from something that is a biv.
2000-09-29 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
* loop.c (check_final_value): A GIV is not replaceable if used
before set.
Sun Oct 10 13:28:48 1999 Bernd Schmidt <bernds@redhat.co.uk>
* loop.c (find_and_verify_loops): When looking for a BARRIER, don't
use one before a jump table.
Fri Jul 9 10:48:28 1999 Bernd Schmidt <bernds@redhat.co.uk>
* loop.c (check_dbra_loop): When reversing a loop, delete all
REG_EQUAL notes referencing the reversed biv except those which are
for a giv based on it.
2000-11-24 Bernd Schmidt <bernds@redhat.co.uk>
* reload1.c (conflicts_with_override): New function.
(emit_input_reload_insns): Use it to tighten test for validity
of substituting into output of previous insn.
Wed Oct 27 03:09:23 1999 J"orn Rennecke <amylaar@redhat.co.uk>
* reload.h (earlyclobber_operand_p): Declare.
* reload.c (earlyclobber_operand_p): Don't declare. No longer static.
* reload1.c (reload_reg_free_for_value_p): RELOAD_OTHER reloads with
an earlyclobbered output conflict with RELOAD_INPUT reloads - handle
case where the RELOAD_OTHER reload is new. Use
earlyclobber_operand_p.
2000-01-12 Bernd Schmidt <bernds@redhat.co.uk>
* reload1.c (reload_reg_unavailable): New static variable.
(reload_reg_free_p): Test it.
(reload_reg_free_for_value_p): Test it instead of reload_reg_used.
(choose_reload_regs_init): Compute it.
Thu Jul 6 18:30:36 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* reload.c (push_reload): When seeing if can reuse a register,
check extra registers against widest of INMODE and OUTMODE.
1999-11-29 Bernd Schmidt <bernds@redhat.co.uk>
* reload.c (push_reload): When looking for a register to put into
reg_rtx, make sure all hard regs in a multi-reg register are in the
right class and nonfixed.
1999-11-29 Joern Rennecke <amylaar@redhat.co.uk>
* reload1.c (reloads_conflict): Reverse test comparing operand
numbers when testing for conflict between output/outaddr reloads.
2000-07-12 Richard Henderson <rth@redhat.com>
* reload.c (push_secondary_reload): Make sure to add the new
reload at the end, after acquiring secondary memory.
2000-09-14 Alexandre Oliva <aoliva@redhat.com>, Bernd Schmidt <bernds@redhat.co.uk>
* reload.c (find_reloads_address_1): Generate reloads for auto_inc
pseudos that refer to the original pseudos, not only to their
equivalent memory locations.
2000-09-18 Bernd Schmidt <bernds@redhat.co.uk>
* reload1.c (forget_old_reloads_1): If a hard reg is stored, clear
its entry in spill_reg_store.
Tue Oct 26 00:41:54 1999 Bernd Schmidt <bernds@cygnus.co.uk>
* reload1.c (reload_reg_free_for_value_p): Show
RELOAD_FOR_OTHER_ADDRESS reloads can conflict with RELOAD_OTHER
reloads.
2000-02-26 Geoff Keating <geoffk@cygnus.com>
* reload1.c (do_output_reload): Check reg_reloaded_valid before
looking at reg_reloaded_contents.
Thu Apr 13 19:39:56 2000 Clinton Popetz <cpopetz@cygnus.com>
* emit-rtl.c (try_split): Avoid infinite loop if the split
results in a sequence that contains the original insn.
1999-12-14 Bernd Schmidt <bernds@cygnus.co.uk>
* combine.c (combine_simplify_rtx): Don't make shared rtl.
(simplify_logical): Likewise.
Sat May 20 07:27:35 2000 Alexandre Oliva <aoliva@cygnus.com>
* fold-const.c (make_range): Handle degenerated intervals.
Fixes c-torture/execute/991221-1.c
2000-07-15 Michael Meissner <meissner@redhat.com>
* fold-const.c (fold): When optimizing FOO++ == CONST into ++FOO
== CONST + INCREMENT, don't overwrite the tree node for FOO++,
create a new node instead.
2000-01-01 Bernd Schmidt <bernds@cygnus.co.uk>
* expmed.c (emit_store_flag): Prevent losing a pending stack
adjust the same way we prevent losing queued increments.
Index: gcc/combine.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/combine.c,v
retrieving revision 1.62.4.1
diff -u -p -r1.62.4.1 combine.c
--- gcc/combine.c 1999/10/18 07:52:32 1.62.4.1
+++ gcc/combine.c 2000/11/29 15:16:54
@@ -4015,7 +4015,8 @@ simplify_rtx (x, op0_mode, last, in_dest
gen_binary (MULT, mode,
XEXP (XEXP (x, 0), 0), XEXP (x, 1)),
gen_binary (MULT, mode,
- XEXP (XEXP (x, 0), 1), XEXP (x, 1))));
+ XEXP (XEXP (x, 0), 1),
+ copy_rtx (XEXP (x, 1)))));
if (GET_CODE (x) != MULT)
return x;
@@ -4954,7 +4955,8 @@ simplify_logical (x, last)
x = apply_distributive_law
(gen_binary (GET_CODE (op0), mode,
gen_binary (AND, mode, XEXP (op0, 0), op1),
- gen_binary (AND, mode, XEXP (op0, 1), op1)));
+ gen_binary (AND, mode, XEXP (op0, 1),
+ copy_rtx (op1))));
if (GET_CODE (x) != AND)
return x;
}
@@ -4963,7 +4965,8 @@ simplify_logical (x, last)
return apply_distributive_law
(gen_binary (GET_CODE (op1), mode,
gen_binary (AND, mode, XEXP (op1, 0), op0),
- gen_binary (AND, mode, XEXP (op1, 1), op0)));
+ gen_binary (AND, mode, XEXP (op1, 1),
+ copy_rtx (op0))));
/* Similarly, taking advantage of the fact that
(and (not A) (xor B C)) == (xor (ior A B) (ior A C)) */
@@ -4972,13 +4975,14 @@ simplify_logical (x, last)
return apply_distributive_law
(gen_binary (XOR, mode,
gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)),
- gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 1))));
+ gen_binary (IOR, mode, copy_rtx (XEXP (op0, 0)),
+ XEXP (op1, 1))));
else if (GET_CODE (op1) == NOT && GET_CODE (op0) == XOR)
return apply_distributive_law
(gen_binary (XOR, mode,
gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 0)),
- gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 1))));
+ gen_binary (IOR, mode, copy_rtx (XEXP (op1, 0)), XEXP (op0, 1))));
break;
case IOR:
@@ -5004,7 +5008,8 @@ simplify_logical (x, last)
x = apply_distributive_law
(gen_binary (AND, mode,
gen_binary (IOR, mode, XEXP (op0, 0), op1),
- gen_binary (IOR, mode, XEXP (op0, 1), op1)));
+ gen_binary (IOR, mode, XEXP (op0, 1),
+ copy_rtx (op1))));
if (GET_CODE (x) != IOR)
return x;
@@ -5015,7 +5020,8 @@ simplify_logical (x, last)
x = apply_distributive_law
(gen_binary (AND, mode,
gen_binary (IOR, mode, XEXP (op1, 0), op0),
- gen_binary (IOR, mode, XEXP (op1, 1), op0)));
+ gen_binary (IOR, mode, XEXP (op1, 1),
+ copy_rtx (op0))));
if (GET_CODE (x) != IOR)
return x;
Index: gcc/emit-rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/emit-rtl.c,v
retrieving revision 1.59.4.4
diff -u -p -r1.59.4.4 emit-rtl.c
--- gcc/emit-rtl.c 1999/08/11 07:28:52 1.59.4.4
+++ gcc/emit-rtl.c 2000/11/29 15:16:59
@@ -2359,10 +2359,18 @@ try_split (pat, trial, last)
it, in turn, will be split (SFmode on the 29k is an example). */
if (GET_CODE (seq) == SEQUENCE)
{
+ int i;
+
+ /* Avoid infinite loop if any insn of the result matches
+ the original pattern. */
+ for (i = 0; i < XVECLEN (seq, 0); i++)
+ if (GET_CODE (XVECEXP (seq, 0, i)) == INSN
+ && rtx_equal_p (PATTERN (XVECEXP (seq, 0, i)), pat))
+ return trial;
+
/* If we are splitting a JUMP_INSN, look for the JUMP_INSN in
SEQ and copy our JUMP_LABEL to it. If JUMP_LABEL is non-zero,
increment the usage count so we don't delete the label. */
- int i;
if (GET_CODE (trial) == JUMP_INSN)
for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
Index: gcc/expmed.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expmed.c,v
retrieving revision 1.31.4.1
diff -u -p -r1.31.4.1 expmed.c
--- gcc/expmed.c 1999/06/28 03:09:17 1.31.4.1
+++ gcc/expmed.c 2000/11/29 15:17:00
@@ -4194,9 +4194,11 @@ emit_store_flag (target, code, op0, op1,
comparison and then the scc insn.
compare_from_rtx may call emit_queue, which would be deleted below
- if the scc insn fails. So call it ourselves before setting LAST. */
+ if the scc insn fails. So call it ourselves before setting LAST.
+ Likewise for do_pending_stack_adjust. */
emit_queue ();
+ do_pending_stack_adjust ();
last = get_last_insn ();
comparison
Index: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/fold-const.c,v
retrieving revision 1.64.4.6
diff -u -p -r1.64.4.6 fold-const.c
--- gcc/fold-const.c 1999/12/24 18:05:27 1.64.4.6
+++ gcc/fold-const.c 2000/11/29 15:17:05
@@ -3259,8 +3259,17 @@ make_range (exp, pin_p, plow, phigh)
low = range_binop (PLUS_EXPR, type, n_high, 0,
integer_one_node, 0);
high = range_binop (MINUS_EXPR, type, n_low, 0,
- integer_one_node, 0);
- in_p = ! in_p;
+ integer_one_node, 0);
+
+ /* If the range is of the form +/- [ x+1, x ], we won't
+ be able to normalize it. But then, it represents the
+ whole range or the empty set, so make it +/- [ -, - ].
+ */
+ if (tree_int_cst_equal (n_low, low)
+ && tree_int_cst_equal (n_high, high))
+ low = high = 0;
+ else
+ in_p = ! in_p;
}
else
low = n_low, high = n_high;
@@ -5625,8 +5634,16 @@ fold (expr)
tree newconst
= fold (build (PLUS_EXPR, TREE_TYPE (varop),
constop, TREE_OPERAND (varop, 1)));
- TREE_SET_CODE (varop, PREINCREMENT_EXPR);
+ /* Do not overwrite the current varop to be a preincrement,
+ create a new node so that we won't confuse our caller who
+ might create trees and throw them away, reusing the
+ arguments that they passed to build. This shows up in
+ the THEN or ELSE parts of ?: being postincrements. */
+ varop = build (PREINCREMENT_EXPR, TREE_TYPE (varop),
+ TREE_OPERAND (varop, 0),
+ TREE_OPERAND (varop, 1));
+
/* If VAROP is a reference to a bitfield, we must mask
the constant by the width of the field. */
if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
@@ -5669,9 +5686,9 @@ fold (expr)
}
- t = build (code, type, TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1));
- TREE_OPERAND (t, constopnum) = newconst;
+ t = build (code, type,
+ (constopnum == 0) ? newconst : varop,
+ (constopnum == 1) ? newconst : varop);
return t;
}
}
@@ -5684,7 +5701,15 @@ fold (expr)
tree newconst
= fold (build (MINUS_EXPR, TREE_TYPE (varop),
constop, TREE_OPERAND (varop, 1)));
- TREE_SET_CODE (varop, PREDECREMENT_EXPR);
+
+ /* Do not overwrite the current varop to be a predecrement,
+ create a new node so that we won't confuse our caller who
+ might create trees and throw them away, reusing the
+ arguments that they passed to build. This shows up in
+ the THEN or ELSE parts of ?: being postdecrements. */
+ varop = build (PREDECREMENT_EXPR, TREE_TYPE (varop),
+ TREE_OPERAND (varop, 0),
+ TREE_OPERAND (varop, 1));
if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
&& DECL_BIT_FIELD(TREE_OPERAND
@@ -5723,9 +5748,9 @@ fold (expr)
}
- t = build (code, type, TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1));
- TREE_OPERAND (t, constopnum) = newconst;
+ t = build (code, type,
+ (constopnum == 0) ? newconst : varop,
+ (constopnum == 1) ? newconst : varop);
return t;
}
}
Index: gcc/loop.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/loop.c,v
retrieving revision 1.156.4.12
diff -u -p -r1.156.4.12 loop.c
--- gcc/loop.c 2000/03/08 04:47:42 1.156.4.12
+++ gcc/loop.c 2000/11/29 15:17:10
@@ -2829,16 +2829,30 @@ find_and_verify_loops (f)
rtx target
= JUMP_LABEL (insn) ? JUMP_LABEL (insn) : get_last_insn ();
int target_loop_num = uid_loop_num[INSN_UID (target)];
- rtx loc;
+ rtx loc, loc2;
for (loc = target; loc; loc = PREV_INSN (loc))
if (GET_CODE (loc) == BARRIER
+ /* Don't move things inside a tablejump. */
+ && ((loc2 = next_nonnote_insn (loc)) == 0
+ || GET_CODE (loc2) != CODE_LABEL
+ || (loc2 = next_nonnote_insn (loc2)) == 0
+ || GET_CODE (loc2) != JUMP_INSN
+ || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
+ && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
&& uid_loop_num[INSN_UID (loc)] == target_loop_num)
break;
if (loc == 0)
for (loc = target; loc; loc = NEXT_INSN (loc))
if (GET_CODE (loc) == BARRIER
+ /* Don't move things inside a tablejump. */
+ && ((loc2 = next_nonnote_insn (loc)) == 0
+ || GET_CODE (loc2) != CODE_LABEL
+ || (loc2 = next_nonnote_insn (loc2)) == 0
+ || GET_CODE (loc2) != JUMP_INSN
+ || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
+ && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
&& uid_loop_num[INSN_UID (loc)] == target_loop_num)
break;
@@ -5678,6 +5692,7 @@ check_final_value (v, loop_start, loop_e
or all uses follow that insn in the same basic block),
- its final value can be calculated (this condition is different
than the one above in record_giv)
+ - it's not used before it's set
- no assignments to the biv occur during the giv's lifetime. */
#if 0
@@ -5689,7 +5704,7 @@ check_final_value (v, loop_start, loop_e
if ((final_value = final_giv_value (v, loop_start, loop_end, n_iterations))
&& (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn)))
{
- int biv_increment_seen = 0;
+ int biv_increment_seen = 0, before_giv_insn = 0;
rtx p = v->insn;
rtx last_giv_use;
@@ -5719,26 +5734,35 @@ check_final_value (v, loop_start, loop_e
{
p = NEXT_INSN (p);
if (p == loop_end)
- p = NEXT_INSN (loop_start);
+ {
+ before_giv_insn = 1;
+ p = NEXT_INSN (loop_start);
+ }
if (p == v->insn)
break;
if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
|| GET_CODE (p) == CALL_INSN)
{
- if (biv_increment_seen)
+ /* It is possible for the BIV increment to use the GIV if we
+ have a cycle. Thus we must be sure to check each insn for
+ both BIV and GIV uses, and we must check for BIV uses
+ first. */
+
+ if (! biv_increment_seen
+ && reg_set_p (v->src_reg, PATTERN (p)))
+ biv_increment_seen = 1;
+
+ if (reg_mentioned_p (v->dest_reg, PATTERN (p)))
{
- if (reg_mentioned_p (v->dest_reg, PATTERN (p)))
+ if (biv_increment_seen || before_giv_insn)
{
v->replaceable = 0;
v->not_replaceable = 1;
break;
}
+ last_giv_use = p;
}
- else if (reg_set_p (v->src_reg, PATTERN (p)))
- biv_increment_seen = 1;
- else if (reg_mentioned_p (v->dest_reg, PATTERN (p)))
- last_giv_use = p;
}
}
@@ -5983,6 +6007,7 @@ basic_induction_var (x, mode, dest_reg,
insn = p;
while (1)
{
+ rtx dest;
do {
insn = PREV_INSN (insn);
} while (insn && GET_CODE (insn) == NOTE
@@ -5994,20 +6019,26 @@ basic_induction_var (x, mode, dest_reg,
if (set == 0)
break;
- if ((SET_DEST (set) == x
- || (GET_CODE (SET_DEST (set)) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))
- <= UNITS_PER_WORD)
- && (GET_MODE_CLASS (GET_MODE (SET_DEST (set)))
- == MODE_INT)
- && SUBREG_REG (SET_DEST (set)) == x))
- && basic_induction_var (SET_SRC (set),
- (GET_MODE (SET_SRC (set)) == VOIDmode
- ? GET_MODE (x)
- : GET_MODE (SET_SRC (set))),
- dest_reg, insn,
- inc_val, mult_val, location))
- return 1;
+ dest = SET_DEST (set);
+ if (dest == x
+ || (GET_CODE (dest) == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD)
+ && (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)
+ && SUBREG_REG (dest) == x))
+ return basic_induction_var (SET_SRC (set),
+ (GET_MODE (SET_SRC (set)) == VOIDmode
+ ? GET_MODE (x)
+ : GET_MODE (SET_SRC (set))),
+ dest_reg, insn,
+ inc_val, mult_val, location);
+
+ while (GET_CODE (dest) == SIGN_EXTRACT
+ || GET_CODE (dest) == ZERO_EXTRACT
+ || GET_CODE (dest) == SUBREG
+ || GET_CODE (dest) == STRICT_LOW_PART)
+ dest = XEXP (dest, 0);
+ if (dest == x)
+ break;
}
/* ... fall through ... */
@@ -8154,6 +8185,40 @@ check_dbra_loop (loop_end, insn_count, l
}
bl->nonneg = 1;
}
+
+ /* No insn may reference both the reversed and another biv or it
+ will fail (see comment near the top of the loop reversal
+ code).
+ Earlier on, we have verified that the biv has no use except
+ counting, or it is the only biv in this function.
+ However, the code that computes no_use_except_counting does
+ not verify reg notes. It's possible to have an insn that
+ references another biv, and has a REG_EQUAL note with an
+ expression based on the reversed biv. To avoid this case,
+ remove all REG_EQUAL notes based on the reversed biv
+ here. */
+ for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
+ if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+ {
+ rtx *pnote;
+ rtx set = single_set (p);
+ /* If this is a set of a GIV based on the reversed biv, any
+ REG_EQUAL notes should still be correct. */
+ if (! set
+ || GET_CODE (SET_DEST (set)) != REG
+ || (size_t) REGNO (SET_DEST (set)) >= reg_iv_type->num_elements
+ || REG_IV_TYPE (REGNO (SET_DEST (set))) != GENERAL_INDUCT
+ || REG_IV_INFO (REGNO (SET_DEST (set)))->src_reg != bl->biv->src_reg)
+ for (pnote = ®_NOTES (p); *pnote;)
+ {
+ if (REG_NOTE_KIND (*pnote) == REG_EQUAL
+ && reg_mentioned_p (regno_reg_rtx[bl->regno],
+ XEXP (*pnote, 0)))
+ *pnote = XEXP (*pnote, 1);
+ else
+ pnote = &XEXP (*pnote, 1);
+ }
+ }
/* Mark that this biv has been reversed. Each giv which depends
on this biv, and which is also live past the end of the loop
Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.71.4.2
diff -u -p -r1.71.4.2 reload.c
--- gcc/reload.c 1999/07/14 22:29:48 1.71.4.2
+++ gcc/reload.c 2000/11/29 15:17:12
@@ -322,7 +322,6 @@ static int find_reusable_reload PROTO((r
static rtx find_dummy_reload PROTO((rtx, rtx, rtx *, rtx *,
enum machine_mode, enum machine_mode,
enum reg_class, int, int));
-static int earlyclobber_operand_p PROTO((rtx));
static int hard_reg_set_here_p PROTO((int, int, rtx));
static struct decomposition decompose PROTO((rtx));
static int immune_p PROTO((rtx, rtx, struct decomposition));
@@ -591,7 +590,13 @@ push_secondary_reload (in_p, x, opnum, o
if (in_p && icode == CODE_FOR_nothing
&& SECONDARY_MEMORY_NEEDED (class, reload_class, mode))
- get_secondary_mem (x, reload_mode, opnum, type);
+ {
+ get_secondary_mem (x, reload_mode, opnum, type);
+
+ /* We may have just added new reloads. Make sure we add
+ the new reload at the end. */
+ s_reload = n_reloads;
+ }
#endif
/* We need to make a new secondary reload for this register class. */
@@ -1529,12 +1534,23 @@ push_reload (in, out, inloc, outloc, cla
&& GET_MODE_SIZE (inmode) <= GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
&& HARD_REGNO_MODE_OK (regno, inmode)
&& GET_MODE_SIZE (outmode) <= GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
- && HARD_REGNO_MODE_OK (regno, outmode)
- && TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno)
- && !fixed_regs[regno])
+ && HARD_REGNO_MODE_OK (regno, outmode))
{
- reload_reg_rtx[i] = gen_rtx_REG (inmode, regno);
- break;
+ unsigned int offs;
+ unsigned int nregs = MAX (HARD_REGNO_NREGS (regno, inmode),
+ HARD_REGNO_NREGS (regno, outmode));
+
+ for (offs = 0; offs < nregs; offs++)
+ if (fixed_regs[regno + offs]
+ || ! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ regno + offs))
+ break;
+
+ if (offs == nregs)
+ {
+ reload_reg_rtx[i] = gen_rtx_REG (inmode, regno);
+ break;
+ }
}
}
@@ -1989,7 +2005,7 @@ find_dummy_reload (real_in, real_out, in
/* Return 1 if X is an operand of an insn that is being earlyclobbered. */
-static int
+int
earlyclobber_operand_p (x)
rtx x;
{
@@ -5346,20 +5362,18 @@ find_reloads_address_1 (mode, x, context
&& (*insn_operand_predicate[icode][0]) (equiv, Pmode)
&& (*insn_operand_predicate[icode][1]) (equiv, Pmode)))
{
- loc = &XEXP (x, 0);
+ /* We use the original pseudo for loc, so that
+ emit_reload_insns() knows which pseudo this
+ reload refers to and updates the pseudo rtx, not
+ its equivalent memory location, as well as the
+ corresponding entry in reg_last_reload_reg. */
+ loc = &XEXP (x_orig, 0);
x = XEXP (x, 0);
reloadnum
= push_reload (x, x, loc, loc,
(context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, RELOAD_OTHER);
-
- /* If we created a new MEM based on reg_equiv_mem[REGNO], then
- LOC above is part of the new MEM, not the MEM in INSN.
-
- We must also replace the address of the MEM in INSN. */
- if (&XEXP (x_orig, 0) != loc)
- push_replacement (&XEXP (x_orig, 0), reloadnum, VOIDmode);
}
else
Index: gcc/reload.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.h,v
retrieving revision 1.17
diff -u -p -r1.17 reload.h
--- gcc/reload.h 1998/12/16 20:57:55 1.17
+++ gcc/reload.h 2000/11/29 15:17:12
@@ -342,3 +342,5 @@ extern void save_call_clobbered_regs PRO
/* Replace (subreg (reg)) with the appropriate (reg) for any operands. */
extern void cleanup_subreg_operands PROTO ((rtx));
+
+extern int earlyclobber_operand_p PROTO((rtx));
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.145.4.2
diff -u -p -r1.145.4.2 reload1.c
--- gcc/reload1.c 2000/03/08 05:02:46 1.145.4.2
+++ gcc/reload1.c 2000/11/29 15:17:15
@@ -423,6 +423,7 @@ static int reload_reg_free_for_value_p P
static int reload_reg_reaches_end_p PROTO((int, int, enum reload_type));
static int allocate_reload_reg PROTO((struct insn_chain *, int, int,
int));
+static int conflicts_with_override PROTO((rtx));
static void choose_reload_regs PROTO((struct insn_chain *));
static void merge_assigned_reloads PROTO((rtx));
static void emit_reload_insns PROTO((struct insn_chain *));
@@ -4518,7 +4519,10 @@ forget_old_reloads_1 (x, ignored)
reload reg in the current instruction. */
if (n_reloads == 0
|| ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i))
- CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+ {
+ CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+ spill_reg_store[regno + i] = 0;
+ }
}
/* Since value of X has changed,
@@ -4577,6 +4581,8 @@ reload_reg_class_lower (r1p, r2p)
/* The following HARD_REG_SETs indicate when each hard register is
used for a reload of various parts of the current insn. */
+/* If reg is unavailable for all reloads. */
+static HARD_REG_SET reload_reg_unavailable;
/* If reg is in use as a reload reg for a RELOAD_OTHER reload. */
static HARD_REG_SET reload_reg_used;
/* If reg is in use for a RELOAD_FOR_INPUT_ADDRESS reload for operand I. */
@@ -4799,8 +4805,8 @@ reload_reg_free_p (regno, opnum, type)
{
int i;
- /* In use for a RELOAD_OTHER means it's not available for anything. */
- if (TEST_HARD_REG_BIT (reload_reg_used, regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used, regno)
+ || TEST_HARD_REG_BIT (reload_reg_unavailable, regno))
return 0;
switch (type)
@@ -5133,7 +5139,7 @@ reloads_conflict (r1, r2)
return (r2_type == RELOAD_FOR_INSN || r2_type == RELOAD_FOR_OUTPUT
|| ((r2_type == RELOAD_FOR_OUTPUT_ADDRESS
|| r2_type == RELOAD_FOR_OUTADDR_ADDRESS)
- && r2_opnum >= r1_opnum));
+ && r2_opnum <= r1_opnum));
case RELOAD_FOR_INSN:
return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_OUTPUT
@@ -5201,6 +5207,10 @@ reload_reg_free_for_value_p (regno, opnu
int ignore_address_reloads;
{
int time1;
+ /* Set if we see an input reload that must not share its reload register
+ with any new earlyclobber, but might otherwise share the reload
+ register with an output or input-output reload. */
+ int check_earlyclobber = 0;
int i;
int copy = 0;
@@ -5208,7 +5218,7 @@ reload_reg_free_for_value_p (regno, opnu
available as spill registers, including hard registers that are
earlyclobbered in asms. As a temporary measure, reject anything
in reload_reg_used. */
- if (TEST_HARD_REG_BIT (reload_reg_used, regno))
+ if (TEST_HARD_REG_BIT (reload_reg_unavailable, regno))
return 0;
if (out == const0_rtx)
@@ -5235,7 +5245,8 @@ reload_reg_free_for_value_p (regno, opnu
switch (type)
{
case RELOAD_FOR_OTHER_ADDRESS:
- time1 = 0;
+ /* RELOAD_FOR_OTHER_ADDRESS conflicts with RELOAD_OTHER reloads. */
+ time1 = copy ? 0 : 1;
break;
case RELOAD_OTHER:
time1 = copy ? 1 : MAX_RECOG_OPERANDS * 5 + 5;
@@ -5327,6 +5338,7 @@ reload_reg_free_for_value_p (regno, opnu
break;
case RELOAD_FOR_INPUT:
time2 = reload_opnum[i] * 4 + 4;
+ check_earlyclobber = 1;
break;
/* reload_opnum[i] * 4 + 4 <= (MAX_RECOG_OPERAND - 1) * 4 + 4
== MAX_RECOG_OPERAND * 4 */
@@ -5339,6 +5351,7 @@ reload_reg_free_for_value_p (regno, opnu
break;
case RELOAD_FOR_OPERAND_ADDRESS:
time2 = MAX_RECOG_OPERANDS * 4 + 2;
+ check_earlyclobber = 1;
break;
case RELOAD_FOR_INSN:
time2 = MAX_RECOG_OPERANDS * 4 + 3;
@@ -5367,6 +5380,9 @@ reload_reg_free_for_value_p (regno, opnu
if (! reload_in[i] || rtx_equal_p (reload_in[i], value))
{
time2 = MAX_RECOG_OPERANDS * 4 + 4;
+ /* Earlyclobbered outputs must conflict with inputs. */
+ if (earlyclobber_operand_p (reload_out[i]))
+ time2 = MAX_RECOG_OPERANDS * 4 + 3;
break;
}
time2 = 1;
@@ -5389,9 +5405,29 @@ reload_reg_free_for_value_p (regno, opnu
}
}
}
+
+ /* Earlyclobbered outputs must conflict with inputs. */
+ if (check_earlyclobber && out && earlyclobber_operand_p (out))
+ return 0;
+
return 1;
}
+/* Determine whether the reload reg X overlaps any rtx'es used for
+ overriding inheritance. Return nonzero if so. */
+
+static int
+conflicts_with_override (x)
+ rtx x;
+{
+ int i;
+ for (i = 0; i < n_reloads; i++)
+ if (reload_override_in[i]
+ && reg_overlap_mentioned_p (x, reload_override_in[i]))
+ return 1;
+ return 0;
+}
+
/* Find a spill register to use as a reload register for reload R.
LAST_RELOAD is non-zero if this is the last reload for the insn being
processed.
@@ -5669,7 +5705,7 @@ choose_reload_regs (chain)
CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]);
}
- IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs);
+ COMPL_HARD_REG_SET (reload_reg_unavailable, chain->used_spill_regs);
#if 0 /* Not needed, now that we can always retry without inheritance. */
/* See if we have more mandatory reloads than spill regs.
@@ -6799,6 +6835,7 @@ emit_reload_insns (chain)
&& dead_or_set_p (insn, old)
/* This is unsafe if some other reload
uses the same reg first. */
+ && ! conflicts_with_override (reloadreg)
&& reload_reg_free_for_value_p (REGNO (reloadreg),
reload_opnum[j],
reload_when_needed[j],
@@ -7112,7 +7149,8 @@ emit_reload_insns (chain)
/* We don't need to test full validity of last_regno for
inherit here; we only want to know if the store actually
matches the pseudo. */
- if (reg_reloaded_contents[last_regno] == pseudo_no
+ if (TEST_HARD_REG_BIT (reg_reloaded_valid, last_regno)
+ && reg_reloaded_contents[last_regno] == pseudo_no
&& spill_reg_store[last_regno]
&& rtx_equal_p (pseudo, spill_reg_stored_to[last_regno]))
delete_output_reload (insn, j, last_regno);