summaryrefslogtreecommitdiff
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
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/regrename.c75
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/asm-5.c82
-rw-r--r--gcc/varasm.c13
5 files changed, 160 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6f9b2d6cd29..5253f248391 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+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.
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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 01f659ff540..d97cc967a6f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+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
diff --git a/gcc/testsuite/gcc.dg/asm-5.c b/gcc/testsuite/gcc.dg/asm-5.c
new file mode 100644
index 00000000000..7b8d0f2f6c5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asm-5.c
@@ -0,0 +1,82 @@
+/* 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;
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 419791d6363..b88615107e6 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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))