OSDN Git Service

* Makefile.in (recog.o): Don't depend on resource.h.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 27 May 2000 20:23:15 +0000 (20:23 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 27 May 2000 20:23:15 +0000 (20:23 +0000)
* recog.c: Don't include resource.h.
(recog_last_allowed_insn): Remove.
(recog_next_insn): Remove.
(struct peep2_insn_data): New.
(peep2_insn_data, peep2_current): New.
(peep2_next_insn): New.
(peep2_regno_dead_p, peep2_reg_dead_p): New.
(peep2_find_free_register): New.
(peephole2_optimize): Track life information by insn as we go.
* recog.h: Update declarations.
* resource.c (find_free_register, reg_dead_p): Remove.
* resource.h: Remove their declarations.
* toplev.c: Include hard-reg-set.h before recog.h.

* genconfig.c (max_insns_per_peep2): New.
(gen_peephole2): New.
(main): Call it.
* genemit.c (output_peephole2_scratches): Generate calls to
peep2_find_free_register; adjust surrounding code.
(main): Have insn-emit.c include hard-reg-set.h before recog.h.
* genrecog.c (change_state): Don't track last_insn.
(write_action): Write into *_pmatch_len before accepting.
(write_tree): Adjust peephole2_insns and subroutines to match.

* config/i386/i386.md (all peepholes): Use peep2_regno_dead_p.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34208 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/config/i386/i386.md
gcc/genconfig.c
gcc/genemit.c
gcc/genrecog.c
gcc/recog.c
gcc/recog.h
gcc/resource.c
gcc/resource.h
gcc/toplev.c

index 6dfc954..b8c478e 100644 (file)
@@ -1,5 +1,34 @@
 2000-05-27  Richard Henderson  <rth@cygnus.com>
 
+       * Makefile.in (recog.o): Don't depend on resource.h.
+       * recog.c: Don't include resource.h.
+       (recog_last_allowed_insn): Remove.
+       (recog_next_insn): Remove.
+       (struct peep2_insn_data): New.
+       (peep2_insn_data, peep2_current): New.
+       (peep2_next_insn): New.
+       (peep2_regno_dead_p, peep2_reg_dead_p): New.
+       (peep2_find_free_register): New.
+       (peephole2_optimize): Track life information by insn as we go.
+       * recog.h: Update declarations.
+       * resource.c (find_free_register, reg_dead_p): Remove.
+       * resource.h: Remove their declarations.
+       * toplev.c: Include hard-reg-set.h before recog.h.
+
+       * genconfig.c (max_insns_per_peep2): New.
+       (gen_peephole2): New.
+       (main): Call it.
+       * genemit.c (output_peephole2_scratches): Generate calls to
+       peep2_find_free_register; adjust surrounding code.
+       (main): Have insn-emit.c include hard-reg-set.h before recog.h.
+       * genrecog.c (change_state): Don't track last_insn.
+       (write_action): Write into *_pmatch_len before accepting.
+       (write_tree): Adjust peephole2_insns and subroutines to match.
+
+       * config/i386/i386.md (all peepholes): Use peep2_regno_dead_p.
+
+2000-05-27  Richard Henderson  <rth@cygnus.com>
+
        * function.c (thread_prologue_epilogue_insns): Don't move the
        line note at the head of the chain.  Only force a lineno note
        before the end of block 0.
index c362db2..5456c47 100644 (file)
@@ -1382,7 +1382,7 @@ final.o : final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h intl.h \
    dbxout.h $(BASIC_BLOCK_H)
 recog.o : recog.c $(CONFIG_H) system.h $(RTL_H) function.h $(BASIC_BLOCK_H) \
    $(REGS_H) $(RECOG_H) hard-reg-set.h flags.h insn-config.h insn-attr.h \
-   insn-flags.h insn-codes.h real.h toplev.h output.h resource.h 
+   insn-flags.h insn-codes.h real.h toplev.h output.h
 reg-stack.o : reg-stack.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) $(RECOG_H) \
    $(REGS_H) hard-reg-set.h flags.h insn-config.h insn-flags.h toplev.h \
    varray.h function.h
index 5696c26..cdadf5d 100644 (file)
   [(match_scratch:SI 1 "r")
    (set (match_operand:SI 0 "memory_operand" "")
         (const_int 0))]
-  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
-   && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+  "! optimize_size
    && ! TARGET_USE_MOV0
