aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1994-06-14 17:37:25 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1994-06-14 17:37:25 -0400
commit893bc853685bc2cb3c3b3394c0abf78c695c8df1 (patch)
tree3bb519f4206cba3494434fff400b0421e30ad30d
parentf98bb7d33fd1b44f3101f008d925ff4de5bc389c (diff)
downloadgcc-893bc853685bc2cb3c3b3394c0abf78c695c8df1.zip
gcc-893bc853685bc2cb3c3b3394c0abf78c695c8df1.tar.gz
gcc-893bc853685bc2cb3c3b3394c0abf78c695c8df1.tar.bz2
(reload): Process and accumulate needs for RELOAD_FOR_OPADDR_ADDR reloads.
When determining if needs are nongroup needs, ignore inactive or optional reloads. (reload_reg_used_in_op_addr_reload): New variable to indicate when reloads of class RELOAD_FOR_OPADDR_ADDR are in use. (mark_reload_reg_in_use, clear_reload_reg_in_use): Process reloads of class RELOAD_FOR_OPADDR_ADDR. (reload_reg_free_p, reload_reg_free_before_p, reloads_conflict): Likewise. (choose_reload_regs): Support RELOAD_FOR_OPADDR_ADDR reloads. (emit_reload_insns): Output RELOAD_FOR_OPADDR_ADDR reloads. From-SVN: r7462
-rw-r--r--gcc/reload1.c102
1 files changed, 89 insertions, 13 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 10afe98..d32e91f 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -945,6 +945,7 @@ reload (first, global, dumpfile)
struct needs insn;
struct needs other_addr;
struct needs op_addr;
+ struct needs op_addr_reload;
struct needs in_addr[MAX_RECOG_OPERANDS];
struct needs out_addr[MAX_RECOG_OPERANDS];
} insn_needs;
@@ -1073,6 +1074,9 @@ reload (first, global, dumpfile)
? reload_outmode[j]
: reload_inmode[j])
> 1)
+ && (!reload_optional[j])
+ && (reload_in[j] != 0 || reload_out[j] != 0
+ || reload_secondary_p[j])
&& reloads_conflict (i, j)
&& reg_classes_intersect_p (class,
reload_reg_class[j]))
@@ -1108,6 +1112,9 @@ reload (first, global, dumpfile)
case RELOAD_FOR_OPERAND_ADDRESS:
this_needs = &insn_needs.op_addr;
break;
+ case RELOAD_FOR_OPADDR_ADDR:
+ this_needs = &insn_needs.op_addr_reload;
+ break;
}
if (size > 1)
@@ -1184,7 +1191,10 @@ reload (first, global, dumpfile)
don't conflict with things needed to reload inputs or
outputs. */
- in_max = MAX (in_max, insn_needs.op_addr.regs[j][i]);
+ in_max = MAX (MAX (insn_needs.op_addr.regs[j][i],
+ insn_needs.op_addr_reload.regs[j][i]),
+ in_max);
+
out_max = MAX (out_max, insn_needs.insn.regs[j][i]);
insn_needs.input.regs[j][i]
@@ -1210,7 +1220,9 @@ reload (first, global, dumpfile)
= MAX (out_max, insn_needs.out_addr[j].groups[i]);
}
- in_max = MAX (in_max, insn_needs.op_addr.groups[i]);
+ in_max = MAX (MAX (insn_needs.op_addr.groups[i],
+ insn_needs.op_addr_reload.groups[i]),
+ in_max);
out_max = MAX (out_max, insn_needs.insn.groups[i]);
insn_needs.input.groups[i]
@@ -3106,6 +3118,8 @@ eliminate_regs_in_insn (insn, replace)
{
rtx old_body = PATTERN (insn);
rtx new_body;
+ rtx old_set;
+ rtx new_set;
int val = 0;
struct elim_table *ep;
@@ -3176,6 +3190,12 @@ eliminate_regs_in_insn (insn, replace)
new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX);
if (new_body != old_body)
{
+ old_set = (GET_CODE (old_body) == PARALLEL) ? single_set (insn) :
+ old_body;
+
+ new_set = (GET_CODE (new_body) == PARALLEL) ? XVECEXP(new_body,0,0) :
+ new_body;
+
/* If we aren't replacing things permanently and we changed something,
make another copy to ensure that all the RTL is new. Otherwise
things can go wrong if find_reload swaps commutative operands
@@ -3187,22 +3207,25 @@ eliminate_regs_in_insn (insn, replace)
new_body = copy_rtx (new_body);
/* If we had a move insn but now we don't, rerecognize it. */
- if ((GET_CODE (old_body) == SET && GET_CODE (SET_SRC (old_body)) == REG
- && (GET_CODE (new_body) != SET
- || GET_CODE (SET_SRC (new_body)) != REG))
+ if ((GET_CODE (old_set) == SET && GET_CODE (SET_SRC (old_set)) == REG
+ && (GET_CODE (new_set) != SET
+ || GET_CODE (SET_SRC (new_set)) != REG))
/* If this was a load from or store to memory, compare
the MEM in recog_operand to the one in the insn. If they
are not equal, then rerecognize the insn. */
- || (GET_CODE (old_body) == SET
- && ((GET_CODE (SET_SRC (old_body)) == MEM
- && SET_SRC (old_body) != recog_operand[1])
- || (GET_CODE (SET_DEST (old_body)) == MEM
- && SET_DEST (old_body) != recog_operand[0])))
+ || (GET_CODE (old_set) == SET
+ && ((GET_CODE (SET_SRC (old_set)) == MEM
+ && SET_SRC (old_set) != recog_operand[1])
+ || (GET_CODE (SET_DEST (old_set)) == MEM
+ && SET_DEST (old_set) != recog_operand[0])))
/* If this was an add insn before, rerecognize. */
||
- (GET_CODE (old_body) == SET
- && GET_CODE (SET_SRC (old_body)) == PLUS))
+ (GET_CODE (old_set) == SET
+ && GET_CODE (SET_SRC (old_set)) == PLUS))
{
+ if (!replace)
+ PATTERN (insn) = copy_rtx (PATTERN (insn));
+
if (! validate_change (insn, &PATTERN (insn), new_body, 0))
/* If recognition fails, store the new body anyway.
It's normal to have recognition failures here
@@ -3993,6 +4016,8 @@ static HARD_REG_SET reload_reg_used_in_input[MAX_RECOG_OPERANDS];
static HARD_REG_SET reload_reg_used_in_output[MAX_RECOG_OPERANDS];
/* If reg is in use for a RELOAD_FOR_OPERAND_ADDRESS reload. */
static HARD_REG_SET reload_reg_used_in_op_addr;
+/* If reg is in use for a RELOAD_FOR_OPADDR_ADDR reload. */
+static HARD_REG_SET reload_reg_used_in_op_addr_reload;
/* If reg is in use for a RELOAD_FOR_INSN reload. */
static HARD_REG_SET reload_reg_used_in_insn;
/* If reg is in use for a RELOAD_FOR_OTHER_ADDRESS reload. */
@@ -4039,6 +4064,10 @@ mark_reload_reg_in_use (regno, opnum, type, mode)
SET_HARD_REG_BIT (reload_reg_used_in_op_addr, i);
break;
+ case RELOAD_FOR_OPADDR_ADDR:
+ SET_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, i);
+ break;
+
case RELOAD_FOR_OTHER_ADDRESS:
SET_HARD_REG_BIT (reload_reg_used_in_other_addr, i);
break;
@@ -4092,6 +4121,10 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr, i);
break;
+ case RELOAD_FOR_OPADDR_ADDR:
+ CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, i);
+ break;
+
case RELOAD_FOR_OTHER_ADDRESS:
CLEAR_HARD_REG_BIT (reload_reg_used_in_other_addr, i);
break;
@@ -4142,6 +4175,9 @@ reload_reg_free_p (regno, opnum, type)
|| TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno))
return 0;
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno))
+ return 0;
+
/* If it is used for some other input, can't use it. */
for (i = 0; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
@@ -4186,6 +4222,13 @@ reload_reg_free_p (regno, opnum, type)
return (! TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno)
&& ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno));
+ case RELOAD_FOR_OPADDR_ADDR:
+ for (i = 0; i < reload_n_operands; i++)
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
+ return 0;
+
+ return (!TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno));
+
case RELOAD_FOR_OUTPUT:
/* This cannot share a register with RELOAD_FOR_INSN reloads, other
outputs, or an operand address for this or an earlier output. */
@@ -4294,6 +4337,7 @@ reload_reg_free_before_p (regno, opnum, type)
return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
case RELOAD_FOR_OPERAND_ADDRESS:
+ case RELOAD_FOR_OPADDR_ADDR:
case RELOAD_FOR_INSN:
/* These can't conflict with inputs, or each other, so all we have to
test is input addresses and the addresses of OTHER items. */
@@ -4389,6 +4433,9 @@ reload_reg_reaches_end_p (regno, opnum, type)
|| TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
return 0;
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno))
+ return 0;
+
return (! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno)
&& ! TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno));
@@ -4415,8 +4462,17 @@ reload_reg_reaches_end_p (regno, opnum, type)
return 1;
+ case RELOAD_FOR_OPADDR_ADDR:
+ for (i = 0; i < reload_n_operands; i++)
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
+ return 0;
+
+ return (! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno)
+ && !TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno));
+
case RELOAD_FOR_INSN:
- /* These conflict with other outputs with with RELOAD_OTHER. So
+ /* These conflict with other outputs with RELOAD_OTHER. So
we need only check for output addresses. */
opnum = -1;
@@ -4465,6 +4521,7 @@ reloads_conflict (r1, r2)
case RELOAD_FOR_INPUT:
return (r2_type == RELOAD_FOR_INSN
|| r2_type == RELOAD_FOR_OPERAND_ADDRESS
+ || r2_type == RELOAD_FOR_OPADDR_ADDR
|| r2_type == RELOAD_FOR_INPUT
|| (r2_type == RELOAD_FOR_INPUT_ADDRESS && r2_opnum > r1_opnum));
@@ -4480,6 +4537,10 @@ reloads_conflict (r1, r2)
return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_INSN
|| r2_type == RELOAD_FOR_OPERAND_ADDRESS);
+ case RELOAD_FOR_OPADDR_ADDR:
+ return (r2_type == RELOAD_FOR_INPUT
+ || r2_type == RELOAD_FOR_OPADDR_ADDR);
+
case RELOAD_FOR_OUTPUT:
return (r2_type == RELOAD_FOR_INSN || r2_type == RELOAD_FOR_OUTPUT
|| (r2_type == RELOAD_FOR_OUTPUT_ADDRESS
@@ -4750,6 +4811,7 @@ choose_reload_regs (insn, avoid_return_reg)
HARD_REG_SET save_reload_reg_used_in_input[MAX_RECOG_OPERANDS];
HARD_REG_SET save_reload_reg_used_in_output[MAX_RECOG_OPERANDS];
HARD_REG_SET save_reload_reg_used_in_op_addr;
+ HARD_REG_SET save_reload_reg_used_in_op_addr_reload;
HARD_REG_SET save_reload_reg_used_in_insn;
HARD_REG_SET save_reload_reg_used_in_other_addr;
HARD_REG_SET save_reload_reg_used_at_all;
@@ -4761,6 +4823,7 @@ choose_reload_regs (insn, avoid_return_reg)
CLEAR_HARD_REG_SET (reload_reg_used);
CLEAR_HARD_REG_SET (reload_reg_used_at_all);
CLEAR_HARD_REG_SET (reload_reg_used_in_op_addr);
+ CLEAR_HARD_REG_SET (reload_reg_used_in_op_addr_reload);
CLEAR_HARD_REG_SET (reload_reg_used_in_insn);
CLEAR_HARD_REG_SET (reload_reg_used_in_other_addr);
@@ -4888,6 +4951,10 @@ choose_reload_regs (insn, avoid_return_reg)
COPY_HARD_REG_SET (save_reload_reg_used_at_all, reload_reg_used_at_all);
COPY_HARD_REG_SET (save_reload_reg_used_in_op_addr,
reload_reg_used_in_op_addr);
+
+ COPY_HARD_REG_SET (save_reload_reg_used_in_op_addr_reload,
+ reload_reg_used_in_op_addr_reload);
+
COPY_HARD_REG_SET (save_reload_reg_used_in_insn,
reload_reg_used_in_insn);
COPY_HARD_REG_SET (save_reload_reg_used_in_other_addr,
@@ -5257,6 +5324,8 @@ choose_reload_regs (insn, avoid_return_reg)
COPY_HARD_REG_SET (reload_reg_used_at_all, save_reload_reg_used_at_all);
COPY_HARD_REG_SET (reload_reg_used_in_op_addr,
save_reload_reg_used_in_op_addr);
+ COPY_HARD_REG_SET (reload_reg_used_in_op_addr_reload,
+ save_reload_reg_used_in_op_addr_reload);
COPY_HARD_REG_SET (reload_reg_used_in_insn,
save_reload_reg_used_in_insn);
COPY_HARD_REG_SET (reload_reg_used_in_other_addr,
@@ -5466,6 +5535,7 @@ emit_reload_insns (insn)
rtx output_reload_insns[MAX_RECOG_OPERANDS];
rtx output_address_reload_insns[MAX_RECOG_OPERANDS];
rtx operand_reload_insns = 0;
+ rtx other_operand_reload_insns = 0;
rtx following_insn = NEXT_INSN (insn);
rtx before_insn = insn;
int special;
@@ -5671,6 +5741,9 @@ emit_reload_insns (insn)
case RELOAD_FOR_OPERAND_ADDRESS:
where = &operand_reload_insns;
break;
+ case RELOAD_FOR_OPADDR_ADDR:
+ where = &other_operand_reload_insns;
+ break;
case RELOAD_FOR_OTHER_ADDRESS:
where = &other_input_address_reload_insns;
break;
@@ -6286,6 +6359,8 @@ emit_reload_insns (insn)
For each operand, any RELOAD_FOR_INPUT_ADDRESS reloads followed by
the RELOAD_FOR_INPUT reload for the operand.
+ RELOAD_FOR_OPADDR_ADDRS reloads.
+
RELOAD_FOR_OPERAND_ADDRESS reloads.
After the insn being reloaded, we write the following:
@@ -6302,6 +6377,7 @@ emit_reload_insns (insn)
emit_insns_before (input_reload_insns[j], before_insn);
}
+ emit_insns_before (other_operand_reload_insns, before_insn);
emit_insns_before (operand_reload_insns, before_insn);
for (j = 0; j < reload_n_operands; j++)