large peephole2 speedup.

Zack Weinberg zack@wolery.cumb.org
Sun Apr 9 10:25:00 GMT 2000


This patch changes the peephole2 optimizer so that it uses flow.c
routines to determine live registers, rather than resource.c.  This is
good for an enormous speedup on some test code: for example,
'test-ildoubl.c' from glibc:

Before:
time in parse: 2.000000 (3%)
time in jump: 0.860000 (1%)
time in cse: 1.440000 (2%)
time in gcse: 1.050000 (1%)
time in loop: 0.240000 (0%)
time in cse2: 0.940000 (1%)
time in flow: 0.530000 (0%)
time in combine: 0.710000 (1%)
time in regmove: 0.330000 (0%)
time in local-alloc: 0.540000 (0%)
time in global-alloc: 3.320000 (6%)
time in flow2: 0.690000 (1%)
time in peephole2: 32.500000 (-19%)
time in sched2: 5.380000 (9%)
time in shorten-branch: 0.380000 (0%)
time in stack-reg: 0.370000 (0%)
time in final: 0.620000 (1%)
0:55.78 - 54.51u, 0.20s, 98% - 1034/11649

After:
time in parse: 2.050000 (9%)
time in jump: 0.850000 (3%)
time in cse: 1.420000 (6%)
time in gcse: 1.030000 (4%)
time in loop: 0.220000 (0%)
time in cse2: 0.920000 (4%)
time in flow: 0.540000 (2%)
time in combine: 0.730000 (3%)
time in regmove: 0.400000 (1%)
time in local-alloc: 0.530000 (2%)
time in global-alloc: 3.260000 (14%)
time in flow2: 0.650000 (2%)
time in peephole2: 0.500000 (2%)
time in sched2: 5.380000 (23%)
time in shorten-branch: 0.310000 (1%)
time in stack-reg: 0.350000 (1%)
time in final: 0.670000 (2%)
0:22.83 - 22.38u, 0.27s, 99% - 511/10831

The code generated is almost identical, differing only in choice of
scratch registers - it seems to like to pick eax, when the old code
would pick edx.

I have bootstrapped this change, built a cross-compiler from x86 to
alpha (alpha is the only other target that uses peephole2), and
compiled glibc successfully.  The patch is smaller than it looks; the
biggest hunk is splitting up propagate_block so its innards can be
made externally visible.  Note that find_free_register no longer has
the ability to determine if a register remains available till later;
no existing peephole needed that.

I note that practically nothing uses resource.c: only reorg.c and one
place in regrename.c.

zw

	* flow.c (propagate_block): Split out the per-insn logic to...
	(propagate_block_1): ...here.
	(calc_live_before): New function.
	(find_free_register): Move here from resource.c.  Just find a
	suitable register not set in REGSET.
	* resource.c (find_free_register): Moved to resource.c.
	(reg_dead_p): Delete function.
	(mark_target_live_regs): Break out tails into
	mark_target_live_regs_hashed and mark_target_live_regs_slow.

	* genemit.c: peephole2 generators take an rtx * and a regset.
	To allocate a scratch, just call find_free_register on the
	regset.  Include basic-block.h in generated file.
	* genrecog.c: peephole2 generators take an rtx * and a regset.
	Include basic-block.h in generated file.
	* recog.c (peephole2_optimize): In each basic block, start
	with bb->global_live_at_end, and use calc_live_before to
	determine live regs at each insn in the block.  Don't alloc or
	free resource info.  Recalc life info only if we changed
	something.
	* resource.h, basic-block.h, recog.h: Update prototypes.

	* i386.md: Replace all uses of reg_dead_p with direct tests of
	the reg live list.

===================================================================
Index: basic-block.h
--- basic-block.h	2000/04/09 01:16:44	1.61
+++ basic-block.h	2000/04/09 17:14:32
@@ -452,6 +452,8 @@ extern void estimate_probability        
 
 /* In flow.c */
 extern void reorder_basic_blocks	PARAMS ((void));
+extern void calc_live_before		PARAMS ((rtx, regset, basic_block));
+extern rtx find_free_register		PARAMS ((const char *, int, regset));
 extern void dump_bb			PARAMS ((basic_block, FILE *));
 extern void debug_bb			PARAMS ((basic_block));
 extern void debug_bb_n			PARAMS ((int));
===================================================================
Index: flow.c
--- flow.c	2000/04/09 01:16:44	1.250
+++ flow.c	2000/04/09 17:14:35
@@ -330,6 +330,8 @@ static void propagate_block_delete_insn 
 static rtx propagate_block_delete_libcall PARAMS ((basic_block, rtx, rtx));
 static void propagate_block		PARAMS ((basic_block, regset,
 						 regset, int));