-   && TARGET_SPLIT_LONG_MOVES"
+   && TARGET_SPLIT_LONG_MOVES
+   && get_attr_length (insn) >= ix86_cost->large_insn
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 1) (const_int 0))
              (clobber (reg:CC 17))])
    (set (match_dup 0) (match_dup 1))]
   [(match_scratch:HI 1 "r")
    (set (match_operand:HI 0 "memory_operand" "")
         (const_int 0))]
-  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
-   && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+  "! optimize_size
    && ! TARGET_USE_MOV0
-   && TARGET_SPLIT_LONG_MOVES"
+   && TARGET_SPLIT_LONG_MOVES
+   && get_attr_length (insn) >= ix86_cost->large_insn
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 2) (const_int 0))
              (clobber (reg:CC 17))])
    (set (match_dup 0) (match_dup 1))]
   [(match_scratch:QI 1 "q")
    (set (match_operand:QI 0 "memory_operand" "")
         (const_int 0))]
-  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
-   && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+  "! optimize_size
    && ! TARGET_USE_MOV0
-   && TARGET_SPLIT_LONG_MOVES"
+   && TARGET_SPLIT_LONG_MOVES
+   && get_attr_length (insn) >= ix86_cost->large_insn
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 2) (const_int 0))
              (clobber (reg:CC 17))])
    (set (match_dup 0) (match_dup 1))]
   [(match_scratch:SI 2 "r")
    (set (match_operand:SI 0 "memory_operand" "")
         (match_operand:SI 1 "immediate_operand" ""))]
-  "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
-  && TARGET_SPLIT_LONG_MOVES"
+  "! optimize_size
+   && get_attr_length (insn) >= ix86_cost->large_insn
+   && TARGET_SPLIT_LONG_MOVES"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (match_dup 2))]
   "")
 ;; represented using a modRM byte.  The XOR replacement is long decoded,
 ;; so this split helps here as well.
 ;;
-;; Note: Can't do this as a regular split because reg_dead_p assumes
-;; resource info is live.
+;; Note: Can't do this as a regular split because we can't get proper
+;; lifetime information then.
 
 (define_peephole2
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
        (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
   "!optimize_size
-   && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+   && peep2_regno_dead_p (0, FLAGS_REG)
    && ((TARGET_PENTIUM 
         && (GET_CODE (operands[0]) != MEM
             || !memory_displacement_operand (operands[0], SImode)))
   [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
        (not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
   "!optimize_size
-   && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+   && peep2_regno_dead_p (0, FLAGS_REG)
    && ((TARGET_PENTIUM 
         && (GET_CODE (operands[0]) != MEM
             || !memory_displacement_operand (operands[0], HImode)))
   [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
        (not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
   "!optimize_size
-   && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+   && peep2_regno_dead_p (0, FLAGS_REG)
    && ((TARGET_PENTIUM 
         && (GET_CODE (operands[0]) != MEM
             || !memory_displacement_operand (operands[0], QImode)))
     || GET_MODE (operands[0]) == HImode
     || GET_MODE (operands[0]) == SImode)
    && (! TARGET_USE_MOV0 || optimize_size)
-   && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 0) (const_int 0))
              (clobber (reg:CC 17))])]
   "operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]));")
   "(GET_MODE (operands[0]) == HImode
     || GET_MODE (operands[0]) == SImode)
    && (optimize_size || TARGET_PENTIUM)
-   && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 0) (const_int -1))
              (clobber (reg:CC 17))])]
   "operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]));")
   [(set (match_operand:SI 0 "register_operand" "")
        (plus:SI (match_dup 0)
                 (match_operand:SI 1 "nonmemory_operand" "")))]
-  "reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
+  "peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
              (clobber (reg:CC 17))])]
   "")
   [(set (match_operand:SI 0 "register_operand" "")
        (mult:SI (match_dup 0)
                 (match_operand:SI 1 "immediate_operand" "")))]
-  "reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
+  "exact_log2 (INTVAL (operands[1])) >= 0
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
              (clobber (reg:CC 17))])]
   "operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
index 6508c39..e7964ab 100644 (file)
@@ -42,6 +42,9 @@ static int have_peephole2_flag;
 /* Maximum number of insns seen in a split.  */
 static int max_insns_per_split = 1;
 
+/* Maximum number of input insns for peephole2.  */
+static int max_insns_per_peep2;
+
 static int clobbers_seen_this_insn;
 static int dup_operands_seen_this_insn;
 
@@ -239,6 +242,26 @@ gen_peephole (peep)
     walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
 }
 
