OSDN Git Service

*** empty log message ***
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 19 Apr 1992 02:12:25 +0000 (02:12 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 19 Apr 1992 02:12:25 +0000 (02:12 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@790 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cse.c
gcc/genemit.c

index 790696b..7c3057b 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -453,7 +453,7 @@ struct table_elt
       : (FIXED_REGNO_P (REGNO (X))                     \
         && REGNO_REG_CLASS (REGNO (X)) != NO_REGS) ? 0 \
       : 2)                                             \
-   : rtx_cost (X) * 2)                                 \
+   : rtx_cost (X, SET) * 2)
 
 /* Determine if the quantity number for register X represents a valid index
    into the `qty_...' variables.  */
@@ -569,8 +569,9 @@ static void cse_set_around_loop ();
 #define COSTS_N_INSNS(N) ((N) * 4 - 2)
 
 int
-rtx_cost (x)
+rtx_cost (x, outer_code)
      rtx x;
+     enum rtx_code outer_code;
 {
   register int i, j;
   register enum rtx_code code;
@@ -627,9 +628,9 @@ rtx_cost (x)
                              + GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD);
       return 2;
 #ifdef RTX_COSTS
-      RTX_COSTS (x, code);
+      RTX_COSTS (x, code, outer_code);
 #endif 
-      CONST_COSTS (x, code);
+      CONST_COSTS (x, code, outer_code);
     }
 
   /* Sum the costs of the sub-rtx's, plus cost of this operation,
@@ -638,10 +639,10 @@ rtx_cost (x)
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     if (fmt[i] == 'e')
-      total += rtx_cost (XEXP (x, i));
+      total += rtx_cost (XEXP (x, i), code);
     else if (fmt[i] == 'E')
       for (j = 0; j < XVECLEN (x, i); j++)
-       total += rtx_cost (XVECEXP (x, i, j));
+       total += rtx_cost (XVECEXP (x, i, j), code);
 
   return total;
 }
@@ -815,7 +816,7 @@ mention_regs (x)
   register int changed = 0;
 
   if (x == 0)
-    return;
+    return 0;
 
   code = GET_CODE (x);
   if (code == REG)
@@ -4157,6 +4158,11 @@ fold_rtx (x, insn)
          && (new = lookup_as_function (x, CONST_INT)) != 0)
        return new;
 
+      /* If this is a paradoxical SUBREG, we can't do anything with
+        it because we have no idea what value the extra bits would have.  */
+      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+       return x;
+
       /* Fold SUBREG_REG.  If it changed, see if we can simplify the SUBREG.
         We might be able to if the SUBREG is extracting a single word in an
         integral mode or extracting the low part.  */
@@ -4180,6 +4186,86 @@ fold_rtx (x, insn)
          if (new)
            return new;
        }
+
+      /* If this is a narrowing SUBREG and our operand is a REG, see if
+        we can find an equivalence for REG that is a arithmetic operation
+        in a wider mode where both operands are paradoxical SUBREGs
+        from objects of our result mode.  In that case, we couldn't report
+        an equivalent value for that operation, since we don't know what the
+        extra bits will be.  But we can find an equivalence for this SUBREG
+        by folding that operation is the narrow mode.  This allows us to
+        fold arithmetic in narrow modes when the machine only supports
+        word-sized arithmetic.  */
+
+      if (GET_CODE (folded_arg0) == REG
+         && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (folded_arg0)))
+       {
+         struct table_elt *elt;
+
+         /* We can use HASH here since we know that canon_hash won't be
+            called.  */
+         elt = lookup (folded_arg0,
+                       HASH (folded_arg0, GET_MODE (folded_arg0)),
+                       GET_MODE (folded_arg0));
+
+         if (elt)
+           elt = elt->first_same_value;
+
+         for (; elt; elt = elt->next_same_value)
+           {
+             /* Just check for unary and binary operations.  */
+             if (GET_RTX_CLASS (GET_CODE (elt->exp)) == '1'
+                 && GET_CODE (elt->exp) != SIGN_EXTEND
+                 && GET_CODE (elt->exp) != ZERO_EXTEND
+                 && GET_CODE (XEXP (elt->exp, 0)) == SUBREG
+                 && GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) == mode)
+               {
+                 rtx op0 = SUBREG_REG (XEXP (elt->exp, 0));
+
+                 if (GET_CODE (op0) != REG && ! CONSTANT_P (op0))
+                   op0 = fold_rtx (op0, 0);
+
+                 op0 = equiv_constant (op0);
+                 if (op0)
+                   new = simplify_unary_operation (GET_CODE (elt->exp), mode,
+                                                   op0, mode);
+               }
+             else if ((GET_RTX_CLASS (GET_CODE (elt->exp)) == '2'
+                       || GET_RTX_CLASS (GET_CODE (elt->exp)) == 'c')
+                      && ((GET_CODE (XEXP (elt->exp, 0)) == SUBREG
+                           && (GET_MODE (SUBREG_REG (XEXP (elt->exp, 0)))
+                               == mode))
+                          || CONSTANT_P (XEXP (elt->exp, 0)))
+                      && ((GET_CODE (XEXP (elt->exp, 1)) == SUBREG
+                           && (GET_MODE (SUBREG_REG (XEXP (elt->exp, 1)))
+                               == mode))
+                          || CONSTANT_P (XEXP (elt->exp, 1))))
+               {
+                 rtx op0 = gen_lowpart_common (mode, XEXP (elt->exp, 0));
+                 rtx op1 = gen_lowpart_common (mode, XEXP (elt->exp, 1));
+
+                 if (op0 && GET_CODE (op0) != REG && ! CONSTANT_P (op0))
+                   op0 = fold_rtx (op0, 0);
+
+                 if (op0)
+                   op0 = equiv_constant (op0);
+
+                 if (op1 && GET_CODE (op1) != REG && ! CONSTANT_P (op1))
+                   op1 = fold_rtx (op1, 0);
+
+                 if (op1)
+                   op1 = equiv_constant (op1);
+
+                 if (op0 && op1)
+                   new = simplify_binary_operation (GET_CODE (elt->exp), mode,
+                                                    op0, op1);
+               }
+
+             if (new)
+               return new;
+           }
+       }
+
       return x;
 
     case NOT:
