OSDN Git Service

* recog.c (peep2_do_rebuild_jump_labels, peep2_do_cleanup_cfg): New
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 29 Jun 2010 22:29:30 +0000 (22:29 +0000)
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 29 Jun 2010 22:29:30 +0000 (22:29 +0000)
static variables.
(peep2_buf_position): New static function.
(peep2_regno_dead_p, peep2_reg_dead_p, peep2_find_free_register,
peephole2_optimize): Use it.
(peep2_attempt, peep2_update_life): New static functions, broken out
of peephole2_optimize.
(peep2_fill_buffer): New static function.
(peephole2_optimize): Change the main loop to try to fill the buffer
with the maximum number of insns before matching them against
peepholes.  Use a forward scan.  Remove special case for targets with
conditional execution.
* genrecog.c (change_state): Delete dead code.
* config/i386/i386.md (peephole2 for arithmetic ops with memory):
Rewrite so as not to expect the second insn to have had a peephole
applied yet.

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

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/genrecog.c
gcc/recog.c

index ee6c6fa..42e0295 100644 (file)
@@ -1,3 +1,22 @@
+2010-06-30  Bernd Schmidt  <bernds@codesourcery.com>
+
+       * recog.c (peep2_do_rebuild_jump_labels, peep2_do_cleanup_cfg): New
+       static variables.
+       (peep2_buf_position): New static function.
+       (peep2_regno_dead_p, peep2_reg_dead_p, peep2_find_free_register,
+       peephole2_optimize): Use it.
+       (peep2_attempt, peep2_update_life): New static functions, broken out
+       of peephole2_optimize.
+       (peep2_fill_buffer): New static function.
+       (peephole2_optimize): Change the main loop to try to fill the buffer
+       with the maximum number of insns before matching them against
+       peepholes.  Use a forward scan.  Remove special case for targets with
+       conditional execution.
+       * genrecog.c (change_state): Delete dead code.
+       * config/i386/i386.md (peephole2 for arithmetic ops with memory):
+       Rewrite so as not to expect the second insn to have had a peephole
+       applied yet.
+
 2010-06-29  Nathan Froyd  <froydnj@codesourcery.com>
 
        * genhooks.c (emit_findices): Cast field precision to int.