+static rtx propagate_block_1		PARAMS ((struct propagate_block_info *,
+						 rtx, int));
 static int insn_dead_p			PARAMS ((struct propagate_block_info *,
 						 rtx, int, rtx));
 static int libcall_dead_p		PARAMS ((struct propagate_block_info *,
@@ -3313,8 +3315,6 @@ propagate_block (bb, live, local_set, fl
 {
   struct propagate_block_info pbi;
   rtx insn, prev;
-  regset_head tmp_head;
-  regset tmp;
   
   pbi.bb = bb;
   pbi.reg_live = live;
@@ -3328,8 +3328,6 @@ propagate_block (bb, live, local_set, fl
   else
     pbi.reg_next_use = NULL;
 
-  tmp = INITIALIZE_REG_SET (tmp_head);
-
   if (flags & PROP_REG_INFO)
     {
       register int i;
@@ -3348,250 +3346,260 @@ propagate_block (bb, live, local_set, fl
     {
       prev = PREV_INSN (insn);
 
-      if (GET_CODE (insn) == NOTE)
+      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+	prev = propagate_block_1 (&pbi, insn, flags);
+      else
 	{
+	  prev = PREV_INSN (insn);
+	  
 	  /* If this is a call to `setjmp' et al,
 	     warn if any non-volatile datum is live.  */
-
-	  if ((flags & PROP_REG_INFO)
+	  if (GET_CODE (insn) == NOTE
+	      && (flags & PROP_REG_INFO)
 	      && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
 	    IOR_REG_SET (regs_live_at_setjmp, pbi.reg_live);
 	}
 
-      /* Update the life-status of regs for this insn.
-	 First DEAD gets which regs are set in this insn
-	 then LIVE gets which regs are used in this insn.
-	 Then the regs live before the insn
-	 are those live after, with DEAD regs turned off,
-	 and then LIVE regs turned on.  */
+      if (insn == bb->head)
+	break;
+    }
 
-      else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-	{
-	  register int i;
-	  rtx note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
-	  int insn_is_dead = 0;
-	  int libcall_is_dead = 0;
-
-	  if (flags & PROP_SCAN_DEAD_CODE)
-	    {
-	      insn_is_dead = insn_dead_p (&pbi, PATTERN (insn), 0,
-					  REG_NOTES (insn));
-	      libcall_is_dead = (insn_is_dead && note != 0
-	                         && libcall_dead_p (&pbi, PATTERN (insn),
-						    note, insn));
-	    }
-
-	  /* We almost certainly don't want to delete prologue or epilogue
-	     instructions.  Warn about probable compiler losage.  */
-	  if (insn_is_dead
-	      && reload_completed
-	      && (((HAVE_epilogue || HAVE_prologue)
-		   && prologue_epilogue_contains (insn))
-		  || (HAVE_sibcall_epilogue
-		      && sibcall_epilogue_contains (insn))))
-	    {
-	      if (flags & PROP_KILL_DEAD_CODE)
-	        { 
-	      	  warning ("ICE: would have deleted prologue/epilogue insn");
-	      	  if (!inhibit_warnings)
-	  	    debug_rtx (insn);
-	        }
-	      libcall_is_dead = insn_is_dead = 0;
-	    }
-
-	  /* If an instruction consists of just dead store(s) on final pass,
-	     delete it.  */
-	  if ((flags & PROP_KILL_DEAD_CODE) && insn_is_dead)
-	    {
-	      if (libcall_is_dead)
-		{
-		  prev = propagate_block_delete_libcall (bb, insn, note);
-		  insn = NEXT_INSN (prev);
-		}
-	      else
-		propagate_block_delete_insn (bb, insn);
+  free_EXPR_LIST_list (&pbi.mem_set_list);
+  if (pbi.reg_next_use)
+    free (pbi.reg_next_use);
+}
 
-	      /* CC0 is now known to be dead.  Either this insn used it,
-		 in which case it doesn't anymore, or clobbered it,
-		 so the next insn can't use it.  */
-	      pbi.cc0_live = 0;
 
-	      goto flushed;
-	    }
+/* Update the life-status of regs for one insn.  First DEAD gets which
+   regs are set in this insn, then LIVE gets which regs are used in
+   this insn.  Then the regs live before the insn are those live
+   after, with DEAD regs turned off, and LIVE regs turned on.  */
 
-	  /* See if this is an increment or decrement that can be
-	     merged into a following memory address.  */
+static rtx
+propagate_block_1 (pbi, insn, flags)
+     struct propagate_block_info *pbi;
+     rtx insn;
+     int flags;
+{
+  int i;
+  rtx note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
+  int insn_is_dead = 0;
+  int libcall_is_dead = 0;
+  regset tmp;
+  regset_head tmp_head;
+  rtx prev = PREV_INSN (insn);
+
+  if (flags & PROP_SCAN_DEAD_CODE)
+    {
+      insn_is_dead = insn_dead_p (pbi, PATTERN (insn), 0,
+				  REG_NOTES (insn));
+      libcall_is_dead = (insn_is_dead && note != 0
+			 && libcall_dead_p (pbi, PATTERN (insn),
+					    note, insn));
+    }
+
+  /* We almost certainly don't want to delete prologue or epilogue
+     instructions.  Warn about probable compiler losage.  */
+  if (insn_is_dead
+      && reload_completed
+      && (((HAVE_epilogue || HAVE_prologue)
+	   && prologue_epilogue_contains (insn))
+	  || (HAVE_sibcall_epilogue
+	      && sibcall_epilogue_contains (insn))))
+    {
+      if (flags & PROP_KILL_DEAD_CODE)
+	{ 
+	  warning ("ICE: would have deleted prologue/epilogue insn");
+	  if (!inhibit_warnings)
+	    debug_rtx (insn);
+	}
+      libcall_is_dead = insn_is_dead = 0;
+    }
+
+  /* If an instruction consists of just dead store(s) on final pass,
+     delete it.  */
+  if ((flags & PROP_KILL_DEAD_CODE) && insn_is_dead)
+    {
+      if (libcall_is_dead)
+	prev = propagate_block_delete_libcall (pbi->bb, insn, note);
+      else
+	propagate_block_delete_insn (pbi->bb, insn);
+
+      /* CC0 is now known to be dead.  Either this insn used it,
+	 in which case it doesn't anymore, or clobbered it,
+	 so the next insn can't use it.  */
+      pbi->cc0_live = 0;
+
+      return prev;
+    }
+
+  /* See if this is an increment or decrement that can be
+     merged into a following memory address.  */
 #ifdef AUTO_INC_DEC
-	  {
-	    register rtx x = single_set (insn);
+  {
+    register rtx x = single_set (insn);
 
-	    /* Does this instruction increment or decrement a register?  */
-	    if (!reload_completed
-		&& (flags & PROP_AUTOINC)
-		&& x != 0
-		&& GET_CODE (SET_DEST (x)) == REG
-		&& (GET_CODE (SET_SRC (x)) == PLUS
-		    || GET_CODE (SET_SRC (x)) == MINUS)
-		&& XEXP (SET_SRC (x), 0) == SET_DEST (x)
-		&& GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
-		/* Ok, look for a following memory ref we can combine with.
-		   If one is found, change the memory ref to a PRE_INC
-		   or PRE_DEC, cancel this insn, and return 1.
-		   Return 0 if nothing has been done.  */
-		&& try_pre_increment_1 (&pbi, insn))
-	      goto flushed;
-	  }
+    /* Does this instruction increment or decrement a register?  */
+    if (!reload_completed
+	&& (flags & PROP_AUTOINC)
+	&& x != 0
+	&& GET_CODE (SET_DEST (x)) == REG
+	&& (GET_CODE (SET_SRC (x)) == PLUS
+	    || GET_CODE (SET_SRC (x)) == MINUS)
+	&& XEXP (SET_SRC (x), 0) == SET_DEST (x)
+	&& GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
+	/* Ok, look for a following memory ref we can combine with.
+	   If one is found, change the memory ref to a PRE_INC
+	   or PRE_DEC, cancel this insn, and return 1.
+	   Return 0 if nothing has been done.  */
+	&& try_pre_increment_1 (pbi, insn))
+      return prev;
+  }
 #endif /* AUTO_INC_DEC */
 
-	  CLEAR_REG_SET (tmp);
+  /* If this is not the final pass, and this insn is copying the
+     value of a library call and it's dead, don't scan the
+     insns that perform the library call, so that the call's
+     arguments are not marked live.  */
+  if (libcall_is_dead)
+    {
+      tmp = INIT_REG_SET (&tmp_head);
+
+      /* Record the death of the dest reg.  */
+      mark_set_regs (pbi, tmp, PATTERN (insn), insn);
+      AND_COMPL_REG_SET (pbi->reg_live, tmp);
 
-	  /* If this is not the final pass, and this insn is copying the
-	     value of a library call and it's dead, don't scan the
-	     insns that perform the library call, so that the call's
-	     arguments are not marked live.  */
-	  if (libcall_is_dead)
-	    {
-	      /* Record the death of the dest reg.  */
-	      mark_set_regs (&pbi, tmp, PATTERN (insn), insn);
-	      AND_COMPL_REG_SET (pbi.reg_live, tmp);
-
-	      insn = XEXP (note, 0);
-	      prev = PREV_INSN (insn);
-	    }
-	  else if (GET_CODE (PATTERN (insn)) == SET
-		   && SET_DEST (PATTERN (insn)) == stack_pointer_rtx
-		   && GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
-		   && XEXP (SET_SRC (PATTERN (insn)), 0) == stack_pointer_rtx
-		   && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
-	    /* We have an insn to pop a constant amount off the stack.
-	       (Such insns use PLUS regardless of the direction of the stack,
-	       and any insn to adjust the stack by a constant is always a pop.)
-	       These insns, if not dead stores, have no effect on life.  */
-	    ;
-	  else
-	    {
-	      /* Any regs live at the time of a call instruction
-		 must not go in a register clobbered by calls.
-		 Find all regs now live and record this for them.  */
-
-	      if (GET_CODE (insn) == CALL_INSN
-		  && (flags & PROP_REG_INFO))
-		EXECUTE_IF_SET_IN_REG_SET (pbi.reg_live, 0, i,
-					   { REG_N_CALLS_CROSSED (i)++; });
-
-	      /* Record sets.  Do this even for dead instructions,
-		 since they would have killed the values if they hadn't
-		 been deleted.  */
-	      mark_set_regs (&pbi, tmp, PATTERN (insn), insn);
-
-	      /* Each call clobbers all call-clobbered regs that are not
-		 global or fixed.  Note that the function-value reg is a
-		 call-clobbered reg, and mark_set_regs has already had
-		 a chance to handle it.  */
-	      if (GET_CODE (insn) == CALL_INSN)
-		{
-		  register int i;
-		  rtx cond;
+      insn = XEXP (note, 0);
+      prev = PREV_INSN (insn);
 
-		  cond = NULL_RTX;
-		  if (GET_CODE (PATTERN (insn)) == COND_EXEC)
-		    cond = COND_EXEC_TEST (PATTERN (insn));
-
-		  /* Non-constant calls clobber memory.  */
-		  if (! CONST_CALL_P (insn))
-		    free_EXPR_LIST_list (&pbi.mem_set_list);
-
-		  /* There may be extra registers to be clobbered.  */
-	          for (note = CALL_INSN_FUNCTION_USAGE (insn);
-		       note;
-		       note = XEXP (note, 1))
-		    if (GET_CODE (XEXP (note, 0)) == CLOBBER)
-		      mark_set_1 (&pbi, tmp, XEXP (XEXP (note, 0), 0),
-				  cond, insn);
-
-		  /* Calls change all call-used and global registers.  */
-		  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-		    if (call_used_regs[i] && ! global_regs[i]
-			&& ! fixed_regs[i])
-		      {
-			int dummy;
-		        mark_set_reg (&pbi, tmp,
-				      gen_rtx_REG (reg_raw_mode[i], i),
-				      cond, &dummy, &dummy);
-		      }
-		}
+      FREE_REG_SET (tmp);
+    }
+  else if (GET_CODE (PATTERN (insn)) == SET
+	   && SET_DEST (PATTERN (insn)) == stack_pointer_rtx
+	   && GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
+	   && XEXP (SET_SRC (PATTERN (insn)), 0) == stack_pointer_rtx
+	   && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
+    /* We have an insn to pop a constant amount off the stack.
+       (Such insns use PLUS regardless of the direction of the stack,
+       and any insn to adjust the stack by a constant is always a pop.)
+       These insns, if not dead stores, have no effect on life.  */
+    ;
+  else
+    {
+      /* Any regs live at the time of a call instruction
+	 must not go in a register clobbered by calls.
+	 Find all regs now live and record this for them.  */
+
+      if (GET_CODE (insn) == CALL_INSN
+	  && (flags & PROP_REG_INFO))
+	EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i,
+	{ REG_N_CALLS_CROSSED (i)++; });
+
+      /* Record sets.  Do this even for dead instructions,
+	 since they would have killed the values if they hadn't
+	 been deleted.  */
+      tmp = INIT_REG_SET (&tmp_head);
+      mark_set_regs (pbi, tmp, PATTERN (insn), insn);
+
+      /* Each call clobbers all call-clobbered regs that are not
+	 global or fixed.  Note that the function-value reg is a
+	 call-clobbered reg, and mark_set_regs has already had
+	 a chance to handle it.  */
+      if (GET_CODE (insn) == CALL_INSN)
+	{
+	  register int i;
+	  rtx cond;
 
-	      /* Update live for the registers killed.  */
-	      AND_COMPL_REG_SET (pbi.reg_live, tmp);
-	      CLEAR_REG_SET (tmp);
+	  cond = NULL_RTX;
+	  if (GET_CODE (PATTERN (insn)) == COND_EXEC)
+	    cond = COND_EXEC_TEST (PATTERN (insn));
+
+	  /* Non-constant calls clobber memory.  */
+	  if (! CONST_CALL_P (insn))
+	    free_EXPR_LIST_list (&pbi->mem_set_list);
+
+	  /* There may be extra registers to be clobbered.  */
+	  for (note = CALL_INSN_FUNCTION_USAGE (insn);
+	       note;
+	       note = XEXP (note, 1))
+	    if (GET_CODE (XEXP (note, 0)) == CLOBBER)
+	      mark_set_1 (pbi, tmp, XEXP (XEXP (note, 0), 0),
+			  cond, insn);
+
+	  /* Calls change all call-used and global registers.  */
+	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	    if (call_used_regs[i] && ! global_regs[i]
+		&& ! fixed_regs[i])
+	      {
+		int dummy;
+		mark_set_reg (pbi, tmp,
+			      gen_rtx_REG (reg_raw_mode[i], i),
+			      cond, &dummy, &dummy);
+	      }
+	}
 
-	      /* If an insn doesn't use CC0, it becomes dead since we 
-		 assume that every insn clobbers it.  So show it dead here;
-		 mark_used_regs will set it live if it is referenced.  */
-	      pbi.cc0_live = 0;
-
-	      /* Record uses.  */
-	      if (! insn_is_dead)
-		mark_used_regs (&pbi, tmp, PATTERN (insn), NULL_RTX, insn);
-
-	      /* Sometimes we may have inserted something before INSN
-		 (such as a move) when we make an auto-inc.  So ensure
-		 we will scan those insns.  */
+      /* Update live for the registers killed.  */
+      AND_COMPL_REG_SET (pbi->reg_live, tmp);
+      CLEAR_REG_SET (tmp);
+
+      /* If an insn doesn't use CC0, it becomes dead since we 
+	 assume that every insn clobbers it.  So show it dead here;
+	 mark_used_regs will set it live if it is referenced.  */
+      pbi->cc0_live = 0;
+
+      /* Record uses.  */
+      if (! insn_is_dead)
+	mark_used_regs (pbi, tmp, PATTERN (insn), NULL_RTX, insn);
+
+      /* Sometimes we may have inserted something before INSN
+	 (such as a move) when we make an auto-inc.  So ensure
+	 we will scan those insns.  */
 #ifdef AUTO_INC_DEC
-	      prev = PREV_INSN (insn);
+      prev = PREV_INSN (insn);
 #endif
 
-	      if (! insn_is_dead && GET_CODE (insn) == CALL_INSN)
-		{
-		  register int i;
-		  rtx note, cond;
-
-		  cond = NULL_RTX;
-		  if (GET_CODE (PATTERN (insn)) == COND_EXEC)
-		    cond = COND_EXEC_TEST (PATTERN (insn));
-
-	          for (note = CALL_INSN_FUNCTION_USAGE (insn);
-		       note;
-		       note = XEXP (note, 1))
-		    if (GET_CODE (XEXP (note, 0)) == USE)
-		      mark_used_regs (&pbi, tmp, XEXP (XEXP (note, 0), 0),
-				      cond, insn);
-
-		  /* The stack ptr is used (honorarily) by a CALL insn.  */
-		  SET_REGNO_REG_SET (tmp, STACK_POINTER_REGNUM);
-
-		  /* Calls may also reference any of the global registers,
-		     so they are made live.  */
-		  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-		    if (global_regs[i])
-		      mark_used_reg (&pbi, tmp,
-				     gen_rtx_REG (reg_raw_mode[i], i),
-				     cond, insn);
-		}
-
-	      /* Update live for the registers used.  */
-	      IOR_REG_SET (pbi.reg_live, tmp);
-	    }
+      if (! insn_is_dead && GET_CODE (insn) == CALL_INSN)
+	{
+	  register int i;
+	  rtx note, cond;
 
-	  /* On final pass, update counts of how many insns in which
-	     each reg is live.  */
-	  if (flags & PROP_REG_INFO)
-	    EXECUTE_IF_SET_IN_REG_SET (pbi.reg_live, 0, i,
-				       { REG_LIVE_LENGTH (i)++; });
-	}
-    flushed:
-      if (insn == bb->head)
-	break;
+	  cond = NULL_RTX;
+	  if (GET_CODE (PATTERN (insn)) == COND_EXEC)
+	    cond = COND_EXEC_TEST (PATTERN (insn));
+
+	  for (note = CALL_INSN_FUNCTION_USAGE (insn);
+	       note;
+	       note = XEXP (note, 1))
+	    if (GET_CODE (XEXP (note, 0)) == USE)
+	      mark_used_regs (pbi, tmp, XEXP (XEXP (note, 0), 0),
+			      cond, insn);
+
+	  /* The stack ptr is used (honorarily) by a CALL insn.  */
+	  SET_REGNO_REG_SET (tmp, STACK_POINTER_REGNUM);
+
+	  /* Calls may also reference any of the global registers,
+	     so they are made live.  */
+	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	    if (global_regs[i])
+	      mark_used_reg (pbi, tmp,
+			     gen_rtx_REG (reg_raw_mode[i], i),
+			     cond, insn);
+	}
+
+      /* Update live for the registers used.  */
+      IOR_REG_SET (pbi->reg_live, tmp);
+      FREE_REG_SET (tmp);
     }
 
-  FREE_REG_SET (tmp);
-  free_EXPR_LIST_list (&pbi.mem_set_list);
+  /* On final pass, update counts of how many insns in which
+     each reg is live.  */
+  if (flags & PROP_REG_INFO)
+    EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i,
+    { REG_LIVE_LENGTH (i)++; });
 
-  if (pbi.reg_next_use)
-    free (pbi.reg_next_use);
+  return prev;
 }
 
-
 /* Return 1 if X (the body of an insn, or part of it) is just dead stores
    (SET expressions whose destinations are registers dead after the insn).
    NEEDED is the regset that says which regs are alive after the insn.
@@ -3859,6 +3867,94 @@ regno_clobbered_at_setjmp (regno)
 	   || REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, regno))
 	  && REGNO_REG_SET_P (regs_live_at_setjmp, regno));
 }
+
+/* Given a basic block, an insn, and the set of regs live after that insn,
+   determine the regs live before that insn.  This is essentially a public
+   interface to propagate_block_1.  */
+
+void
+calc_live_before (insn, live, bb)
+     rtx insn;
+     regset live;
+     basic_block bb;
+{
+  struct propagate_block_info pbi;
+
+  pbi.bb = bb;
+  pbi.reg_live = live;
+  pbi.mem_set_list = NULL_RTX;
+  pbi.local_set = 0;
+  pbi.cc0_live = 0;
+  pbi.flags = 0;
+
+  propagate_block_1 (&pbi, insn, pbi.flags);
+}
+
+/* Try to find a hard register of mode MODE, matching the register
+   class in CLASS_STR, which is not marked as used in LIVE.
+
+   If an appropriate register is available, it will be returned and
+   the corresponding bit(s) in LIVE will be set; otherwise, NULL_RTX
+   is returned.  */
+
+rtx
+find_free_register (class_str, mode, live)
+     const char *class_str;
+     int mode;
+     regset live;
+{
+  int i, j;
+  unsigned char clet = class_str[0];
+  enum reg_class class
+    = (clet == 'r' ? GENERAL_REGS :  REG_CLASS_FROM_LETTER (clet));
+
+  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 (REGNO_REG_SET_P (live, regno + j))
+	    {
+	      success = 0;
+	      break;
+	    }
+	}
+      if (success)
+	{
+	  for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+	    SET_REGNO_REG_SET (live, regno + j);
+	  return gen_rtx_REG (mode, regno);
+	}
+    }
+  return NULL_RTX;
+}
+
 
 /* INSN references memory, possibly using autoincrement addressing modes.
    Find any entries on the mem_set_list that need to be invalidated due
===================================================================
Index: genemit.c
--- genemit.c	2000/02/26 13:50:42	1.53
+++ genemit.c	2000/04/09 17:14:35
@@ -573,11 +573,11 @@ gen_split (split)
   /* Output the prototype, function name and argument declarations.  */
   if (GET_CODE (split) == DEFINE_PEEPHOLE2)
     {
-      printf ("extern rtx gen_%s_%d PARAMS ((rtx, rtx *));\n",
+      printf ("extern rtx gen_%s_%d PARAMS ((rtx *, regset));\n",
 	      name, insn_code_number);
-      printf ("rtx\ngen_%s_%d (curr_insn, operands)\n\
-     rtx curr_insn ATTRIBUTE_UNUSED;\n\
-     rtx *operands;\n", 
+      printf ("rtx\ngen_%s_%d (operands, live)\n\
+     rtx *operands;\n\
+     regset live ATTRIBUTE_UNUSED;\n",
 	      name, insn_code_number);
     }
   else
@@ -704,35 +704,12 @@ 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++)
     {
       rtx elt = XVECEXP (split, 0, i);
       if (GET_CODE (elt) == MATCH_SCRATCH)
 	{
-	  int last_insn_nr = insn_nr;
-	  int cur_insn_nr = insn_nr;
-	  int j;
-	  for (j = i + 1; j < XVECLEN (split, 0); j++)
-	    if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP)
-	      {
-		if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0))
-		  last_insn_nr = cur_insn_nr;
-	      }
-	    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] = find_free_register (\"%s\", %smode, live)) == NULL_RTX)\n\
     return NULL;\n", 
 		  XINT (elt, 0),
 		  XSTR (elt, 1),
@@ -820,6 +797,7 @@ from the machine description file `md'. 
   printf ("#include \"recog.h\"\n");
   printf ("#include \"hard-reg-set.h\"\n");
   printf ("#include \"resource.h\"\n");
+  printf ("#include \"basic-block.h\"\n");
   printf ("#include \"reload.h\"\n\n");
   printf ("#define FAIL return (end_sequence (), _val)\n");
   printf ("#define DONE return (_val = gen_sequence (), end_sequence (), _val)\n");
===================================================================
Index: genrecog.c
--- genrecog.c	2000/04/07 07:16:59	1.77
+++ genrecog.c	2000/04/09 17:14:35
@@ -1971,7 +1971,7 @@ write_action (test, depth, uncond, succe
 	  break;
 
 	case PEEPHOLE2:
-	  printf ("%stem = gen_peephole2_%d (insn, operands);\n",
+	  printf ("%stem = gen_peephole2_%d (operands, live);\n",
 		  indent, test->u.insn.code_number);
 	  printf ("%sif (tem != 0)\n%s  goto ret1;\n", indent, indent);
 	  break;
@@ -2181,7 +2181,8 @@ write_subroutine (head, type)
   switch (type)
     {
     case RECOG:
-      printf ("%sint recog%s PARAMS ((rtx, rtx, int *));\n", s_or_e, extension);
+      printf ("%sint recog%s PARAMS ((rtx, rtx, int *));\n",
+	      s_or_e, extension);
       printf ("%sint\n\
 recog%s (x0, insn, pnum_clobbers)\n\
      register rtx x0;\n\
@@ -2196,12 +2197,14 @@ 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, rtx *, regset));\n",
+	      s_or_e, extension);
       printf ("%srtx\n\
-peephole2%s (x0, insn, _plast_insn)\n\
+peephole2%s (x0, insn, _plast_insn, live)\n\
      register rtx x0;\n\
      rtx insn ATTRIBUTE_UNUSED;\n\
-     rtx *_plast_insn ATTRIBUTE_UNUSED;\n", s_or_e, extension);
+     rtx *_plast_insn ATTRIBUTE_UNUSED;\n\
+     regset live;\n", s_or_e, extension);
       break;
     }
 
@@ -2262,6 +2265,7 @@ write_header ()
 #include \"flags.h\"\n\
 #include \"hard-reg-set.h\"\n\
 #include \"resource.h\"\n\
+#include \"basic-block.h\"\n\
 \n");
 
   puts ("\n\
@@ -2455,7 +2459,7 @@ make_insn_sequence (insn, type)
 
     case PEEPHOLE2:
       /* Define the subroutine we will call below and emit in genemit.  */
-      printf ("extern rtx gen_peephole2_%d PARAMS ((rtx, rtx *));\n",
+      printf ("extern rtx gen_peephole2_%d PARAMS ((rtx *, regset));\n",
 	      next_insn_code);
       break;
     }
===================================================================
Index: recog.c
--- recog.c	2000/03/09 16:07:33	1.57
+++ recog.c	2000/04/09 17:14:36
@@ -2714,14 +2714,10 @@ peephole2_optimize (dump_file)
   rtx insn, prev;
   int i, changed;
   sbitmap blocks;
+  regset_head live_head, tmp_head;
+  regset live = INIT_REG_SET (&live_head);
+  regset tmp = INIT_REG_SET (&tmp_head);
 
-  /* ??? 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);
-
   blocks = sbitmap_alloc (n_basic_blocks);
   sbitmap_zero (blocks);
   changed = 0;
@@ -2729,6 +2725,7 @@ peephole2_optimize (dump_file)
   for (i = n_basic_blocks - 1; i >= 0; --i)
     {
       basic_block bb = BASIC_BLOCK (i);
+      COPY_REG_SET (live, bb->global_live_at_end);
 
       /* Since we don't update life info until the very end, we can't
 	 allow matching instructions that we've replaced before.  Walk
@@ -2737,39 +2734,45 @@ peephole2_optimize (dump_file)
 	 restrict how far forward we will allow the match to proceed.  */
 
       recog_last_allowed_insn = NEXT_INSN (bb->end);
-      for (insn = bb->end; ; insn = prev)
+      for (insn = bb->end; insn && insn != bb->head; insn = prev)
 	{
 	  prev = PREV_INSN (insn);
 	  if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
 	    {
 	      rtx try, last_insn;
 
-	      try = peephole2_insns (PATTERN (insn), insn, &last_insn);
-	      if (try != NULL)
-		{
-		  flow_delete_insn_chain (insn, last_insn);
-		  try = emit_insn_after (try, prev);
-
-		  if (last_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);
-		  changed = 1;
-		}
-	    }
+	      calc_live_before (insn, live, bb);
 
-	  if (insn == bb->head)
-	    break;
+	      /* Don't allow peephole2_insns to modify the live regs list.
+		 Any regs it allocates are scratches only.  */
+	      COPY_REG_SET (tmp, live);
+	      try = peephole2_insns (PATTERN (insn), insn, &last_insn, tmp);
+	      if (try == NULL)
+		continue;
+
+	      flow_delete_insn_chain (insn, last_insn);
+	      try = emit_insn_after (try, prev);
+
+	      if (last_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);
+	      changed = 1;
+	    }
 	}
     }
 
-  free_resource_info ();
-
-  compute_bb_for_insn (get_max_uid ());
-  count_or_remove_death_notes (blocks, 1);
-  update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
+  if (changed)
+    {
+      compute_bb_for_insn (get_max_uid ());
+      count_or_remove_death_notes (blocks, 1);
+      update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
+    }
+  sbitmap_free (blocks);
+  FREE_REG_SET (live);
+  FREE_REG_SET (tmp);
 }
 #endif
===================================================================
Index: recog.h
--- recog.h	2000/02/26 14:23:43	1.31
+++ recog.h	2000/04/09 17:14:36
@@ -118,7 +118,10 @@ extern void extract_insn		PARAMS ((rtx))
 extern void preprocess_constraints	PARAMS ((void));
 extern rtx recog_next_insn		PARAMS ((rtx, int));
 extern void peephole2_optimize		PARAMS ((FILE *));
-extern rtx peephole2_insns		PARAMS ((rtx, rtx, rtx *));
+/* Last arg to this function is a regset, but basic-block.h isn't available
+   here.  */
+extern rtx peephole2_insns		PARAMS ((rtx, rtx, rtx *,
+						 struct bitmap_head_def *));
 
 /* Nonzero means volatile operands are recognized.  */
 extern int volatile_ok;
===================================================================
Index: resource.c
--- resource.c	2000/03/27 21:50:15	1.28
+++ resource.c	2000/04/09 17:14:36
@@ -846,27 +846,34 @@ mark_set_resources (x, res, in_dest, mar
    in a hash table indexed by INSN_UID.  This is only done if the function
    init_resource_info () was invoked before we are called.  */
 
+static void mark_target_live_regs_hashed
+	PARAMS ((rtx, rtx, struct resources *));
+static void mark_target_live_regs_slow
+	PARAMS ((rtx, rtx, struct resources *, int, struct target_info *));
+
 void
 mark_target_live_regs (insns, target, res)
      rtx insns;
      rtx target;
      struct resources *res;
 {
-  int b = -1;
-  int i;
-  struct target_info *tinfo = NULL;
-  rtx insn;
-  rtx jump_insn = 0;
-  rtx jump_target;
-  HARD_REG_SET scratch;
-  struct resources set, needed;
-
   /* Handle end of function.  */
   if (target == 0)
     {
       *res = end_of_function_needs;
       return;
     }
+  mark_target_live_regs_hashed (insns, target, res);
+}
+
+static void
+mark_target_live_regs_hashed (insns, target, res)
+     rtx insns;
+     rtx target;
+     struct resources *res;
+{
+  int b = -1;
+  struct target_info *tinfo = NULL;
 
   /* We have to assume memory is needed, but the CC isn't.  */
   res->memory = 1;
@@ -916,6 +923,24 @@ mark_target_live_regs (insns, target, re
 	}
     }
 
+  mark_target_live_regs_slow (insns, target, res, b, tinfo);
+}
+
+static void
+mark_target_live_regs_slow (insns, target, res, b, tinfo)
+     rtx insns;
+     rtx target;
+     struct resources *res;
+     int b;
+     struct target_info *tinfo;
+{
+  rtx insn;
+  rtx jump_insn = 0;
+  rtx jump_target;
+  HARD_REG_SET scratch;
+  struct resources set, needed;
+  int i;
+
   CLEAR_HARD_REG_SET (pending_dead_regs);
 
   /* If we found a basic block, get the live registers from it and update
@@ -1260,110 +1285,4 @@ mark_end_of_function_resources (trial, i
 {
   mark_referenced_resources (trial, &end_of_function_needs,
 			     include_delayed_effects);
-}
-
-/* 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: resource.h
--- resource.h	2000/03/27 21:50:15	1.6
+++ resource.h	2000/04/09 17:14:36
@@ -50,6 +50,3 @@ extern void incr_ticks_for_insn		PARAMS 
 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: config/i386/i386.md
--- config/i386/i386.md	2000/04/08 04:33:28	1.149
+++ config/i386/i386.md	2000/04/09 17:14:37
@@ -9134,7 +9134,7 @@
    (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))
+   && ! REGNO_REG_SET_P (live, FLAGS_REG)
    && ! TARGET_USE_MOV0
    && TARGET_SPLIT_LONG_MOVES"
   [(parallel [(set (match_dup 1) (const_int 0))
@@ -9147,7 +9147,7 @@
    (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))
+   && ! REGNO_REG_SET_P (live, FLAGS_REG)
    && ! TARGET_USE_MOV0
    && TARGET_SPLIT_LONG_MOVES"
   [(parallel [(set (match_dup 2) (const_int 0))
@@ -9160,7 +9160,7 @@
    (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))
+   && ! REGNO_REG_SET_P (live, FLAGS_REG)
    && ! TARGET_USE_MOV0
    && TARGET_SPLIT_LONG_MOVES"
   [(parallel [(set (match_dup 2) (const_int 0))
@@ -9217,14 +9217,14 @@
 ;; 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 need to know if the
+;; CC register is live.
 
 (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))
+   && ! REGNO_REG_SET_P (live, FLAGS_REG)
    && ((TARGET_PENTIUM 
         && (GET_CODE (operands[0]) != MEM
             || !memory_displacement_operand (operands[0], SImode)))
@@ -9238,7 +9238,7 @@
   [(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))
+   && ! REGNO_REG_SET_P (live, FLAGS_REG)
    && ((TARGET_PENTIUM 
         && (GET_CODE (operands[0]) != MEM
             || !memory_displacement_operand (operands[0], HImode)))
@@ -9252,7 +9252,7 @@
   [(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))
+   && ! REGNO_REG_SET_P (live, FLAGS_REG)
    && ((TARGET_PENTIUM 
         && (GET_CODE (operands[0]) != MEM
             || !memory_displacement_operand (operands[0], QImode)))
@@ -9415,7 +9415,7 @@
     || 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))"
+   && ! REGNO_REG_SET_P (live, FLAGS_REG)"
   [(parallel [(set (match_dup 0) (const_int 0))
 	      (clobber (reg:CC 17))])]
   "operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]));")
@@ -9427,7 +9427,7 @@
   "(GET_MODE (operands[0]) == HImode
     || GET_MODE (operands[0]) == SImode)
    && (optimize_size || TARGET_PENTIUM)
-   && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
+   && ! REGNO_REG_SET_P (live, FLAGS_REG)"
   [(parallel [(set (match_dup 0) (const_int -1))
 	      (clobber (reg:CC 17))])]
   "operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]));")
@@ -9438,7 +9438,7 @@
   [(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))"
+  "! REGNO_REG_SET_P (live, FLAGS_REG)"
   [(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
 	      (clobber (reg:CC 17))])]
   "")
@@ -9447,7 +9447,7 @@
   [(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))"
+  "! REGNO_REG_SET_P (live, 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])));")


More information about the Gcc-patches mailing list