summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/reload1.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2001-01-03 17:16:04 +0000
committerobrien <obrien@FreeBSD.org>2001-01-03 17:16:04 +0000
commite103926ab58446425b46d5df55c940db3abeff84 (patch)
tree46177f22832f755e34be042b91555eedf10b4f66 /contrib/gcc/reload1.c
parentd566d0a5f8c3f4d187ecbf8096628e9ae9dd3567 (diff)
downloadFreeBSD-src-e103926ab58446425b46d5df55c940db3abeff84.zip
FreeBSD-src-e103926ab58446425b46d5df55c940db3abeff84.tar.gz
Enlist the FreeBSD-CURRENT users as testers of GCC 2.95.3 Release Candidate #1
Diffstat (limited to 'contrib/gcc/reload1.c')
-rw-r--r--contrib/gcc/reload1.c218
1 files changed, 153 insertions, 65 deletions
diff --git a/contrib/gcc/reload1.c b/contrib/gcc/reload1.c
index d9245b0..027accf 100644
--- a/contrib/gcc/reload1.c
+++ b/contrib/gcc/reload1.c
@@ -420,9 +420,13 @@ static void clear_reload_reg_in_use PROTO((int, int, enum reload_type,
enum machine_mode));
static int reload_reg_free_p PROTO((int, int, enum reload_type));
static int reload_reg_free_for_value_p PROTO((int, int, enum reload_type, rtx, rtx, int, int));
+static int free_for_value_p PROTO((int, enum machine_mode, int,
+ enum reload_type, rtx, rtx,
+ int, int));
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 +4522,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 +4584,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 +4808,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 +5142,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
@@ -5171,25 +5180,8 @@ rtx reload_override_in[MAX_RELOADS];
or -1 if we did not need a register for this reload. */
int reload_spill_index[MAX_RELOADS];
-/* Return 1 if the value in reload reg REGNO, as used by a reload
- needed for the part of the insn specified by OPNUM and TYPE,
- may be used to load VALUE into it.
-
- Other read-only reloads with the same value do not conflict
- unless OUT is non-zero and these other reloads have to live while
- output reloads live.
- If OUT is CONST0_RTX, this is a special case: it means that the
- test should not be for using register REGNO as reload register, but
- for copying from register REGNO into the reload register.
-
- RELOADNUM is the number of the reload we want to load this value for;
- a reload does not conflict with itself.
+/* Subroutine of free_for_value_p, used to check a single register. */
- When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with
- reloads that load an address for the very reload we are considering.
-
- The caller has to make sure that there is no conflict with the return
- register. */
static int
reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
ignore_address_reloads)
@@ -5201,6 +5193,10 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
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 +5204,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
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 +5231,8 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
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 +5324,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
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 +5337,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
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 +5366,9 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
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 +5391,71 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
}
}
}
+
+ /* Earlyclobbered outputs must conflict with inputs. */
+ if (check_earlyclobber && out && earlyclobber_operand_p (out))
+ return 0;
+
return 1;
}
+/* Return 1 if the value in reload reg REGNO, as used by a reload
+ needed for the part of the insn specified by OPNUM and TYPE,
+ may be used to load VALUE into it.
+
+ MODE is the mode in which the register is used, this is needed to
+ determine how many hard regs to test.
+
+ Other read-only reloads with the same value do not conflict
+ unless OUT is non-zero and these other reloads have to live while
+ output reloads live.
+ If OUT is CONST0_RTX, this is a special case: it means that the
+ test should not be for using register REGNO as reload register, but
+ for copying from register REGNO into the reload register.
+
+ RELOADNUM is the number of the reload we want to load this value for;
+ a reload does not conflict with itself.
+
+ When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with
+ reloads that load an address for the very reload we are considering.
+
+ The caller has to make sure that there is no conflict with the return
+ register. */
+
+static int
+free_for_value_p (regno, mode, opnum, type, value, out, reloadnum,
+ ignore_address_reloads)
+ int regno;
+ enum machine_mode mode;
+ int opnum;
+ enum reload_type type;
+ rtx value, out;
+ int reloadnum;
+ int ignore_address_reloads;
+{
+ int nregs = HARD_REGNO_NREGS (regno, mode);
+ while (nregs-- > 0)
+ if (! reload_reg_free_for_value_p (regno + nregs, opnum, type, value, out,
+ reloadnum, ignore_address_reloads))
+ 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.
@@ -5472,11 +5536,10 @@ allocate_reload_reg (chain, r, last_reload, noerror)
/* We check reload_reg_used to make sure we
don't clobber the return register. */
&& ! TEST_HARD_REG_BIT (reload_reg_used, regnum)
- && reload_reg_free_for_value_p (regnum,
- reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- reload_out[r], r, 1)))
+ && free_for_value_p (regnum, reload_mode[r],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r], reload_out[r], r, 1)))
&& TEST_HARD_REG_BIT (reg_class_contents[class], regnum)
&& HARD_REGNO_MODE_OK (regnum, reload_mode[r])
/* Look first for regs to share, then for unshared. But
@@ -5669,7 +5732,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.
@@ -5931,10 +5994,9 @@ choose_reload_regs (chain)
&& (reload_nregs[r] == max_group_size
|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class],
i))
- && reload_reg_free_for_value_p (i, reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- const0_rtx, r, 1))
+ && free_for_value_p (i, reload_mode[r], reload_opnum[r],
+ reload_when_needed[r], reload_in[r],
+ const0_rtx, r, 1))
{
/* If a group is needed, verify that all the subsequent
registers still have their values intact. */
@@ -5968,9 +6030,11 @@ choose_reload_regs (chain)
break;
if (i1 != n_earlyclobbers
- || ! (reload_reg_free_for_value_p
- (i, reload_opnum[r], reload_when_needed[r],
- reload_in[r], reload_out[r], r, 1))
+ || ! (free_for_value_p (i, reload_mode[r],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r],
+ reload_out[r], r, 1))
/* Don't use it if we'd clobber a pseudo reg. */
|| (TEST_HARD_REG_BIT (reg_used_in_insn, i)
&& reload_out[r]
@@ -5992,9 +6056,12 @@ choose_reload_regs (chain)
&& rtx_equal_p (reload_out[r],
reload_reg_rtx[r])))
{
- reload_override_in[r] = last_reg;
- reload_inheritance_insn[r]
- = reg_reloaded_insn[i];
+ if (! reload_optional[r])
+ {
+ reload_override_in[r] = last_reg;
+ reload_inheritance_insn[r]
+ = reg_reloaded_insn[i];
+ }
}
else
{
@@ -6072,10 +6139,11 @@ choose_reload_regs (chain)
and of the desired class. */
if (equiv != 0
&& ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
- && ! reload_reg_free_for_value_p (regno, reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- reload_out[r], r, 1))
+ && ! free_for_value_p (regno, reload_mode[r],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r], reload_out[r], r,
+ 1))
|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
regno)))
equiv = 0;
@@ -6093,7 +6161,8 @@ choose_reload_regs (chain)
if (reg_overlap_mentioned_for_reload_p (equiv,
reload_earlyclobbers[i]))
{
- reload_override_in[r] = equiv;
+ if (! reload_optional[r])
+ reload_override_in[r] = equiv;
equiv = 0;
break;
}
@@ -6104,7 +6173,8 @@ choose_reload_regs (chain)
In particular, we then can't use EQUIV for a
RELOAD_FOR_OUTPUT_ADDRESS reload. */
- if (equiv != 0 && regno_clobbered_p (regno, insn))
+ if (equiv != 0 && regno_clobbered_p (regno, insn,
+ reload_mode[r], 0))
{
switch (reload_when_needed[r])
{
@@ -6116,13 +6186,32 @@ choose_reload_regs (chain)
case RELOAD_OTHER:
case RELOAD_FOR_INPUT:
case RELOAD_FOR_OPERAND_ADDRESS:
- reload_override_in[r] = equiv;
+ if (! reload_optional[r])
+ reload_override_in[r] = equiv;
/* Fall through. */
default:
equiv = 0;
break;
}
}
+ else if (regno_clobbered_p (regno, insn, reload_mode[r], 1))
+ switch (reload_when_needed[r])
+ {
+ case RELOAD_FOR_OTHER_ADDRESS:
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ case RELOAD_FOR_INPUT_ADDRESS:
+ case RELOAD_FOR_OPADDR_ADDR:
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ case RELOAD_FOR_INPUT:
+ break;
+ case RELOAD_OTHER:
+ if (! reload_optional[r])
+ reload_override_in[r] = equiv;
+ /* Fall through. */
+ default:
+ equiv = 0;
+ break;
+ }
/* If we found an equivalent reg, say no code need be generated
to load it, and use it as our reload reg. */
@@ -6283,13 +6372,12 @@ choose_reload_regs (chain)
check_reg = reload_override_in[r];
else
continue;
- if (! reload_reg_free_for_value_p (true_regnum (check_reg),
- reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- (reload_inherited[r]
- ? reload_out[r] : const0_rtx),
- r, 1))
+ if (! free_for_value_p (true_regnum (check_reg), reload_mode[r],
+ reload_opnum[r], reload_when_needed[r],
+ reload_in[r],
+ (reload_inherited[r]
+ ? reload_out[r] : const0_rtx),
+ r, 1))
{
if (pass)
continue;
@@ -6646,10 +6734,10 @@ emit_reload_insns (chain)
/* Don't use OLDEQUIV if any other reload changes it at an
earlier stage of this insn or at this stage. */
- if (! reload_reg_free_for_value_p (regno, reload_opnum[j],
- reload_when_needed[j],
- reload_in[j], const0_rtx, j,
- 0))
+ if (! free_for_value_p (regno, reload_mode[j],
+ reload_opnum[j],
+ reload_when_needed[j],
+ reload_in[j], const0_rtx, j, 0))
oldequiv = 0;
/* If it is no cheaper to copy from OLDEQUIV into the
@@ -6799,11 +6887,10 @@ emit_reload_insns (chain)
&& dead_or_set_p (insn, old)
/* This is unsafe if some other reload
uses the same reg first. */
- && reload_reg_free_for_value_p (REGNO (reloadreg),
- reload_opnum[j],
- reload_when_needed[j],
- old, reload_out[j],
- j, 0))
+ && ! conflicts_with_override (reloadreg)
+ && free_for_value_p (REGNO (reloadreg), reload_mode[j],
+ reload_opnum[j], reload_when_needed[j],
+ old, reload_out[j], j, 0))
{
rtx temp = PREV_INSN (insn);
while (temp && GET_CODE (temp) == NOTE)
@@ -7112,7 +7199,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);
@@ -7288,7 +7376,7 @@ emit_reload_insns (chain)
|| !(set = single_set (insn))
|| rtx_equal_p (old, SET_DEST (set))
|| !reg_mentioned_p (old, SET_SRC (set))
- || !regno_clobbered_p (REGNO (old), insn))
+ || !regno_clobbered_p (REGNO (old), insn, reload_mode[j], 0))
gen_reload (old, reloadreg, reload_opnum[j],
reload_when_needed[j]);
}
OpenPOWER on IntegriCloud