index b8dbe43..f85444d 100644 (file)
@@ -47,12 +47,20 @@ static int insn_index_number;
 
 struct clobber_pat
 {
-  int code_number;             /* Counts only insns.  */
+  struct clobber_ent *insns;
   rtx pattern;
   int first_clobber;
   struct clobber_pat *next;
 } *clobber_list;
 
+/* Records one insn that uses the clobber list.  */
+
+struct clobber_ent
+{
+  int code_number;             /* Counts only insns.  */
+  struct clobber_ent *next;
+};
+
 static void
 max_operand_1 (x)
      rtx x;
@@ -271,14 +279,54 @@ gen_insn (insn)
 
       if (i != XVECLEN (insn, 1) - 1)
        {
-         register struct clobber_pat *new
-           = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat));
+         register struct clobber_pat *p;
+         register struct clobber_ent *link
+           = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent));
+         register int j;
+
+         link->code_number = insn_code_number;
+
+         /* See if any previous CLOBBER_LIST entry is the same as this
+            one.  */
+
+         for (p = clobber_list; p; p = p->next)
+           {
+             if (p->first_clobber != i + 1
+                 || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
+               continue;
+
+             for (j = i + 1; j < XVECLEN (insn, 1); j++)
+               {
+                 rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0);
+                 rtx new = XEXP (XVECEXP (insn, 1, j), 0);
+
+                 /* OLD and NEW are the same if both are to be a SCRATCH
+                    or if both are registers of the same mode and number.  */
+                 if (! ((GET_CODE (old) == MATCH_SCRATCH
+                         && GET_CODE (new) == MATCH_SCRATCH)
+                        || (GET_CODE (old) == REG && GET_CODE (new) == REG
+                            && GET_MODE (old) == GET_MODE (new)
+                            && REGNO (old) == REGNO (new))))
+                   break;
+               }
+      
+             if (j == XVECLEN (insn, 1))
+               break;
+           }
+
+         if (p == 0)
+           {
+             p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat));
          
-         new->code_number = insn_code_number;
-         new->pattern = insn;
-         new->first_clobber = i + 1;
-         new->next = clobber_list;
-         clobber_list = new;
+             p->insns = 0;
+             p->pattern = insn;
+             p->first_clobber = i + 1;
+             p->next = clobber_list;
+             clobber_list = p;
+           }
+
+         link->next = p->insns;
+         p->insns = link;
        }
     }
 
@@ -547,6 +595,7 @@ static void
 output_add_clobbers ()
 {
   struct clobber_pat *clobber;
+  struct clobber_ent *ent;
   int i;
 
   printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n");
@@ -558,7 +607,8 @@ output_add_clobbers ()
 
   for (clobber = clobber_list; clobber; clobber = clobber->next)
     {
-      printf ("    case %d:\n", clobber->code_number);
+      for (ent = clobber->insns; ent; ent = ent->next)
+       printf ("    case %d:\n", ent->code_number);
 
       for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
        {
@@ -567,7 +617,7 @@ output_add_clobbers ()
          printf (";\n");
        }
 
-      printf ("      break;\n");
+      printf ("      break;\n\n");
     }
 
   printf ("    default:\n");