index 93843b3..7003f52 100644 (file)
 ;;  leal    (%edx,%eax,4), %eax
 
 (define_peephole2
-  [(parallel [(set (match_operand 0 "register_operand" "")
+  [(match_scratch:SI 5 "r")
+   (parallel [(set (match_operand 0 "register_operand" "")
                   (ashift (match_operand 1 "register_operand" "")
                           (match_operand 2 "const_int_operand" "")))
               (clobber (reg:CC FLAGS_REG))])
-   (set (match_operand 3 "register_operand")
-        (match_operand 4 "x86_64_general_operand" ""))
-   (parallel [(set (match_operand 5 "register_operand" "")
-                  (plus (match_operand 6 "register_operand" "")
-                        (match_operand 7 "register_operand" "")))
+   (parallel [(set (match_operand 3 "register_operand" "")
+                  (plus (match_dup 0)
+                        (match_operand 4 "x86_64_general_operand" "")))
                   (clobber (reg:CC FLAGS_REG))])]
   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
    /* Validate MODE for lea.  */
        || GET_MODE (operands[0]) == SImode
        || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
    /* We reorder load and the shift.  */
-   && !rtx_equal_p (operands[1], operands[3])
-   && !reg_overlap_mentioned_p (operands[0], operands[4])
-   /* Last PLUS must consist of operand 0 and 3.  */
-   && !rtx_equal_p (operands[0], operands[3])
-   && (rtx_equal_p (operands[3], operands[6])
-       || rtx_equal_p (operands[3], operands[7]))
-   && (rtx_equal_p (operands[0], operands[6])
-       || rtx_equal_p (operands[0], operands[7]))
-   /* The intermediate operand 0 must die or be same as output.  */
-   && (rtx_equal_p (operands[0], operands[5])
-       || peep2_reg_dead_p (3, operands[0]))"
-  [(set (match_dup 3) (match_dup 4))
+   && !reg_overlap_mentioned_p (operands[0], operands[4])"
+  [(set (match_dup 5) (match_dup 4))
    (set (match_dup 0) (match_dup 1))]
 {
-  enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
+  enum machine_mode mode = GET_MODE (operands[1]) == DImode ? DImode : SImode;
   int scale = 1 << INTVAL (operands[2]);
   rtx index = gen_lowpart (Pmode, operands[1]);
-  rtx base = gen_lowpart (Pmode, operands[3]);
-  rtx dest = gen_lowpart (mode, operands[5]);
+  rtx base = gen_lowpart (Pmode, operands[5]);
+  rtx dest = gen_lowpart (mode, operands[3]);
 
   operands[1] = gen_rtx_PLUS (Pmode, base,
                              gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
   if (mode != Pmode)
     operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
+  operands[5] = base;
   operands[0] = dest;
 })
 \f
index 26c2a95..bc7767f 100644 (file)
@@ -1761,20 +1761,11 @@ change_state (const char *oldpos, const char *newpos, const char *indent)
   int odepth = strlen (oldpos);
   int ndepth = strlen (newpos);
   int depth;
-  int old_has_insn, new_has_insn;
 
   /* Pop up as many levels as necessary.  */
   for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth)
     continue;
 
-  /* Hunt for the last [A-Z] in both strings.  */
-  for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
-    if (ISUPPER (oldpos[old_has_insn]))
-      break;
-  for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
-    if (ISUPPER (newpos[new_has_insn]))
-      break;
-
   /* Go down to desired level.  */
   while (depth < ndepth)
     {
index 43f901f..eb456c0 100644 (file)
@@ -2958,6 +2958,10 @@ struct peep2_insn_data
 
 static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
 static int peep2_current;
+
+static bool peep2_do_rebuild_jump_labels;
+static bool peep2_do_cleanup_cfg;
+
 /* The number of instructions available to match a peep2.  */
 int peep2_current_count;
 
@@ -2966,6 +2970,16 @@ int peep2_current_count;
    DF_LIVE_OUT for the block.  */
 #define PEEP2_EOB      pc_rtx
 
+/* Wrap N to fit into the peep2_insn_data buffer.  */
+
+static int
+peep2_buf_position (int n)
+{
+  if (n >= MAX_INSNS_PER_PEEP2 + 1)
+    n -= MAX_INSNS_PER_PEEP2 + 1;
+  return n;
+}
+
 /* 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.  */
@@ -2975,9 +2989,7 @@ peep2_next_insn (int n)
 {
   gcc_assert (n <= peep2_current_count);
 
-  n += peep2_current;
-  if (n >= MAX_INSNS_PER_PEEP2 + 1)
-    n -= MAX_INSNS_PER_PEEP2 + 1;
+  n = peep2_buf_position (peep2_current + n);
 
   return peep2_insn_data[n].insn;
 }
@@ -2990,9 +3002,7 @@ peep2_regno_dead_p (int ofs, int regno)
 {
   gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
 
-  ofs += peep2_current;
-  if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
-    ofs -= MAX_INSNS_PER_PEEP2 + 1;
+  ofs = peep2_buf_position (peep2_current + ofs);
 
   gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
 
@@ -3008,9 +3018,7 @@ peep2_reg_dead_p (int ofs, rtx reg)
 
   gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
 
-  ofs += peep2_current;
-  if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
-    ofs -= MAX_INSNS_PER_PEEP2 + 1;
+  ofs = peep2_buf_position (peep2_current + ofs);
 
   gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
 
@@ -3045,12 +3053,8 @@ peep2_find_free_register (int from, int to, const char *class_str,
   gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
   gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
 
-  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;
+  from = peep2_buf_position (peep2_current + from);
+  to = peep2_buf_position (peep2_current + to);
 
   gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
   REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
@@ -3059,8 +3063,7 @@ peep2_find_free_register (int from, int to, const char *class_str,
     {
       HARD_REG_SET this_live;
 
-      if (++from >= MAX_INSNS_PER_PEEP2 + 1)
-       from = 0;
+      from = peep2_buf_position (from + 1);
       gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
       REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
       IOR_HARD_REG_SET (live, this_live);
@@ -3153,19 +3156,234 @@ peep2_reinit_state (regset live)
   COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
 }
 
+/* While scanning basic block BB, we found a match of length MATCH_LEN,
+   starting at INSN.  Perform the replacement, removing the old insns and
+   replacing them with ATTEMPT.  Returns the last insn emitted.  */
+
+static rtx
+peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt)
+{
+  int i;
+  rtx last, note, before_try, x;
+  bool was_call = false;
+
+  /* If we are splitting a CALL_INSN, look for the CALL_INSN
+     in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
+     cfg-related call notes.  */
+  for (i = 0; i <= match_len; ++i)
+    {
+      int j;
+      rtx old_insn, new_insn, note;
+
+      j = peep2_buf_position (peep2_current + i);
+      old_insn = peep2_insn_data[j].insn;
+      if (!CALL_P (old_insn))
+       continue;
+      was_call = true;
+
+      new_insn = attempt;
+      while (new_insn != NULL_RTX)
+       {
+         if (CALL_P (new_insn))
+           break;
+         new_insn = NEXT_INSN (new_insn);
+       }
+
+      gcc_assert (new_insn != NULL_RTX);
+
+      CALL_INSN_FUNCTION_USAGE (new_insn)
+       = CALL_INSN_FUNCTION_USAGE (old_insn);
+
+      for (note = REG_NOTES (old_insn);
+          note;
+          note = XEXP (note, 1))
+       switch (REG_NOTE_KIND (note))
+         {
+         case REG_NORETURN:
+         case REG_SETJMP:
+           add_reg_note (new_insn, REG_NOTE_KIND (note),
+                         XEXP (note, 0));
+           break;
+         default:
+           /* Discard all other reg notes.  */
+           break;
+         }
+
+      /* Croak if there is another call in the sequence.  */
+      while (++i <= match_len)
+       {
+         j = peep2_buf_position (peep2_current + i);
+         old_insn = peep2_insn_data[j].insn;
+         gcc_assert (!CALL_P (old_insn));
+       }
+      break;
+    }
+
+  i = peep2_buf_position (peep2_current + match_len);
+
+  note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX);
+
+  /* Replace the old sequence with the new.  */
+  last = emit_insn_after_setloc (attempt,
+                                peep2_insn_data[i].insn,
+                                INSN_LOCATOR (peep2_insn_data[i].insn));
+  before_try = PREV_INSN (insn);
+  delete_insn_chain (insn, peep2_insn_data[i].insn, false);
+
+  /* Re-insert the EH_REGION notes.  */
+  if (note || (was_call && nonlocal_goto_handler_labels))
+    {
+      edge eh_edge;
+      edge_iterator ei;
+
+      FOR_EACH_EDGE (eh_edge, ei, bb->succs)
+       if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
+         break;
+
+      if (note)
+       copy_reg_eh_region_note_backward (note, last, before_try);
+
+      if (eh_edge)
+       for (x = last; x != before_try; x = PREV_INSN (x))
+         if (x != BB_END (bb)
+             && (can_throw_internal (x)
+                 || can_nonlocal_goto (x)))
+           {
+             edge nfte, nehe;
+             int flags;
+
+             nfte = split_block (bb, x);
+             flags = (eh_edge->flags
+                      & (EDGE_EH | EDGE_ABNORMAL));
+             if (CALL_P (x))
+               flags |= EDGE_ABNORMAL_CALL;
+             nehe = make_edge (nfte->src, eh_edge->dest,
+                               flags);
+
+             nehe->probability = eh_edge->probability;
+             nfte->probability
+               = REG_BR_PROB_BASE - nehe->probability;
+
+             peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
+             bb = nfte->src;
+             eh_edge = nehe;
+           }
+
+      /* Converting possibly trapping insn to non-trapping is
+        possible.  Zap dummy outgoing edges.  */
+      peep2_do_cleanup_cfg |= purge_dead_edges (bb);
+    }
+
+  /* If we generated a jump instruction, it won't have
+     JUMP_LABEL set.  Recompute after we're done.  */
+  for (x = last; x != before_try; x = PREV_INSN (x))
+    if (JUMP_P (x))
+      {
+       peep2_do_rebuild_jump_labels = true;
+       break;
+      }
+
+  return last;
+}
+
+/* After performing a replacement in basic block BB, fix up the life
+   information in our buffer.  LAST is the last of the insns that we
+   emitted as a replacement.  PREV is the insn before the start of
+   the replacement.  MATCH_LEN is the number of instructions that were
+   matched, and which now need to be replaced in the buffer.  */
+
+static void
+peep2_update_life (basic_block bb, int match_len, rtx last, rtx prev)
+{
+  int i = peep2_buf_position (peep2_current + match_len + 1);
+  rtx x;
+  regset_head live;
+
+  INIT_REG_SET (&live);
+  COPY_REG_SET (&live, peep2_insn_data[i].live_before);
+
+  gcc_assert (peep2_current_count >= match_len + 1);
+  peep2_current_count -= match_len + 1;
+
+  x = last;
+  do
+    {
+      if (INSN_P (x))
+       {
+         df_insn_rescan (x);
+         if (peep2_current_count < MAX_INSNS_PER_PEEP2)
+           {
+             peep2_current_count++;
+             if (--i < 0)
+               i = MAX_INSNS_PER_PEEP2;
+             peep2_insn_data[i].insn = x;
+             df_simulate_one_insn_backwards (bb, x, &live);
+             COPY_REG_SET (peep2_insn_data[i].live_before, &live);
+           }
+       }
+      x = PREV_INSN (x);
+    }
+  while (x != prev);
+  CLEAR_REG_SET (&live);
+
+  peep2_current = i;
+}
+
+/* Add INSN, which is in BB, at the end of the peep2 insn buffer if possible.
+   Return true if we added it, false otherwise.  The caller will try to match
+   peepholes against the buffer if we return false; otherwise it will try to
+   add more instructions to the buffer.  */
+
+static bool
+peep2_fill_buffer (basic_block bb, rtx insn, regset live)
+{
+  int pos;
+
+  /* Once we have filled the maximum number of insns the buffer can hold,
+     allow the caller to match the insns against peepholes.  We wait until
+     the buffer is full in case the target has similar peepholes of different
+     length; we always want to match the longest if possible.  */
+  if (peep2_current_count == MAX_INSNS_PER_PEEP2)
+    return false;
+
+  /* If an insn has RTX_FRAME_RELATED_P set, peephole substitution would lose
+     the REG_FRAME_RELATED_EXPR that is attached.  */
+  if (RTX_FRAME_RELATED_P (insn))
+    {
+      /* Let the buffer drain first.  */
+      if (peep2_current_count > 0)
+       return false;
+      /* Step over the insn then return true without adding the insn
+        to the buffer; this will cause us to process the next
+        insn.  */
+      df_simulate_one_insn_forwards (bb, insn, live);
+      return true;
+    }
+
+  pos = peep2_buf_position (peep2_current + peep2_current_count);
+  peep2_insn_data[pos].insn = insn;
+  COPY_REG_SET (peep2_insn_data[pos].live_before, live);
+  peep2_current_count++;
+
+  df_simulate_one_insn_forwards (bb, insn, live);
+  return true;
+}
+
 /* Perform the peephole2 optimization pass.  */
 
 static void
 peephole2_optimize (void)
 {
-  rtx insn, prev;
+  rtx insn;
   bitmap live;
   int i;
   basic_block bb;
-  bool do_cleanup_cfg = false;
-  bool do_rebuild_jump_labels = false;
+
+  peep2_do_cleanup_cfg = false;
+  peep2_do_rebuild_jump_labels = false;
 
   df_set_flags (DF_LR_RUN_DCE);
+  df_note_add_problem ();
   df_analyze ();
 
   /* Initialize the regsets we're going to use.  */
@@ -3175,214 +3393,59 @@ peephole2_optimize (void)
 
   FOR_EACH_BB_REVERSE (bb)
     {
+      bool past_end = false;
+      int pos;
+
       rtl_profile_for_bb (bb);
 
       /* Start up propagation.  */
-      bitmap_copy (live, DF_LR_OUT (bb));
-      df_simulate_initialize_backwards (bb, live);
+      bitmap_copy (live, DF_LR_IN (bb));
+      df_simulate_initialize_forwards (bb, live);
       peep2_reinit_state (live);
 
-      for (insn = BB_END (bb); ; insn = prev)
+      insn = BB_HEAD (bb);
+      for (;;)
        {
-         prev = PREV_INSN (insn);
-         if (NONDEBUG_INSN_P (insn))
-           {
-             rtx attempt, before_try, x;
-             int match_len;
-             rtx note;
-             bool was_call = false;
-
-             /* 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;
-             df_simulate_one_insn_backwards (bb, insn, live);
-             COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
-
-             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_reinit_state (live);
-                 attempt = NULL;
-               }
-             else
-               /* Match the peephole.  */
-               attempt = peephole2_insns (PATTERN (insn), insn, &match_len);
+         rtx attempt, head;
+         int match_len;
 
-             if (attempt != NULL)
-               {
-                 /* If we are splitting a CALL_INSN, look for the CALL_INSN
-                    in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
-                    cfg-related call notes.  */
-                 for (i = 0; i <= match_len; ++i)
-                   {
-                     int j;
-                     rtx old_insn, new_insn, note;
-
-                     j = i + peep2_current;
-                     if (j >= MAX_INSNS_PER_PEEP2 + 1)
-                       j -= MAX_INSNS_PER_PEEP2 + 1;
-                     old_insn = peep2_insn_data[j].insn;
-                     if (!CALL_P (old_insn))
-                       continue;
-                     was_call = true;
-
-                     new_insn = attempt;
-                     while (new_insn != NULL_RTX)
-                       {
-                         if (CALL_P (new_insn))
-                           break;
-                         new_insn = NEXT_INSN (new_insn);
-                       }
-
-                     gcc_assert (new_insn != NULL_RTX);
-
-                     CALL_INSN_FUNCTION_USAGE (new_insn)
-                       = CALL_INSN_FUNCTION_USAGE (old_insn);
-
-                     for (note = REG_NOTES (old_insn);
-                          note;
-                          note = XEXP (note, 1))
-                       switch (REG_NOTE_KIND (note))
-                         {
-                         case REG_NORETURN:
-                         case REG_SETJMP:
-                           add_reg_note (new_insn, REG_NOTE_KIND (note),
-                                         XEXP (note, 0));
-                           break;
-                         default:
-                           /* Discard all other reg notes.  */
-                           break;
-                         }
-
-                     /* Croak if there is another call in the sequence.  */
-                     while (++i <= match_len)
-                       {
-                         j = i + peep2_current;
-                         if (j >= MAX_INSNS_PER_PEEP2 + 1)
-                           j -= MAX_INSNS_PER_PEEP2 + 1;
-                         old_insn = peep2_insn_data[j].insn;
-                         gcc_assert (!CALL_P (old_insn));
-                       }
-                     break;
-                   }
-
-                 i = match_len + peep2_current;
-                 if (i >= MAX_INSNS_PER_PEEP2 + 1)
-                   i -= MAX_INSNS_PER_PEEP2 + 1;
-
-                 note = find_reg_note (peep2_insn_data[i].insn,
-                                       REG_EH_REGION, NULL_RTX);
-
-                 /* Replace the old sequence with the new.  */
-                 attempt = emit_insn_after_setloc (attempt,
-                                                   peep2_insn_data[i].insn,
-                                      INSN_LOCATOR (peep2_insn_data[i].insn));
-                 before_try = PREV_INSN (insn);
-                 delete_insn_chain (insn, peep2_insn_data[i].insn, false);
-
-                 /* Re-insert the EH_REGION notes.  */
-                 if (note || (was_call && nonlocal_goto_handler_labels))
-                   {
-                     edge eh_edge;
-                     edge_iterator ei;
-
-                     FOR_EACH_EDGE (eh_edge, ei, bb->succs)
-                       if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
-                         break;
+         if (!past_end && !NONDEBUG_INSN_P (insn))
+           {
+           next_insn:
+             insn = NEXT_INSN (insn);
+             if (insn == NEXT_INSN (BB_END (bb)))
+               past_end = true;
+             continue;
+           }
+         if (!past_end && peep2_fill_buffer (bb, insn, live))
+           goto next_insn;
 
-                     if (note)
-                       copy_reg_eh_region_note_backward (note, attempt,
-                                                         before_try);
-
-                     if (eh_edge)
-                       for (x = attempt ; x != before_try ; x = PREV_INSN (x))
-                         if (x != BB_END (bb)
-                             && (can_throw_internal (x)
-                                 || can_nonlocal_goto (x)))
-                           {
-                             edge nfte, nehe;
-                             int flags;
-
-                             nfte = split_block (bb, x);
-                             flags = (eh_edge->flags
-                                      & (EDGE_EH | EDGE_ABNORMAL));
-                             if (CALL_P (x))
-                               flags |= EDGE_ABNORMAL_CALL;
-                             nehe = make_edge (nfte->src, eh_edge->dest,
-                                               flags);
-
-                             nehe->probability = eh_edge->probability;
-                             nfte->probability
-                               = REG_BR_PROB_BASE - nehe->probability;
-
-                             do_cleanup_cfg |= purge_dead_edges (nfte->dest);
-                             bb = nfte->src;
-                             eh_edge = nehe;
-                           }
-
-                     /* Converting possibly trapping insn to non-trapping is
-                        possible.  Zap dummy outgoing edges.  */
-                     do_cleanup_cfg |= purge_dead_edges (bb);
-                   }
+         /* If we did not fill an empty buffer, it signals the end of the
+            block.  */
+         if (peep2_current_count == 0)
+           break;
 
-                 if (targetm.have_conditional_execution ())
-                   {
-                     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.  */
-                     if (++i >= MAX_INSNS_PER_PEEP2 + 1)
-                       i = 0;
-                     bitmap_copy (live, peep2_insn_data[i].live_before);
-
-                     /* Update life information for the new sequence.  */
-                     x = attempt;
-                     do
-                       {
-                         if (INSN_P (x))
-                           {
-                             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;
-                             df_insn_rescan (x);
-                             df_simulate_one_insn_backwards (bb, x, live);
-                             bitmap_copy (peep2_insn_data[i].live_before,
-                                          live);
-                           }
-                         x = PREV_INSN (x);
-                       }
-                     while (x != prev);
+         /* The buffer filled to the current maximum, so try to match.  */
 
-                     peep2_current = i;
-                   }
+         pos = peep2_buf_position (peep2_current + peep2_current_count);
+         peep2_insn_data[pos].insn = PEEP2_EOB;
+         COPY_REG_SET (peep2_insn_data[pos].live_before, live);
 
-                 /* If we generated a jump instruction, it won't have
-                    JUMP_LABEL set.  Recompute after we're done.  */
-                 for (x = attempt; x != before_try; x = PREV_INSN (x))
-                   if (JUMP_P (x))
-                     {
-                       do_rebuild_jump_labels = true;
-                       break;
-                     }
-               }
+         /* Match the peephole.  */
+         head = peep2_insn_data[peep2_current].insn;
+         attempt = peephole2_insns (PATTERN (head), head, &match_len);
+         if (attempt != NULL)
+           {
+             rtx last;
+             last = peep2_attempt (bb, head, match_len, attempt);
+             peep2_update_life (bb, match_len, last, PREV_INSN (attempt));
+           }
+         else
+           {
+             /* If no match, advance the buffer by one insn.  */
+             peep2_current = peep2_buf_position (peep2_current + 1);
+             peep2_current_count--;
            }
-
-         if (insn == BB_HEAD (bb))
-           break;
        }
     }
 
@@ -3390,7 +3453,7 @@ peephole2_optimize (void)
   for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
     BITMAP_FREE (peep2_insn_data[i].live_before);
   BITMAP_FREE (live);
-  if (do_rebuild_jump_labels)
+  if (peep2_do_rebuild_jump_labels)
     rebuild_jump_labels (get_insns ());
 }
 #endif /* HAVE_peephole2 */