This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: State of maturity for gcc 2.95.3 and gcc 2.96
- To: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- Subject: Re: State of maturity for gcc 2.95.3 and gcc 2.96
- From: Bernd Schmidt <bernds at redhat dot co dot uk>
- Date: Mon, 16 Oct 2000 10:23:25 +0100 (BST)
- cc: Toon Moene <toon at moene dot indiv dot nluug dot nl>, "David O'Brien" <obrien at FreeBSD dot org>, Gerald Pfeifer <pfeifer at dbai dot tuwien dot ac dot at>, gcc at gcc dot gnu dot org
On Sun, 15 Oct 2000, Franz Sirl wrote:
> On Sat, 14 Oct 2000, Bernd Schmidt wrote:
> > On Sat, 14 Oct 2000, Toon Moene wrote:
> > > Bernd Schmidt wrote:
> > > > On Thu, 12 Oct 2000, David O'Brien wrote:
> > > > > Since 3.0 is still quite some time away, can 2.95.3 finally be
> > > > > released? Some very major bugs have been fixed, but commits have been
> > > > > very cautious to that branch. I'd almost imagine all that would be
> > > > > needed is to do a checkout and tar it up.
> > > >
> > > > You'd want to fix at least one new bug introduced in reload...
> > >
> > > This would indicate that our process to update the release branch is not
> > > correct.
> >
> > No, it indicates that not everything that looks like an obvious bug fix
> > is necessarily correct.
> >
> > More specifically, this patch
> > * reload1.c (reload_reg_free_for_value_p): Don't use a register
> > that is in reload_reg_used.
> > is incorrect; there's a correct solution for the bug in the current
> > sources.
>
> Could you be a bit more specific on what patch is the correct bugfix so I can
> find it in the mainline and/or lists? I'll look into backporting it to the
> gcc-2_95-branch then.
Here's a set of patches that may be helpful. I did a diff between the current
2.95 reload and loop code and tried to figure out patches I remembered or which
seemed obvious, then I backported those.
Off-hand, I can think of a few more patches that may be worthwhile. Better to
test this set thoroughly first, though.
Bernd
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.
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.
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.
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-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.
Index: 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
--- loop.c 2000/03/08 04:47:42 1.156.4.12
+++ loop.c 2000/10/13 12:33:41
@@ -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;
@@ -8154,6 +8168,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: 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
--- reload.c 1999/07/14 22:29:48 1.71.4.2
+++ reload.c 2000/10/13 12:33:43
@@ -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: reload.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.h,v
retrieving revision 1.17
diff -u -p -r1.17 reload.h
--- reload.h 1998/12/16 20:57:55 1.17
+++ reload.h 2000/10/13 12:33:43
@@ -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: 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
--- reload1.c 2000/03/08 05:02:46 1.145.4.2
+++ reload1.c 2000/10/13 12:33:46
@@ -4518,7 +4518,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 +4580,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 +4804,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 +5138,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 +5206,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 +5217,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 +5244,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 +5337,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 +5350,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 +5379,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,6 +5404,11 @@ 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;
}
@@ -5669,7 +5689,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.