+static void
+gen_peephole2 (peep)
+     rtx peep;
+{
+  int i, n;
+
+  /* Look through the patterns that are matched
+     to compute the maximum operand number.  */
+  for (i = XVECLEN (peep, 0) - 1; i >= 0; --i)
+    walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
+
+  /* Look at the number of insns this insn can be matched from.  */
+  for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i)
+    if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP
+       && GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH)
+      n++;
+  if (n > max_insns_per_peep2)
+    max_insns_per_peep2 = n;
+}
+
 extern int main PARAMS ((int, char **));
 
 int
@@ -289,7 +312,7 @@ from the machine description file `md'.  */\n\n");
 
          case DEFINE_PEEPHOLE2:
            have_peephole2_flag = 1;
-           gen_split (desc);
+           gen_peephole2 (desc);
            break;
 
          case DEFINE_PEEPHOLE:
@@ -302,9 +325,8 @@ from the machine description file `md'.  */\n\n");
        }
     }
 
-  printf ("\n#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
-
-  printf ("\n#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
+  printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
+  printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
 
   /* This is conditionally defined, in case the user writes code which emits
      more splits than we can readily see (and knows s/he does it).  */
@@ -328,7 +350,10 @@ from the machine description file `md'.  */\n\n");
     printf ("#define HAVE_peephole 1\n");
 
   if (have_peephole2_flag)
-    printf ("#define HAVE_peephole2 1\n");
+    {
+      printf ("#define HAVE_peephole2 1\n");
+      printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
+    }
 
   fflush (stdout);
   return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
index dab819b..54793d4 100644 (file)
@@ -699,10 +699,7 @@ output_peephole2_scratches (split)
   int i;
   int insn_nr = 0;
 
-  printf ("  rtx first_insn ATTRIBUTE_UNUSED;\n");
-  printf ("  rtx last_insn ATTRIBUTE_UNUSED;\n");
   printf ("  HARD_REG_SET _regs_allocated;\n");
-
   printf ("  CLEAR_HARD_REG_SET (_regs_allocated);\n");
 
   for (i = 0; i < XVECLEN (split, 0); i++)
@@ -721,15 +718,11 @@ output_peephole2_scratches (split)
              }
            else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
              cur_insn_nr++;
-         printf ("  first_insn = recog_next_insn (curr_insn, %d);\n", insn_nr);
-         if (last_insn_nr > insn_nr)
-           printf ("  last_insn = recog_next_insn (curr_insn, %d);\n",
-                   last_insn_nr - 1);
-         else
-           printf ("  last_insn = 0;\n");
-         printf ("  if ((operands[%d] = find_free_register (first_insn, last_insn, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
+
+         printf ("  if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
     return NULL;\n", 
                  XINT (elt, 0),
+                 insn_nr, last_insn_nr,
                  XSTR (elt, 1),
                  GET_MODE_NAME (GET_MODE (elt)));
 
@@ -777,8 +770,8 @@ from the machine description file `md'.  */\n\n");
   printf ("#include \"insn-config.h\"\n");
   printf ("#include \"insn-flags.h\"\n");
   printf ("#include \"insn-codes.h\"\n");
-  printf ("#include \"recog.h\"\n");
   printf ("#include \"hard-reg-set.h\"\n");
+  printf ("#include \"recog.h\"\n");
   printf ("#include \"resource.h\"\n");
   printf ("#include \"reload.h\"\n\n");
   printf ("#define FAIL return (end_sequence (), _val)\n");
index 7c435a0..b955eb0 100644 (file)
@@ -272,8 +272,8 @@ static struct decision *write_switch
 static void write_cond
   PARAMS ((struct decision_test *, int, enum routine_type));
 static void write_action
-  PARAMS ((struct decision_test *, int, int, struct decision *,
-        enum routine_type));
+  PARAMS ((struct decision *, struct decision_test *, int, int,
+          struct decision *, enum routine_type));
 static int is_unconditional
   PARAMS ((struct decision_test *, enum routine_type));
 static int write_node
@@ -1578,10 +1578,6 @@ change_state (oldpos, newpos, afterward, indent)
     if (newpos[new_has_insn] >= 'A' && newpos[new_has_insn] <= 'Z')
       break;
 
-  /* Make sure to reset the last_insn pointer when popping back up.  */
-  if (old_has_insn >= 0 && new_has_insn < 0)
-    printf ("%slast_insn = insn;\n", indent);
-
   /* Go down to desired level.  */
   while (depth < ndepth)
     {
@@ -1591,21 +1587,20 @@ change_state (oldpos, newpos, afterward, indent)
          /* We can only fail if we're moving down the tree.  */
          if (old_has_insn >= 0 && oldpos[old_has_insn] >= newpos[depth])
            {
-             printf ("%slast_insn = recog_next_insn (insn, %d);\n", 
+             printf ("%stem = peep2_next_insn (%d);\n", 
                      indent, newpos[depth] - 'A');
            }
          else
            {
-             printf ("%stem = recog_next_insn (insn, %d);\n", 
+             printf ("%stem = peep2_next_insn (%d);\n", 
                      indent, newpos[depth] - 'A');
              printf ("%sif (tem == NULL_RTX)\n", indent);
              if (afterward)
                printf ("%s  goto L%d;\n", indent, afterward->number);
              else
                printf ("%s  goto ret0;\n", indent);
-             printf ("%slast_insn = tem;\n", indent);
            }
-         printf ("%sx%d = PATTERN (last_insn);\n", indent, depth + 1);
+         printf ("%sx%d = PATTERN (tem);\n", indent, depth + 1);
        }
       else if (newpos[depth] >= 'a' && newpos[depth] <= 'z')
        printf ("%sx%d = XVECEXP (x%d, 0, %d);\n",
@@ -1888,7 +1883,8 @@ write_cond (p, depth, subroutine_type)
    perform a state change.  For the `accept' tests we must do more work.  */
 
 static void
-write_action (test, depth, uncond, success, subroutine_type)
+write_action (p, test, depth, uncond, success, subroutine_type)
+     struct decision *p;
      struct decision_test *test;
      int depth, uncond;
      struct decision *success;
@@ -1942,9 +1938,20 @@ write_action (test, depth, uncond, success, subroutine_type)
          break;
 
        case PEEPHOLE2:
-         printf ("%stem = gen_peephole2_%d (insn, operands);\n",
-                 indent, test->u.insn.code_number);
-         printf ("%sif (tem != 0)\n%s  goto ret1;\n", indent, indent);
+         {
+           int match_len = 0, i;
+
+           for (i = strlen (p->position) - 1; i >= 0; --i)
+             if (p->position[i] >= 'A' && p->position[i] <= 'Z')
+               {
+                 match_len = p->position[i] - 'A';
+                 break;
+               }
+           printf ("%s*_pmatch_len = %d;\n", indent, match_len);
+           printf ("%stem = gen_peephole2_%d (insn, operands);\n",
+                   indent, test->u.insn.code_number);
+           printf ("%sif (tem != 0)\n%s  return tem;\n", indent, indent);
+         }
          break;
 
        default:
@@ -2027,7 +2034,7 @@ write_node (p, depth, subroutine_type)
       printf (")\n");
     }
 
-  write_action (last_test, depth, uncond, p->success.first, subroutine_type);
+  write_action (p, last_test, depth, uncond, p->success.first, subroutine_type);
 
   return uncond > 0;
 }
@@ -2090,7 +2097,7 @@ write_tree (head, prevpos, type, initial)
       };
 
       static const char * const call_suffix[] = {
-         ", pnum_clobbers", "", ", _plast_insn"
+         ", pnum_clobbers", "", ", _pmatch_len"
       };
 
       /* This node has been broken out into a separate subroutine.
@@ -2167,12 +2174,13 @@ split%s (x0, insn)\n\
      rtx insn ATTRIBUTE_UNUSED;\n", s_or_e, extension);
       break;
     case PEEPHOLE2:
-      printf ("%srtx peephole2%s PARAMS ((rtx, rtx, rtx *));\n", s_or_e, extension);
+      printf ("%srtx peephole2%s PARAMS ((rtx, rtx, int *));\n",
+             s_or_e, extension);
       printf ("%srtx\n\
-peephole2%s (x0, insn, _plast_insn)\n\
+peephole2%s (x0, insn, _pmatch_len)\n\
      register rtx x0;\n\
      rtx insn ATTRIBUTE_UNUSED;\n\
-     rtx *_plast_insn ATTRIBUTE_UNUSED;\n", s_or_e, extension);
+     int *_pmatch_len ATTRIBUTE_UNUSED;\n", s_or_e, extension);
       break;
     }
 
@@ -2180,8 +2188,6 @@ peephole2%s (x0, insn, _plast_insn)\n\
   for (i = 1; i <= max_depth; i++)
     printf ("  register rtx x%d ATTRIBUTE_UNUSED;\n", i);
 
-  if (type == PEEPHOLE2)
-    printf ("  register rtx last_insn = insn;\n");
   printf ("  %s tem ATTRIBUTE_UNUSED;\n", IS_SPLIT (type) ? "rtx" : "int");
 
   if (head->first)
@@ -2189,8 +2195,6 @@ peephole2%s (x0, insn, _plast_insn)\n\
   else
     printf ("  goto ret0;\n");
 
-  if (type == PEEPHOLE2)
-    printf (" ret1:\n  *_plast_insn = last_insn;\n  return tem;\n");
   printf (" ret0:\n  return %d;\n}\n\n", IS_SPLIT (type) ? 0 : -1);
 }
 
index bac7e47..8760041 100644 (file)
@@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "basic-block.h"
 #include "output.h"
-#include "resource.h"
 
 #ifndef STACK_PUSH_CODE
 #ifdef STACK_GROWS_DOWNWARD
@@ -2682,100 +2681,340 @@ split_all_insns (upd_life)
 }
 \f
 #ifdef HAVE_peephole2
-/* This is the last insn we'll allow recog_next_insn to consider.  */
-static rtx recog_last_allowed_insn;
+struct peep2_insn_data
+{
+  rtx insn;
+  regset live_before;
+};
+
+static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
+static int peep2_current;
+
+/* A non-insn marker indicating the last insn of the block.
+   The live_before regset for this element is correct, indicating
+   global_live_at_end for the block.  */
+#define PEEP2_EOB      pc_rtx
+
+/* Return the Nth non-note insn after `current', or return NULL_RTX if it
+   does not exist.  Used by the recognizer to find the next insn to match
+   in a multi-insn pattern.  */
 
-/* Return the Nth non-note insn after INSN, or return NULL_RTX if it does
-   not exist.  Used by the recognizer to find the next insn to match in a
-   multi-insn pattern.  */
 rtx
-recog_next_insn (insn, n)
-     rtx insn;
+peep2_next_insn (n)
      int n;
 {
-  if (insn != NULL_RTX)
+  if (n >= MAX_INSNS_PER_PEEP2 + 1)
+    abort ();
+
+  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;
+}
+
+/* Return true if REGNO is dead before the Nth non-note insn
+   after `current'.  */
+
+int
+peep2_regno_dead_p (ofs, regno)
+     int ofs;
+     int regno;
+{
+  if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
+    abort ();
+
+  ofs += peep2_current;
+  if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
+    ofs -= MAX_INSNS_PER_PEEP2 + 1;
+
+  if (peep2_insn_data[ofs].insn == NULL_RTX)
+    abort ();
+
+  return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno);
+}
+
+/* Similarly for a REG.  */
+
+int
+peep2_reg_dead_p (ofs, reg)
+     int ofs;
+     rtx reg;
+{
+  int regno, n;
+
+  if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
+    abort ();
+
+  ofs += peep2_current;
+  if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
+    ofs -= MAX_INSNS_PER_PEEP2 + 1;
+
+  if (peep2_insn_data[ofs].insn == NULL_RTX)
+    abort ();
+
+  regno = REGNO (reg);
+  n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+  while (--n >= 0)
+    if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
+      return 0;
+  return 1;
+}
+
+/* Try to find a hard register of mode MODE, matching the register class in
+   CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
+   remains available until the end of LAST_INSN.  LAST_INSN may be NULL_RTX,
+   in which case the only condition is that the register must be available
+   before CURRENT_INSN.
+   Registers that already have bits set in REG_SET will not be considered.
+
+   If an appropriate register is available, it will be returned and the
+   corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
+   returned.  */
+
+rtx
+peep2_find_free_register (from, to, class_str, mode, reg_set)
+     int from, to;
+     const char *class_str;
+     enum machine_mode mode;
+     HARD_REG_SET *reg_set;
+{
+  static int search_ofs;
+  enum reg_class class;
+  HARD_REG_SET live;
+  int i;
+
+  if (from >= MAX_INSNS_PER_PEEP2 + 1 || to >= MAX_INSNS_PER_PEEP2 + 1)
+    abort ();
+
+  from += peep2_current;
+  if (from >= MAX_INSNS_PER_PEEP2 + 1)
+    from -= MAX_INSNS_PER_PEEP2 + 1;
+  to += peep2_current;
+  if (to >= MAX_INSNS_PER_PEEP2 + 1)
+    to -= MAX_INSNS_PER_PEEP2 + 1;
+
+  if (peep2_insn_data[from].insn == NULL_RTX)
+    abort ();
+  REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
+
+  while (from != to)
     {
-      while (n > 0)
+      HARD_REG_SET this_live;
+
+      if (++from >= MAX_INSNS_PER_PEEP2 + 1)
+       from = 0;
+      if (peep2_insn_data[from].insn == NULL_RTX)
+       abort ();
+      REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
+      IOR_HARD_REG_SET (live, this_live);
+    }
+
+  class = (class_str[0] == 'r' ? GENERAL_REGS
+          : REG_CLASS_FROM_LETTER (class_str[0]));
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      int raw_regno, regno, success, j;
+
+      /* Distribute the free registers as much as possible.  */
+      raw_regno = search_ofs + i;
+      if (raw_regno >= FIRST_PSEUDO_REGISTER)
+       raw_regno -= FIRST_PSEUDO_REGISTER;
+#ifdef REG_ALLOC_ORDER
+      regno = reg_alloc_order[raw_regno];
+#else
+      regno = raw_regno;
+#endif
+
+      /* Don't allocate fixed registers.  */
+      if (fixed_regs[regno])
+       continue;
+      /* Make sure the register is of the right class.  */
+      if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno))
+       continue;
+      /* And can support the mode we need.  */
+      if (! HARD_REGNO_MODE_OK (regno, mode))
+       continue;
+      /* And that we don't create an extra save/restore.  */
+      if (! call_used_regs[regno] && ! regs_ever_live[regno])
+       continue;
+      /* And we don't clobber traceback for noreturn functions.  */
+      if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
+         && (! reload_completed || frame_pointer_needed))
+       continue;
+
+      success = 1;
+      for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+       {
+         if (TEST_HARD_REG_BIT (*reg_set, regno + j)
+             || TEST_HARD_REG_BIT (live, regno + j))
+           {
+             success = 0;
+             break;
+           }
+       }
+      if (success)
        {
-         if (insn == recog_last_allowed_insn)
-           return NULL_RTX;
+         for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+           SET_HARD_REG_BIT (*reg_set, regno + j);
 
-         insn = NEXT_INSN (insn);
-         if (insn == NULL_RTX)
-           break;
+         /* Start the next search with the next register.  */
+         if (++raw_regno >= FIRST_PSEUDO_REGISTER)
+           raw_regno = 0;
+         search_ofs = raw_regno;
 
-         if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-           n -= 1;
+         return gen_rtx_REG (mode, regno);
        }
     }
 
-  return insn;
+  search_ofs = 0;
+  return NULL_RTX;
 }
 
 /* Perform the peephole2 optimization pass. */
