Commit 3ada20ee by Richard Henderson Committed by Richard Henderson

regrename.c (build_def_use): Don't rename asm operands that were originally hard registers.

        * 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.

From-SVN: r48435
parent 5a598ccc
2001-12-31 Richard Henderson <rth@redhat.com>
* 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.
2001-12-31 Douglas B Rupp <rupp@gnat.com>
* config/alpha/vms.h (HAS_INIT_SECTION, NEED_ATEXIT): Remove.
......
......@@ -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)
......
2001-12-31 Richard Henderson <rth@redhat.com>
* gcc.dg/asm-5.c: New.
2001-12-31 Paolo Carlini <pcarlini@unitus.it>
* g++.old-deja/g++.robertl/eb130.C: hash_set is now
......
/* Asm operands that are given as hard registers must keep the same
hard register all the way through compilation. Example derived
from glibc source. */
/* { dg-do compile { target alpha*-*-* } } */
/* { dg-options "-O2 -frename-registers -fcprop-registers" } */
/* { dg-final { scan-assembler "callsys1 .0 .19 .0 .16 .17" } } */
/* { dg-final { scan-assembler "callsys2 .0 .19 .0 .16 .17" } } */
struct stat {
int dummy;
};
struct kernel_stat {
int dummy;
};
extern int xstat_conv (int vers, struct kernel_stat *kbuf, void *ubuf);
extern int *__errno_location (void) __attribute__ ((__const__));
int
__fxstat (int vers, int fd, struct stat *buf)
{
struct kernel_stat kbuf;
int result;
if (vers == 0)
return
({
long _sc_ret, _sc_err;
{
register long _sc_0 __asm__("$0");
register long _sc_16 __asm__("$16");
register long _sc_17 __asm__("$17");
register long _sc_19 __asm__("$19");
_sc_0 = 91;
_sc_16 = (long) (fd);
_sc_17 = (long) (((struct kernel_stat *) buf));
__asm__("callsys1 %0 %1 %2 %3 %4"
: "=r"(_sc_0), "=r"(_sc_19)
: "0"(_sc_0), "r"(_sc_16), "r"(_sc_17)
: "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
"$22", "$23", "$24", "$25", "$27", "$28", "memory");
_sc_ret = _sc_0, _sc_err = _sc_19;
}
if (_sc_err)
{
(*__errno_location ()) = (_sc_ret);
_sc_ret = -1L;
}
_sc_ret;
});
result =
({
long _sc_ret, _sc_err;
{
register long _sc_0 __asm__("$0");
register long _sc_16 __asm__("$16");
register long _sc_17 __asm__("$17");
register long _sc_19 __asm__("$19");
_sc_0 = 91;
_sc_16 = (long) (fd);
_sc_17 = (long) ((&kbuf));
__asm__("callsys2 %0 %1 %2 %3 %4"
: "=r"(_sc_0), "=r"(_sc_19)
: "0"(_sc_0), "r"(_sc_16), "r"(_sc_17)
: "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
"$22", "$23", "$24", "$25", "$27", "$28", "memory");
_sc_ret = _sc_0, _sc_err = _sc_19;
}
if (_sc_err)
{
(*__errno_location ()) = (_sc_ret);
_sc_ret = -1L;
}
_sc_ret;
});
if (result == 0)
result = xstat_conv (vers, &kbuf, buf);
return result;
}
......@@ -898,14 +898,11 @@ make_decl_rtl (decl, asmspec)
/* If the user specified one of the eliminables registers here,
e.g., FRAME_POINTER_REGNUM, we don't want to get this variable
confused with that register and be eliminated. Although this
usage is somewhat suspect, we nevertheless use the following
kludge to avoid setting DECL_RTL to frame_pointer_rtx. */
SET_DECL_RTL (decl,
gen_rtx_REG (DECL_MODE (decl),
FIRST_PSEUDO_REGISTER));
REGNO (DECL_RTL (decl)) = reg_number;
confused with that register and be eliminated. This usage is
somewhat suspect... */
SET_DECL_RTL (decl, gen_rtx_raw_REG (DECL_MODE (decl), reg_number));
ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number;
REG_USERVAR_P (DECL_RTL (decl)) = 1;
if (TREE_STATIC (decl))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment