OSDN Git Service

* c-decl.c (store_parm_decls_oldstyle): Let diagnostic machinery
[pf3gnuchains/gcc-fork.git] / gcc / rtlanal.c
index 607f74c..da9774e 100644 (file)
@@ -58,6 +58,10 @@ static unsigned int cached_num_sign_bit_copies (rtx, enum machine_mode, rtx,
 static unsigned int num_sign_bit_copies1 (rtx, enum machine_mode, rtx,
                                           enum machine_mode, unsigned int);
 
+/* Offset of the first 'e', 'E' or 'V' operand for each rtx code, or
+   -1 if a code has no such operand.  */
+static int non_rtx_starting_operands[NUM_RTX_CODE];
+
 /* Bit flags that specify the machine subtype we are compiling for.
    Bits are tested using macros TARGET_... defined in the tm.h file
    and set by `-m...' switches.  Must be defined in rtlanal.c.  */
@@ -813,10 +817,10 @@ modified_between_p (rtx x, rtx start, rtx end)
       return 1;
 
     case MEM:
-      if (MEM_READONLY_P (x))
-       return 0;
       if (modified_between_p (XEXP (x, 0), start, end))
        return 1;
+      if (MEM_READONLY_P (x))
+       return 0;
       for (insn = NEXT_INSN (start); insn != end; insn = NEXT_INSN (insn))
        if (memory_modified_in_insn_p (x, insn))
          return 1;
@@ -871,10 +875,10 @@ modified_in_p (rtx x, rtx insn)
       return 1;
 
     case MEM:
-      if (MEM_READONLY_P (x))
-       return 0;
       if (modified_in_p (XEXP (x, 0), insn))
        return 1;
+      if (MEM_READONLY_P (x))
+       return 0;
       if (memory_modified_in_insn_p (x, insn))
        return 1;
       return 0;
@@ -2101,11 +2105,9 @@ may_trap_p (rtx x)
     case UMOD:
       if (HONOR_SNANS (GET_MODE (x)))
        return 1;
-      if (! CONSTANT_P (XEXP (x, 1))
-         || (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
-             && flag_trapping_math))
-       return 1;
-      if (XEXP (x, 1) == const0_rtx)
+      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+       return flag_trapping_math;
+      if (!CONSTANT_P (XEXP (x, 1)) || (XEXP (x, 1) == const0_rtx))
        return 1;
       break;
 
@@ -2624,6 +2626,82 @@ computed_jump_p (rtx insn)
   return 0;
 }
 
+/* Optimized loop of for_each_rtx, trying to avoid useless recursive
+   calls.  Processes the subexpressions of EXP and passes them to F.  */
+static int
+for_each_rtx_1 (rtx exp, int n, rtx_function f, void *data)
+{
+  int result, i, j;
+  const char *format = GET_RTX_FORMAT (GET_CODE (exp));
+  rtx *x;
+
+  for (; format[n] != '\0'; n++)
+    {
+      switch (format[n])
+       {
+       case 'e':
+         /* Call F on X.  */
+         x = &XEXP (exp, n);
+         result = (*f) (x, data);
+         if (result == -1)
+           /* Do not traverse sub-expressions.  */
+           continue;
+         else if (result != 0)
+           /* Stop the traversal.  */
+           return result;
+       
+         if (*x == NULL_RTX)
+           /* There are no sub-expressions.  */
+           continue;
+       
+         i = non_rtx_starting_operands[GET_CODE (*x)];
+         if (i >= 0)
+           {
+             result = for_each_rtx_1 (*x, i, f, data);
+             if (result != 0)
+               return result;
+           }
+         break;
+
+       case 'V':
+       case 'E':
+         if (XVEC (exp, n) == 0)
+           continue;
+         for (j = 0; j < XVECLEN (exp, n); ++j)
+           {
+             /* Call F on X.  */
+             x = &XVECEXP (exp, n, j);
+             result = (*f) (x, data);
+             if (result == -1)
+               /* Do not traverse sub-expressions.  */
+               continue;
+             else if (result != 0)
+               /* Stop the traversal.  */
+               return result;
+       
+             if (*x == NULL_RTX)
+               /* There are no sub-expressions.  */
+               continue;
+       
+             i = non_rtx_starting_operands[GET_CODE (*x)];
+             if (i >= 0)
+               {
+                 result = for_each_rtx_1 (*x, i, f, data);
+                 if (result != 0)
+                   return result;
+               }
+           }
+         break;
+
+       default:
+         /* Nothing to do.  */
+         break;
+       }
+    }
+
+  return 0;
+}
+
 /* Traverse X via depth-first search, calling F for each
    sub-expression (including X itself).  F is also passed the DATA.
    If F returns -1, do not traverse sub-expressions, but continue
@@ -2641,8 +2719,6 @@ int
 for_each_rtx (rtx *x, rtx_function f, void *data)
 {
   int result;
-  int length;
-  const char *format;
   int i;
 
   /* Call F on X.  */