+
 void
 peephole2_optimize (dump_file)
      FILE *dump_file ATTRIBUTE_UNUSED;
 {
+  regset_head rs_heads[MAX_INSNS_PER_PEEP2 + 2];
   rtx insn, prev;
-  int i, changed;
+  regset live;
+  int i, b;
+#ifdef HAVE_conditional_execution
   sbitmap blocks;
+  int changed;
+#endif
 
-  /* ??? TODO: Arrange with resource.c to start at bb->global_live_at_end
-     and backtrack insn by insn as we proceed through the block.  In this
-     way we'll not need to keep searching forward from the beginning of 
-     basic blocks to find register life info.  */
-
-  init_resource_info (NULL);
+  /* Initialize the regsets we're going to use.  */
+  for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
+    peep2_insn_data[i].live_before = INITIALIZE_REG_SET (rs_heads[i]);
+  live = INITIALIZE_REG_SET (rs_heads[i]);
 
+#ifdef HAVE_conditional_execution
   blocks = sbitmap_alloc (n_basic_blocks);
   sbitmap_zero (blocks);
   changed = 0;
+#else
+  count_or_remove_death_notes (NULL, 1);
+#endif
 
-  for (i = n_basic_blocks - 1; i >= 0; --i)
+  for (b = n_basic_blocks - 1; b >= 0; --b)
     {
-      basic_block bb = BASIC_BLOCK (i);
+      basic_block bb = BASIC_BLOCK (b);
+      struct propagate_block_info *pbi;
+
+      /* 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;
+
+      /* Indicate that the last slot contains live_after data.  */
+      peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
+      peep2_current = MAX_INSNS_PER_PEEP2;
 
-      /* Since we don't update life info until the very end, we can't
-        allow matching instructions that we've replaced before.  Walk
-        backward through the basic block so that we don't have to 
-        care about subsequent life info; recog_last_allowed_insn to
-        restrict how far forward we will allow the match to proceed.  */
+      /* Start up propagation.  */
+      COPY_REG_SET (live, bb->global_live_at_end);
+      COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
+
+#ifdef HAVE_conditional_execution
+      pbi = init_propagate_block_info (bb, live, NULL, 0);
+#else
+      pbi = init_propagate_block_info (bb, live, NULL, PROP_DEATH_NOTES);
+#endif
 
-      recog_last_allowed_insn = NEXT_INSN (bb->end);
       for (insn = bb->end; ; insn = prev)
        {
          prev = PREV_INSN (insn);
          if (INSN_P (insn))
            {
-             rtx try, last_insn;
-
-             try = peephole2_insns (PATTERN (insn), insn, &last_insn);
+             rtx try;
+             int match_len;
+
+             /* Record this insn.  */
+             if (--peep2_current < 0)
+               peep2_current = MAX_INSNS_PER_PEEP2;
+             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 (try != NULL)
                {
-                 flow_delete_insn_chain (insn, last_insn);
+                 i = match_len + peep2_current;
+                 if (i >= MAX_INSNS_PER_PEEP2 + 1)
+                   i -= MAX_INSNS_PER_PEEP2 + 1;
+
+                 /* Replace the old sequence with the new.  */
+                 flow_delete_insn_chain (insn, peep2_insn_data[i].insn);
                  try = emit_insn_after (try, prev);
 
-                 if (last_insn == bb->end)
+                 /* Adjust the basic block boundaries.  */
+                 if (peep2_insn_data[i].insn == bb->end)
                    bb->end = try;
                  if (insn == bb->head)
                    bb->head = NEXT_INSN (prev);
 
-                 recog_last_allowed_insn = NEXT_INSN (prev);
-                 SET_BIT (blocks, i);
+#ifdef HAVE_conditional_execution
+                 /* With conditional execution, we cannot back up the
+                    live information so easily, since the conditional
+                    death data structures are not so self-contained.
+                    So record that we've made a modification to this
+                    block and update life information at the end.  */
+                 SET_BIT (blocks, b);
                  changed = 1;
+
+                 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;
+#else
+                 /* Back up lifetime information past the end of the
+                    newly created sequence.  */
+                 if (++i >= MAX_INSNS_PER_PEEP2 + 1)
+                   i = 0;
+                 COPY_REG_SET (live, peep2_insn_data[i].live_before);
+
+                 /* Update life information for the new sequence.  */
+                 do
+                   {
+                     if (INSN_P (try))
+                       {
+                         if (--i < 0)
+                           i = MAX_INSNS_PER_PEEP2;
+                         peep2_insn_data[i].insn = try;
+                         propagate_one_insn (pbi, try);
+                         COPY_REG_SET (peep2_insn_data[i].live_before, live);
+                       }
+                     try = PREV_INSN (try);
+                   }
+                 while (try != prev);
+
+                 /* ??? Should verify that LIVE now matches what we
+                    had before the new sequence.  */
+
+                 peep2_current = i;
+#endif
                }
            }
 
          if (insn == bb->head)
            break;
        }
+
+      free_propagate_block_info (pbi);
     }
 
-  free_resource_info ();
+  for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
+    FREE_REG_SET (peep2_insn_data[i].live_before);
+  FREE_REG_SET (live);
 
-  compute_bb_for_insn (get_max_uid ());
+#ifdef HAVE_conditional_execution
   count_or_remove_death_notes (blocks, 1);
   update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
-}
+  sbitmap_free (blocks);
 #endif
