summaryrefslogtreecommitdiff
path: root/gcc/regrename.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2001-12-31 23:16:08 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2001-12-31 23:16:08 +0000
commita68730c1908d833596a6bc615ff68aaac366ddb9 (patch)
tree7d850bce20a5f26a1ae39d2f9c74b5c8ed4ace75 /gcc/regrename.c
parent914dbc03b689e4fd8ba2318c888a5ea2e25234e6 (diff)
downloadgcc-a68730c1908d833596a6bc615ff68aaac366ddb9.tar.gz
* regrename.c (build_def_use): Don't rename asm operands that
were originally hard registers. (copyprop_hardreg_forward_1): Likewise. (find_oldest_value_reg): Copy ORIGINAL_REGNO from source. * varasm.c (make_decl_rtl): Use gen_rtx_raw_REG. Set ORIGINAL_REGNO. * gcc.dg/asm-5.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@48435 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/regrename.c')
-rw-r--r--gcc/regrename.c75
1 files changed, 61 insertions, 14 deletions
diff --git a/gcc/regrename.c b/gcc/regrename.c
index fca249e99e8..720e0cf46c9 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -838,6 +838,21 @@ build_def_use (bb)
scan_rtx (insn, &CALL_INSN_FUNCTION_USAGE (insn),
NO_REGS, terminate_all_read, OP_IN, 0);
+ /* Step 2C: Can't rename asm operands that were originally
+ hard registers. */
+ if (asm_noperands (PATTERN (insn)) > 0)
+ for (i = 0; i < n_ops; i++)
+ {
+ rtx *loc = recog_data.operand_loc[i];
+ rtx op = *loc;
+
+ if (GET_CODE (op) == REG
+ && REGNO (op) == ORIGINAL_REGNO (op)
+ && (recog_data.operand_type[i] == OP_IN
+ || recog_data.operand_type[i] == OP_INOUT))
+ scan_rtx (insn, loc, NO_REGS, terminate_all_read, OP_IN, 0);
+ }
+
/* Step 3: Append to chains for reads inside operands. */
for (i = 0; i < n_ops + recog_data.n_dups; i++)
{
@@ -909,8 +924,27 @@ build_def_use (bb)
/* Step 6: Begin new chains for writes inside operands. */
/* ??? Many targets have output constraints on the SET_DEST
of a call insn, which is stupid, since these are certainly
- ABI defined hard registers. Don't change calls at all. */
- if (GET_CODE (insn) != CALL_INSN)
+ ABI defined hard registers. Don't change calls at all.
+ Similarly take special care for asm statement that originally
+ referenced hard registers. */
+ if (asm_noperands (PATTERN (insn)) > 0)
+ {
+ for (i = 0; i < n_ops; i++)
+ if (recog_data.operand_type[i] == OP_OUT)
+ {
+ rtx *loc = recog_data.operand_loc[i];
+ rtx op = *loc;
+ enum reg_class class = recog_op_alt[i][alt].class;
+
+ if (GET_CODE (op) == REG
+ && REGNO (op) == ORIGINAL_REGNO (op))
+ continue;
+
+ scan_rtx (insn, loc, class, mark_write, OP_OUT,
+ recog_op_alt[i][alt].earlyclobber);
+ }
+ }
+ else if (GET_CODE (insn) != CALL_INSN)
for (i = 0; i < n_ops + recog_data.n_dups; i++)
{
int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
@@ -1000,9 +1034,8 @@ static int kill_autoinc_value PARAMS ((rtx *, void *));
static void copy_value PARAMS ((rtx, rtx, struct value_data *));
static bool mode_change_ok PARAMS ((enum machine_mode, enum machine_mode,
unsigned int));
-static rtx find_oldest_value_reg PARAMS ((enum reg_class, unsigned int,
- enum machine_mode,
- struct value_data *));
+static rtx find_oldest_value_reg PARAMS ((enum reg_class, rtx,
+ struct value_data *));
static bool replace_oldest_value_reg PARAMS ((rtx *, enum reg_class, rtx,
struct value_data *));
static bool replace_oldest_value_addr PARAMS ((rtx *, enum reg_class,
@@ -1240,19 +1273,24 @@ mode_change_ok (orig_mode, new_mode, regno)
of that oldest register, otherwise return NULL. */
static rtx
-find_oldest_value_reg (class, regno, mode, vd)
+find_oldest_value_reg (class, reg, vd)
enum reg_class class;
- unsigned int regno;
- enum machine_mode mode;
+ rtx reg;
struct value_data *vd;
{
+ unsigned int regno = REGNO (reg);
+ enum machine_mode mode = GET_MODE (reg);
unsigned int i;
for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
if (TEST_HARD_REG_BIT (reg_class_contents[class], i)
&& (vd->e[i].mode == mode
|| mode_change_ok (vd->e[i].mode, mode, regno)))
- return gen_rtx_REG (mode, i);
+ {
+ rtx new = gen_rtx_REG (mode, i);
+ ORIGINAL_REGNO (new) = ORIGINAL_REGNO (reg);
+ return new;
+ }
return NULL_RTX;
}
@@ -1267,7 +1305,7 @@ replace_oldest_value_reg (loc, class, insn, vd)
rtx insn;
struct value_data *vd;
{
- rtx new = find_oldest_value_reg (class, REGNO (*loc), GET_MODE (*loc), vd);
+ rtx new = find_oldest_value_reg (class, *loc, vd);
if (new)
{
if (rtl_dump_file)
@@ -1443,6 +1481,7 @@ copyprop_hardreg_forward_1 (bb, vd)
for (insn = bb->head; ; insn = NEXT_INSN (insn))
{
int n_ops, i, alt, predicated;
+ bool is_asm;
rtx set;
if (! INSN_P (insn))
@@ -1459,6 +1498,7 @@ copyprop_hardreg_forward_1 (bb, vd)
preprocess_constraints ();
alt = which_alternative;
n_ops = recog_data.n_operands;
+ is_asm = asm_noperands (PATTERN (insn)) >= 0;
/* Simplify the code below by rewriting things to reflect
matching constraints. Also promote OP_OUT to OP_INOUT
@@ -1498,8 +1538,9 @@ copyprop_hardreg_forward_1 (bb, vd)
be able to do the move from a different register class. */
if (set && REG_P (SET_SRC (set)))
{
- unsigned int regno = REGNO (SET_SRC (set));
- enum machine_mode mode = GET_MODE (SET_SRC (set));
+ rtx src = SET_SRC (set);
+ unsigned int regno = REGNO (src);
+ enum machine_mode mode = GET_MODE (src);
unsigned int i;
rtx new;
@@ -1507,8 +1548,7 @@ copyprop_hardreg_forward_1 (bb, vd)
register in the same class. */
if (REG_P (SET_DEST (set)))
{
- new = find_oldest_value_reg (REGNO_REG_CLASS (regno),
- regno, mode, vd);
+ new = find_oldest_value_reg (REGNO_REG_CLASS (regno), src, vd);
if (new && validate_change (insn, &SET_SRC (set), new, 0))
{
if (rtl_dump_file)
@@ -1528,6 +1568,7 @@ copyprop_hardreg_forward_1 (bb, vd)
new = gen_rtx_REG (mode, i);
if (validate_change (insn, &SET_SRC (set), new, 0))
{
+ ORIGINAL_REGNO (new) = ORIGINAL_REGNO (src);
if (rtl_dump_file)
fprintf (rtl_dump_file,
"insn %u: replaced reg %u with %u\n",
@@ -1550,6 +1591,12 @@ copyprop_hardreg_forward_1 (bb, vd)
if (recog_data.constraints[i][0] == '\0')
continue;
+ /* Don't replace in asms intentionally referencing hard regs. */
+ if (is_asm && GET_CODE (recog_data.operand[i]) == REG
+ && (REGNO (recog_data.operand[i])
+ == ORIGINAL_REGNO (recog_data.operand[i])))
+ continue;
+
if (recog_data.operand_type[i] == OP_IN)
{
if (recog_op_alt[i][alt].is_address)