@@ -2658,43 +2734,14 @@ for_each_rtx (rtx *x, rtx_function f, void *data)
     /* There are no sub-expressions.  */
     return 0;
 
-  length = GET_RTX_LENGTH (GET_CODE (*x));
-  format = GET_RTX_FORMAT (GET_CODE (*x));
-
-  for (i = 0; i < length; ++i)
-    {
-      switch (format[i])
-       {
-       case 'e':
-         result = for_each_rtx (&XEXP (*x, i), f, data);
-         if (result != 0)
-           return result;
-         break;
-
-       case 'V':
-       case 'E':
-         if (XVEC (*x, i) != 0)
-           {
-             int j;
-             for (j = 0; j < XVECLEN (*x, i); ++j)
-               {
-                 result = for_each_rtx (&XVECEXP (*x, i, j), f, data);
-                 if (result != 0)
-                   return result;
-               }
-           }
-         break;
-
-       default:
-         /* Nothing to do.  */
-         break;
-       }
-
-    }
+  i = non_rtx_starting_operands[GET_CODE (*x)];
+  if (i < 0)
+    return 0;
 
-  return 0;
+  return for_each_rtx_1 (*x, i, f, data);
 }
 
+
 /* Searches X for any reference to REGNO, returning the rtx of the
    reference found if any.  Otherwise, returns NULL_RTX.  */
 
@@ -3110,12 +3157,15 @@ parms_set (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
 }
 
 /* Look backward for first parameter to be loaded.
+   Note that loads of all parameters will not necessarily be
+   found if CSE has eliminated some of them (e.g., an argument
+   to the outer function is passed down as a parameter).
    Do not skip BOUNDARY.  */
 rtx
 find_first_parameter_load (rtx call_insn, rtx boundary)
 {
   struct parms_set_data parm;
-  rtx p, before;
+  rtx p, before, first_set;
 
   /* Since different machines initialize their parameter registers
      in different orders, assume nothing.  Collect the set of all
@@ -3137,6 +3187,7 @@ find_first_parameter_load (rtx call_insn, rtx boundary)
        parm.nregs++;
       }
   before = call_insn;
+  first_set = call_insn;
 
   /* Search backward for the first set of a register in this set.  */
   while (parm.nregs && before != boundary)
@@ -3159,9 +3210,20 @@ find_first_parameter_load (rtx call_insn, rtx boundary)
        }
 
       if (INSN_P (before))
-       note_stores (PATTERN (before), parms_set, &parm);
+       {
+         int nregs_old = parm.nregs;
+         note_stores (PATTERN (before), parms_set, &parm);
+         /* If we found something that did not set a parameter reg,
+            we're done.  Do not keep going, as that might result
+            in hoisting an insn before the setting of a pseudo
+            that is used by the hoisted insn. */
+         if (nregs_old != parm.nregs)
+           first_set = before;
+         else
+           break;
+       }
     }
-  return before;
+  return first_set;
 }
 
 /* Return true if we should avoid inserting code between INSN and preceding
@@ -4612,3 +4674,17 @@ get_condition (rtx jump, rtx *earliest, int allow_cc_mode, int valid_at_insn_p)
                                 allow_cc_mode, valid_at_insn_p);
 }
 
+\f
+/* Initialize non_rtx_starting_operands, which is used to speed up
+   for_each_rtx.  */
+void
+init_rtlanal (void)
+{
+  int i;
+  for (i = 0; i < NUM_RTX_CODE; i++)
+    {
+      const char *format = GET_RTX_FORMAT (i);
+      const char *first = strpbrk (format, "eEV");
+      non_rtx_starting_operands[i] = first ? first - format : -1;
+    }
+}