OSDN Git Service

PR middle-end/26983
[pf3gnuchains/gcc-fork.git] / gcc / recog.c
index 9d937ed..cd1cb7d 100644 (file)
@@ -31,6 +31,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "hard-reg-set.h"
 #include "recog.h"
 #include "regs.h"
+#include "addresses.h"
 #include "expr.h"
 #include "function.h"
 #include "flags.h"
@@ -238,45 +239,6 @@ validate_change (rtx object, rtx *loc, rtx new, int in_group)
 }
 
 
-/* Function to be passed to for_each_rtx to test whether a piece of
-   RTL contains any mem/v.  */
-static int
-volatile_mem_p (rtx *x, void *data ATTRIBUTE_UNUSED)
-{
-  return (MEM_P (*x) && MEM_VOLATILE_P (*x));
-}
-
-/* Same as validate_change, but doesn't support groups, and it accepts
-   volatile mems if they're already present in the original insn.  */
-
-int
-validate_change_maybe_volatile (rtx object, rtx *loc, rtx new)
-{
-  int result;
-
-  if (validate_change (object, loc, new, 0))
-    return 1;
-
-  if (volatile_ok
-      /* If there isn't a volatile MEM, there's nothing we can do.  */
-      || !for_each_rtx (&PATTERN (object), volatile_mem_p, 0)
-      /* Make sure we're not adding or removing volatile MEMs.  */
-      || for_each_rtx (loc, volatile_mem_p, 0)
-      || for_each_rtx (&new, volatile_mem_p, 0)
-      || !insn_invalid_p (object))
-    return 0;
-
-  volatile_ok = 1;
-
-  gcc_assert (!insn_invalid_p (object));
-
-  result = validate_change (object, loc, new, 0);
-
-  volatile_ok = 0;
-
-  return result;
-}
-
 /* This subroutine of apply_change_group verifies whether the changes to INSN
    were valid; i.e. whether INSN can still be recognized.  */
 
@@ -736,6 +698,46 @@ validate_replace_src_group (rtx from, rtx to, rtx insn)
   d.insn = insn;
   note_uses (&PATTERN (insn), validate_replace_src_1, &d);
 }
+
+/* Try simplify INSN.
+   Invoke simplify_rtx () on every SET_SRC and SET_DEST inside the INSN's
+   pattern and return true if something was simplified.  */
+
+bool
+validate_simplify_insn (rtx insn)
+{
+  int i;
+  rtx pat = NULL;
+  rtx newpat = NULL;
+
+  pat = PATTERN (insn);
+
+  if (GET_CODE (pat) == SET)
+    {
+      newpat = simplify_rtx (SET_SRC (pat));
+      if (newpat && !rtx_equal_p (SET_SRC (pat), newpat))
+       validate_change (insn, &SET_SRC (pat), newpat, 1);
+      newpat = simplify_rtx (SET_DEST (pat));
+      if (newpat && !rtx_equal_p (SET_DEST (pat), newpat))
+       validate_change (insn, &SET_DEST (pat), newpat, 1);
+    }
+  else if (GET_CODE (pat) == PARALLEL)
+    for (i = 0; i < XVECLEN (pat, 0); i++)
+      {
+       rtx s = XVECEXP (pat, 0, i);
+
+       if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
+         {
+           newpat = simplify_rtx (SET_SRC (s));
+           if (newpat && !rtx_equal_p (SET_SRC (s), newpat))
+             validate_change (insn, &SET_SRC (s), newpat, 1);
+           newpat = simplify_rtx (SET_DEST (s));
+           if (newpat && !rtx_equal_p (SET_DEST (s), newpat))
+             validate_change (insn, &SET_DEST (s), newpat, 1);
+         }
+      }
+  return ((num_changes_pending () > 0) && (apply_change_group () > 0));
+}
 \f
 #ifdef HAVE_cc0
 /* Return 1 if the insn using CC0 set by INSN does not contain
@@ -2196,7 +2198,7 @@ preprocess_constraints (void)
                case 'p':
                  op_alt[j].is_address = 1;
                  op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
-                   [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+                     [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
                  break;
 
                case 'g':
@@ -2217,7 +2219,8 @@ preprocess_constraints (void)
                      op_alt[j].cl
                        = (reg_class_subunion
                           [(int) op_alt[j].cl]
-                          [(int) MODE_BASE_REG_CLASS (VOIDmode)]);
+                          [(int) base_reg_class (VOIDmode, ADDRESS,
+                                                 SCRATCH)]);
                      break;
                    }
 
@@ -2664,6 +2667,10 @@ reg_fits_class_p (rtx operand, enum reg_class cl, int offset,
                  enum machine_mode mode)
 {
   int regno = REGNO (operand);
+
+  if (cl == NO_REGS)
+    return 0;
+
   if (regno < FIRST_PSEUDO_REGISTER
       && TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
                            regno + offset))
@@ -2809,7 +2816,7 @@ split_all_insns (int upd_life)
 /* Same as split_all_insns, but do not expect CFG to be available.
    Used by machine dependent reorg passes.  */
 
-void
+unsigned int
 split_all_insns_noflow (void)
 {
   rtx next, insn;
@@ -2839,6 +2846,7 @@ split_all_insns_noflow (void)
            split_insn (insn);
        }
     }
+  return 0;
 }
 \f
 #ifdef HAVE_peephole2
@@ -3442,12 +3450,13 @@ gate_handle_peephole2 (void)
   return (optimize > 0 && flag_peephole2);
 }
 
-static void
+static unsigned int
 rest_of_handle_peephole2 (void)
 {
 #ifdef HAVE_peephole2
   peephole2_optimize ();
 #endif
+  return 0;
 }
 
 struct tree_opt_pass pass_peephole2 =
@@ -3467,10 +3476,11 @@ struct tree_opt_pass pass_peephole2 =
   'z'                                   /* letter */
 };
 
-static void
+static unsigned int
 rest_of_handle_split_all_insns (void)
 {
   split_all_insns (1);
+  return 0;
 }
 
 struct tree_opt_pass pass_split_all_insns =