OSDN Git Service

* regrename.c (build_def_use): Don't rename asm operands that
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 Dec 2001 23:16:08 +0000 (23:16 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 Dec 2001 23:16:08 +0000 (23:16 +0000)
        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

gcc/ChangeLog
gcc/regrename.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/asm-5.c [new file with mode: 0644]
gcc/varasm.c

index 6f9b2d6..5253f24 100644 (file)
@@ -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.
index fca249e..720e0cf 100644 (file)
@@ -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)
index 01f659f..d97cc96 100644 (file)
@@ -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 (file)
index 0000000..7b8d0f2
--- /dev/null
@@ -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;
+}
index 419791d..b886151 100644 (file)
@@ -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))