OSDN Git Service

PR testsuite/25214
[pf3gnuchains/gcc-fork.git] / gcc / recog.c
index 8e6a62b..8a3fe35 100644 (file)
@@ -339,7 +339,7 @@ num_changes_pending (void)
 /* Tentatively apply the changes numbered NUM and up.
    Return 1 if all changes are valid, zero otherwise.  */
 
-static int
+int
 verify_changes (int num)
 {
   int i;
@@ -1003,7 +1003,7 @@ general_operand (rtx op, enum machine_mode mode)
 
       /* FLOAT_MODE subregs can't be paradoxical.  Combine will occasionally
         create such rtl, and we must reject it.  */
-      if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
+      if (SCALAR_FLOAT_MODE_P (GET_MODE (op))
          && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
        return 0;
 
@@ -1087,7 +1087,7 @@ register_operand (rtx op, enum machine_mode mode)
 
       /* FLOAT_MODE subregs can't be paradoxical.  Combine will occasionally
         create such rtl, and we must reject it.  */
-      if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
+      if (SCALAR_FLOAT_MODE_P (GET_MODE (op))
          && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
        return 0;
 
@@ -2429,16 +2429,22 @@ constrain_operands (int strict)
                break;
 
                /* No need to check general_operand again;
-                  it was done in insn-recog.c.  */
+                  it was done in insn-recog.c.  Well, except that reload
+                  doesn't check the validity of its replacements, but
+                  that should only matter when there's a bug.  */
              case 'g':
                /* Anything goes unless it is a REG and really has a hard reg
                   but the hard reg is not in the class GENERAL_REGS.  */
-               if (strict < 0
-                   || GENERAL_REGS == ALL_REGS
-                   || !REG_P (op)
-                   || (reload_in_progress
-                       && REGNO (op) >= FIRST_PSEUDO_REGISTER)
-                   || reg_fits_class_p (op, GENERAL_REGS, offset, mode))
+               if (REG_P (op))
+                 {
+                   if (strict < 0
+                       || GENERAL_REGS == ALL_REGS
+                       || (reload_in_progress
+                           && REGNO (op) >= FIRST_PSEUDO_REGISTER)
+                       || reg_fits_class_p (op, GENERAL_REGS, offset, mode))
+                     win = 1;
+                 }
+               else if (strict < 0 || general_operand (op, mode))
                  win = 1;
                break;
 
@@ -2853,6 +2859,8 @@ struct peep2_insn_data
 
 static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
 static int peep2_current;
+/* The number of instructions available to match a peep2.  */
+int peep2_current_count;
 
 /* A non-insn marker indicating the last insn of the block.
    The live_before regset for this element is correct, indicating
@@ -2866,14 +2874,12 @@ static int peep2_current;
 rtx
 peep2_next_insn (int n)
 {
-  gcc_assert (n < MAX_INSNS_PER_PEEP2 + 1);
+  gcc_assert (n <= peep2_current_count);
 
   n += peep2_current;
   if (n >= MAX_INSNS_PER_PEEP2 + 1)
     n -= MAX_INSNS_PER_PEEP2 + 1;
 
-  if (peep2_insn_data[n].insn == PEEP2_EOB)
-    return NULL_RTX;
   return peep2_insn_data[n].insn;
 }
 
@@ -3062,6 +3068,7 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
       /* Indicate that all slots except the last holds invalid data.  */
       for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
        peep2_insn_data[i].insn = NULL_RTX;
+      peep2_current_count = 0;
 
       /* Indicate that the last slot contains live_after data.  */
       peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
@@ -3090,12 +3097,25 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
              /* Record this insn.  */
              if (--peep2_current < 0)
                peep2_current = MAX_INSNS_PER_PEEP2;
+             if (peep2_current_count < MAX_INSNS_PER_PEEP2
+                 && peep2_insn_data[peep2_current].insn == NULL_RTX)
+               peep2_current_count++;
              peep2_insn_data[peep2_current].insn = insn;
              propagate_one_insn (pbi, insn);
              COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
 
-             /* Match the peephole.  */
-             try = peephole2_insns (PATTERN (insn), insn, &match_len);
+             if (RTX_FRAME_RELATED_P (insn))
+               {
+                 /* If an insn has RTX_FRAME_RELATED_P set, peephole
+                    substitution would lose the
+                    REG_FRAME_RELATED_EXPR that is attached.  */
+                 peep2_current_count = 0;
+                 try = NULL;
+               }
+             else
+               /* Match the peephole.  */
+               try = peephole2_insns (PATTERN (insn), insn, &match_len);
+
              if (try != NULL)
                {
                  /* If we are splitting a CALL_INSN, look for the CALL_INSN
@@ -3234,6 +3254,7 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
                  for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
                    peep2_insn_data[i].insn = NULL_RTX;
                  peep2_insn_data[peep2_current].insn = PEEP2_EOB;
+                 peep2_current_count = 0;
 #else
                  /* Back up lifetime information past the end of the
                     newly created sequence.  */
@@ -3249,6 +3270,9 @@ peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
                        {
                          if (--i < 0)
                            i = MAX_INSNS_PER_PEEP2;
+                         if (peep2_current_count < MAX_INSNS_PER_PEEP2
+                             && peep2_insn_data[i].insn == NULL_RTX)
+                           peep2_current_count++;
                          peep2_insn_data[i].insn = x;
                          propagate_one_insn (pbi, x);
                          COPY_REG_SET (peep2_insn_data[i].live_before, live);
@@ -3460,7 +3484,7 @@ rest_of_handle_split_all_insns (void)
 
 struct tree_opt_pass pass_split_all_insns =
 {
-  NULL,                                 /* name */
+  "split1",                             /* name */
   NULL,                                 /* gate */
   rest_of_handle_split_all_insns,       /* execute */
   NULL,                                 /* sub */
@@ -3471,7 +3495,7 @@ struct tree_opt_pass pass_split_all_insns =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
+  TODO_dump_func,                       /* todo_flags_finish */
   0                                     /* letter */
 };
 
@@ -3489,7 +3513,7 @@ gate_do_final_split (void)
 
 struct tree_opt_pass pass_split_for_shorten_branches =
 {
-  NULL,                                 /* name */
+  "split3",                             /* name */
   gate_do_final_split,                  /* gate */
   split_all_insns_noflow,               /* execute */
   NULL,                                 /* sub */
@@ -3500,7 +3524,7 @@ struct tree_opt_pass pass_split_for_shorten_branches =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
+  TODO_dump_func,                       /* todo_flags_finish */
   0                                     /* letter */
 };
 
@@ -3525,7 +3549,7 @@ gate_handle_split_before_regstack (void)
 
 struct tree_opt_pass pass_split_before_regstack =
 {
-  NULL,                                 /* name */
+  "split2",                             /* name */
   gate_handle_split_before_regstack,    /* gate */
   rest_of_handle_split_all_insns,       /* execute */
   NULL,                                 /* sub */
@@ -3536,6 +3560,6 @@ struct tree_opt_pass pass_split_before_regstack =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
+  TODO_dump_func,                       /* todo_flags_finish */
   0                                     /* letter */
 };