+}
+#endif /* HAVE_peephole2 */
index 51f6fb0..465013a 100644 (file)
@@ -116,9 +116,16 @@ extern void add_clobbers           PARAMS ((rtx, int));
 extern void insn_extract               PARAMS ((rtx));
 extern void extract_insn               PARAMS ((rtx));
 extern void preprocess_constraints     PARAMS ((void));
-extern rtx recog_next_insn             PARAMS ((rtx, int));
+extern rtx peep2_next_insn             PARAMS ((int));
+extern int peep2_regno_dead_p          PARAMS ((int, int));
+extern int peep2_reg_dead_p            PARAMS ((int, rtx));
+#ifdef CLEAR_HARD_REG_SET
+extern rtx peep2_find_free_register    PARAMS ((int, int, const char *,
+                                                enum machine_mode,
+                                                HARD_REG_SET *));
+#endif
 extern void peephole2_optimize         PARAMS ((FILE *));
-extern rtx peephole2_insns             PARAMS ((rtx, rtx, rtx *));
+extern rtx peephole2_insns             PARAMS ((rtx, rtx, int *));
 
 /* Nonzero means volatile operands are recognized.  */
 extern int volatile_ok;
index d84fabe..af1b4ed 100644 (file)
@@ -1268,109 +1268,3 @@ mark_end_of_function_resources (trial, include_delayed_effects)
   mark_referenced_resources (trial, &end_of_function_needs,
                             include_delayed_effects);
 }
