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++)
{
/* 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];
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,
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;
}
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)
for (insn = bb->head; ; insn = NEXT_INSN (insn))
{
int n_ops, i, alt, predicated;
+ bool is_asm;
rtx set;
if (! INSN_P (insn))
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
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;
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)
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",
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)
--- /dev/null
+/* 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;
+}