diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-12-31 23:16:08 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-12-31 23:16:08 +0000 |
commit | a68730c1908d833596a6bc615ff68aaac366ddb9 (patch) | |
tree | 7d850bce20a5f26a1ae39d2f9c74b5c8ed4ace75 /gcc/regrename.c | |
parent | 914dbc03b689e4fd8ba2318c888a5ea2e25234e6 (diff) | |
download | gcc-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.c | 75 |
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) |