OSDN Git Service

Merge from gcc-2.8
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 6bc921b..a96e4f7 100644 (file)
@@ -1055,6 +1055,43 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
   return 1;
 }
 \f
+/* Check if PAT is an insn - or a part of it - used to set up an
+   argument for a function in a hard register.  */
+
+static int
+sets_function_arg_p (pat)
+     rtx pat;
+{
+  int i;
+  rtx inner_dest;
+
+  switch (GET_CODE (pat))
+    {
+    case INSN:
+      return sets_function_arg_p (PATTERN (pat));
+
+    case PARALLEL:
+      for (i = XVECLEN (pat, 0); --i >= 0;)
+       if (sets_function_arg_p (XVECEXP (pat, 0, i)))
+         return 1;
+
+      break;
+
+    case SET:
+      inner_dest = SET_DEST (pat);
+      while (GET_CODE (inner_dest) == STRICT_LOW_PART
+            || GET_CODE (inner_dest) == SUBREG
+            || GET_CODE (inner_dest) == ZERO_EXTRACT)
+       inner_dest = XEXP (inner_dest, 0);
+
+      return (GET_CODE (inner_dest) == REG
+             && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER
+             && FUNCTION_ARG_REGNO_P (REGNO (inner_dest)));
+    }
+
+  return 0;
+}
+
 /* LOC is the location within I3 that contains its pattern or the component
    of a PARALLEL of the pattern.  We validate that it is valid for combining.
 
@@ -1150,19 +1187,28 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed)
       if ((inner_dest != dest
           && (reg_overlap_mentioned_p (i2dest, inner_dest)
               || (i1dest && reg_overlap_mentioned_p (i1dest, inner_dest))))
+
          /* This is the same test done in can_combine_p except that we
             allow a hard register with SMALL_REGISTER_CLASSES if SRC is a
-            CALL operation.
-            Moreover, we can't test all_adjacent; we don't have to, since
-            this instruction will stay in place, thus we are not considering
-            to increase the lifetime of INNER_DEST.  */
+            CALL operation. Moreover, we can't test all_adjacent; we don't
+            have to, since this instruction will stay in place, thus we are
+            not considering increasing the lifetime of INNER_DEST.
+
+            Also, if this insn sets a function argument, combining it with
+            something that might need a spill could clobber a previous
+            function argument; the all_adjacent test in can_combine_p also
+            checks this; here, we do a more specific test for this case.  */
+            
          || (GET_CODE (inner_dest) == REG
              && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER
              && (! HARD_REGNO_MODE_OK (REGNO (inner_dest),
                                        GET_MODE (inner_dest))
                 || (SMALL_REGISTER_CLASSES && GET_CODE (src) != CALL
                     && ! REG_USERVAR_P (inner_dest)
-                    && FUNCTION_VALUE_REGNO_P (REGNO (inner_dest)))))
+                    && (FUNCTION_VALUE_REGNO_P (REGNO (inner_dest))
+                        || (FUNCTION_ARG_REGNO_P (REGNO (inner_dest))
+                            && i3 != 0
+                            && sets_function_arg_p (prev_nonnote_insn (i3)))))))
          || (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src)))
        return 0;
 
@@ -7188,7 +7234,7 @@ simplify_and_const_int (x, mode, varop, constop)
 /* We let num_sign_bit_copies recur into nonzero_bits as that is useful.
    We don't let nonzero_bits recur into num_sign_bit_copies, because that
    is less useful.  We can't allow both, because that results in exponential
-   run time recusion.  There is a nullstone testcase that triggered
+   run time recursion.  There is a nullstone testcase that triggered
    this.  This macro avoids accidental uses of num_sign_bit_copies.  */
 #define num_sign_bit_copies()