-\f
-/* Try to find a hard register of mode MODE, matching the register class in
-   CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
-   remains available until the end of LAST_INSN.  LAST_INSN may be NULL_RTX,
-   in which case the only condition is that the register must be available
-   before CURRENT_INSN.
-   Registers that already have bits set in REG_SET will not be considered.
-
-   If an appropriate register is available, it will be returned and the
-   corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
-   returned.  */
-
-rtx
-find_free_register (current_insn, last_insn, class_str, mode, reg_set)
-     rtx current_insn, last_insn;
-     const char *class_str;
-     int mode;
-     HARD_REG_SET *reg_set;
-{
-  int i, j;
-  struct resources used;
-  unsigned char clet = class_str[0];
-  enum reg_class class
-    = (clet == 'r' ? GENERAL_REGS :  REG_CLASS_FROM_LETTER (clet));
-
-  mark_target_live_regs (get_insns (), current_insn, &used);
-  if (last_insn)
-    while (current_insn != last_insn)
-      {
-       /* Exclude anything set in this insn.  */
-       mark_set_resources (PATTERN (current_insn), &used, 0,
-                           MARK_SRC_DEST_CALL);
-       current_insn = next_nonnote_insn (current_insn);
-      }
-
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      int regno;
-      int success;
-
-#ifdef REG_ALLOC_ORDER
-      regno = reg_alloc_order [i];
-#else
-      regno = i;
-#endif
-
-      /* Don't allocate fixed registers.  */
-      if (fixed_regs[regno])
-       continue;
-      /* Make sure the register is of the right class.  */
-      if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno))
-       continue;
-      /* And can support the mode we need.  */
-      if (! HARD_REGNO_MODE_OK (regno, mode))
-       continue;
-      /* And that we don't create an extra save/restore.  */
-      if (! call_used_regs[regno] && ! regs_ever_live[regno])
-       continue;
-      /* And we don't clobber traceback for noreturn functions.  */
-      if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
-         && (! reload_completed || frame_pointer_needed))
-       continue;
-
-      success = 1;
-      for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
-       {
-         if (TEST_HARD_REG_BIT (*reg_set, regno + j)
-             || TEST_HARD_REG_BIT (used.regs, regno + j))
-           {
-             success = 0;
-             break;
-           }
-       }
-      if (success)
-       {
-         for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
-           {
-             SET_HARD_REG_BIT (*reg_set, regno + j);
-           }
-         return gen_rtx_REG (mode, regno);
-       }
-    }
-  return NULL_RTX;
-}
-
-/* Return true if REG is dead at CURRENT_INSN.  */
-
-int
-reg_dead_p (current_insn, reg)
-     rtx current_insn, reg;
-{
-  struct resources used;
-  int regno, j;
-
-  mark_target_live_regs (get_insns (), current_insn, &used);
-  
-  regno = REGNO (reg);
-  for (j = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1; j >= 0; j--)
-    {
-      if (TEST_HARD_REG_BIT (used.regs, regno + j))
-       return 0;
-    }
-
-  return 1;
-}
index 718ec65..4f01731 100644 (file)
@@ -50,6 +50,3 @@ extern void incr_ticks_for_insn               PARAMS ((rtx));
 extern void mark_end_of_function_resources PARAMS ((rtx, int));
 extern void init_resource_info         PARAMS ((rtx));
 extern void free_resource_info         PARAMS ((void));
-extern rtx find_free_register          PARAMS ((rtx, rtx, const char *, int,
-                                              HARD_REG_SET *));
-extern int reg_dead_p                  PARAMS ((rtx, rtx));
index 30ef18a..1fc72f1 100644 (file)
@@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA.  */
 #include "insn-attr.h"
 #include "insn-codes.h"
 #include "insn-config.h"
+#include "hard-reg-set.h"
 #include "recog.h"
 #include "defaults.h"
 #include "output.h"
@@ -54,7 +55,6 @@ Boston, MA 02111-1307, USA.  */
 #include "function.h"
 #include "toplev.h"
 #include "expr.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "intl.h"
 #include "ggc.h"