Removing some old code from the loop optimizer

Bernd Schmidt bernds@redhat.co.uk
Mon Sep 18 09:55:00 GMT 2000


Back in 1999, we added a patch to loop.c which introduced quite a bit of
new code: recombine_givs, code to convert bivs to givs, etc.  This was
done in an attempt to improve optimization for a particular target on
some particular testcases.
The code evolved a bit since then, and there is a large number of unmerged
changes in this code.  We've had a bit of internal discussion at Red Hat
what to do with it, and the conclusion was to delete it.  There are
several reasons:
 - It does not actually seem to fulfil its original purpose anymore.
   Re-testing showed that the currently installed version seems to have no
   significant gains on the original test code, and the additional patches
   actually seem to pessimize code.
 - I went back to the original testcases and tried to find simpler
   improvements; the recent changes to the cost calculations are a result
   of this.  I hope they should cover most of the code generation problems we
   found back then.
 - This code has numerous known bugs, with the additional patches introducing
   more of them.
 - It's large and complex and thus making maintenance of loop.c harder.

Jeff Law has approved removing this code.  He hasn't seen this patch yet,
so I'm submitting it here, and I will install it tomorrow morning unless
someone objects.

If someone finds that this code has a significant benefit on some code
samples (and does not pessimize others at the same time), I'd like to hear
about it.  I will try to fix any such problems if possible.


Bernd


	Undo most of the Wed Jan 27 23:39:53 1999 patch:
	* loop.h (struct induction): Delete members derived, ix and last_use.
	(struct loop_ivs): Delete members first_increment_giv and
	last_increment_giv.
	* loop.c (verify_dominator, find_life_end, cmp_recombine_givs_stats,
	recombine_givs): Delete functions.
	(find_and_verify_loops): Don't initialize cont_dominator.
	(strength_reduce): Lose code to try to find bivs that can be
	expressed as givs of another biv, and to convert biv increments 
	into givs.
	Lose loop_scan_start variable, always use loop->scan_start.
	Don't call recombine_givs.  Don't handle derived givs.
        (record_giv): Don't initialize derived and last_use fields.
	(biv_eliminiation_giv_has_0_offset): Lose code to handle derived
	givs.
	* unroll.c (derived_regs): Delete static variable.
	(unroll_loop): Don't initialize it.
	(copy_loop_body): Lose code to handle derived givs.
	(find_splittable_givs): Don't check for givs made from biv
	increments.
	Don't set derived_regs.
 
Index: loop.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/loop.c,v
retrieving revision 1.287
diff -u -p -r1.287 loop.c
--- loop.c	2000/09/14 01:20:33	1.287
+++ loop.c	2000/09/18 16:30:10
@@ -159,7 +159,6 @@ FILE *loop_dump_stream;
 
 /* Forward declarations.  */
 
-static void verify_dominator PARAMS ((struct loop *));
 static void find_and_verify_loops PARAMS ((rtx, struct loops *));
 static void mark_loop_jump PARAMS ((rtx, struct loop *));
 static void prescan_loop PARAMS ((struct loop *));
@@ -2431,58 +2430,6 @@ prescan_loop (loop)
     }
 }
 
-/* LOOP->CONT_DOMINATOR is now the last label between the loop start
-   and the continue note that is a the destination of a (cond)jump after
-   the continue note.  If there is any (cond)jump between the loop start
-   and what we have so far as LOOP->CONT_DOMINATOR that has a
-   target between LOOP->CONT_DOMINATOR and the continue note, move
-   LOOP->CONT_DOMINATOR forward to that label; if a jump's
-   destination cannot be determined, clear LOOP->CONT_DOMINATOR.  */
-
-static void
-verify_dominator (loop)
-     struct loop *loop;
-{
-  rtx insn;
-
-  if (! loop->cont_dominator)
-    /* This can happen for an empty loop, e.g. in
-       gcc.c-torture/compile/920410-2.c  */
-    return;
-  if (loop->cont_dominator == const0_rtx)
-    {
-      loop->cont_dominator = 0;
-      return;
-    }
-  for (insn = loop->start; insn != loop->cont_dominator;
-       insn = NEXT_INSN (insn))
-    {
-      if (GET_CODE (insn) == JUMP_INSN
-	  && GET_CODE (PATTERN (insn)) != RETURN)
-	{
-	  rtx label = JUMP_LABEL (insn);
-	  int label_luid;
-
-	  /* If it is not a jump we can easily understand or for
-	     which we do not have jump target information in the JUMP_LABEL
-	     field (consider ADDR_VEC and ADDR_DIFF_VEC insns), then clear
-	     LOOP->CONT_DOMINATOR.  */
-	  if (! any_condjump_p (insn)
-	      || label == NULL_RTX)
-	    {
-	      loop->cont_dominator = NULL_RTX;
-	      return;
-	    }
-
-	  label_luid = INSN_LUID (label);
-	  if (label_luid < INSN_LUID (loop->cont)
-	      && (label_luid
-		  > INSN_LUID (loop->cont)))
-	    loop->cont_dominator = label;
-	}
-    }
-}
-
 /* Scan the function looking for loops.  Record the start and end of each loop.
    Also mark as invalid loops any loops that contain a setjmp or are branched
    to from outside the loop.  */
@@ -2553,52 +2500,13 @@ find_and_verify_loops (f, loops)
 	      abort ();
 
 	    current_loop->end = insn;
-	    verify_dominator (current_loop);
 	    current_loop = current_loop->outer;
 	    break;
 
 	  default:
 	    break;
 	  }
-      /* If for any loop, this is a jump insn between the NOTE_INSN_LOOP_CONT
-	 and NOTE_INSN_LOOP_END notes, update loop->cont_dominator.  */
-      else if (GET_CODE (insn) == JUMP_INSN
-	       && GET_CODE (PATTERN (insn)) != RETURN
-	       && current_loop)
-	{
-	  rtx label = JUMP_LABEL (insn);
-
-	  if (! any_condjump_p (insn))
-	    label = NULL_RTX;
 
-	  loop = current_loop;
-	  do
-	    {
-	      /* First see if we care about this loop.  */
-	      if (loop->cont && loop->cont_dominator != const0_rtx)
-		{
-		  /* If the jump destination is not known, invalidate
-		     loop->cont_dominator.  */
-		  if (! label)
-		    loop->cont_dominator = const0_rtx;
-		  else
-		    /* Check if the destination is between loop start and
-		       cont.  */
-		    if ((INSN_LUID (label)
-			 < INSN_LUID (loop->cont))
-			&& (INSN_LUID (label) > INSN_LUID (loop->start))
-			/* And if there is no later destination already
-			   recorded.  */
-			&& (! loop->cont_dominator
-			    || (INSN_LUID (label)
-				> INSN_LUID (loop->cont_dominator))))
-		      loop->cont_dominator = label;
-		}
-	      loop = loop->outer;
-	    }
-	  while (loop);
-	}
-
       /* Note that this will mark the NOTE_INSN_LOOP_END note as being in the
 	 enclosing loop, but this doesn't matter.  */
       uid_loop[INSN_UID (insn)] = current_loop;
@@ -3750,11 +3658,9 @@ strength_reduce (loop, insn_count, flags
   int call_seen;
   rtx test;
   rtx end_insert_before;
-  int n_extra_increment;
   int unrolled_insn_copies = 0;
   rtx loop_start = loop->start;
   rtx loop_end = loop->end;
-  rtx loop_scan_start = loop->scan_start;
   rtx test_reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
 
   VARRAY_INT_INIT (ivs->reg_iv_type, max_reg_before_loop, "reg_iv_type");
@@ -3906,362 +3812,12 @@ strength_reduce (loop, insn_count, flags
 		  fprintf (loop_dump_stream, "\n");
 		}
 	    }
-	}
-      else
-	{
-	  struct iv_class *bl2 = 0;
-	  rtx increment = NULL_RTX;
-
-	  /* Biv initial value is not a simple move.  If it is the sum of
-	     another biv and a constant, check if both bivs are incremented
-	     in lockstep.  Then we are actually looking at a giv.
-	     For simplicity, we only handle the case where there is but a
-	     single increment, and the register is not used elsewhere.  */
-	  if (bl->biv_count == 1
-	      && bl->regno < max_reg_before_loop
-	      && uid_luid[REGNO_LAST_UID (bl->regno)] < INSN_LUID (loop_end)
-	      && GET_CODE (src) == PLUS
-	      && GET_CODE (XEXP (src, 0)) == REG
-	      && CONSTANT_P (XEXP (src, 1))
-	      && ((increment = biv_total_increment (bl)) != NULL_RTX))
-	    {
-	      unsigned int regno = REGNO (XEXP (src, 0));
-
-	      for (bl2 = ivs->loop_iv_list; bl2; bl2 = bl2->next)
-		if (bl2->regno == regno)
-		  break;
-	    }
-
-	  /* Now, can we transform this biv into a giv?  */
-	  if (bl2
-	      && bl2->biv_count == 1
-	      && rtx_equal_p (increment, biv_total_increment (bl2))
-	      /* init_insn is only set to insns that are before loop_start
-		 without any intervening labels.  */
-	      && ! reg_set_between_p (bl2->biv->src_reg,
-				      PREV_INSN (bl->init_insn), loop_start)
-	      /* The register from BL2 must be set before the register from
-		 BL is set, or we must be able to move the latter set after
-		 the former set.  Currently there can't be any labels
-	         in-between when biv_total_increment returns nonzero both times
-		 but we test it here in case some day some real cfg analysis
-		 gets used to set always_computable.  */
-	      && (loop_insn_first_p (bl2->biv->insn, bl->biv->insn)
-		  ? no_labels_between_p (bl2->biv->insn, bl->biv->insn)
-		  : (! reg_used_between_p (bl->biv->src_reg, bl->biv->insn,
-					   bl2->biv->insn)
-		     && no_jumps_between_p (bl->biv->insn, bl2->biv->insn)))
-	      && validate_change (bl->biv->insn,
-				  &SET_SRC (single_set (bl->biv->insn)),
-				  copy_rtx (src), 0))
-	    {
-	      rtx dominator = loop->cont_dominator;
-	      rtx giv = bl->biv->src_reg;
-	      rtx giv_insn = bl->biv->insn;
-	      rtx after_giv = NEXT_INSN (giv_insn);
-
-	      if (loop_dump_stream)
-		fprintf (loop_dump_stream, "is giv of biv %d\n", bl2->regno);
-	      /* Let this giv be discovered by the generic code.  */
-	      REG_IV_TYPE (ivs, bl->regno) = UNKNOWN_INDUCT;
-	      ivs->reg_biv_class[bl->regno] = (struct iv_class *) NULL_PTR;
-	      /* We can get better optimization if we can move the giv setting
-		 before the first giv use.  */
-	      if (dominator
-		  && ! loop_insn_first_p (dominator, loop_scan_start)
-		  && ! reg_set_between_p (bl2->biv->src_reg, loop_start,
-					  dominator)
-		  && ! reg_used_between_p (giv, loop_start, dominator)
-		  && ! reg_used_between_p (giv, giv_insn, loop_end))
-		{
-		  rtx p;
-		  rtx next;
-
-		  for (next = NEXT_INSN (dominator);; next = NEXT_INSN (next))
-		    {
-		      if (GET_CODE (next) == JUMP_INSN
-			  || (INSN_P (next)
-			      && insn_dependent_p (giv_insn, next)))
-			break;
-#ifdef HAVE_cc0
-		      if (! INSN_P (next) || ! sets_cc0_p (PATTERN (next)))
-#endif
-			dominator = next;
-		    }
-		  if (loop_dump_stream)
-		    fprintf (loop_dump_stream, "move after insn %d\n",
-			     INSN_UID (dominator));
-		  /* Avoid problems with luids by actually moving the insn
-		     and adjusting all luids in the range.  */
-		  reorder_insns (giv_insn, giv_insn, dominator);
-		  for (p = dominator; INSN_UID (p) >= max_uid_for_loop;)
-		    p = PREV_INSN (p);
-		  compute_luids (giv_insn, after_giv, INSN_LUID (p));
-		  /* If the only purpose of the init insn is to initialize
-		     this giv, delete it.  */
-		  if (single_set (bl->init_insn)
-		      && ! reg_used_between_p (giv, bl->init_insn, loop_start))
-		    delete_insn (bl->init_insn);
-		}
-	      else if (! loop_insn_first_p (bl2->biv->insn, bl->biv->insn))
-		{
-		  rtx p = PREV_INSN (giv_insn);
-		  while (INSN_UID (p) >= max_uid_for_loop)
-		    p = PREV_INSN (p);
-		  reorder_insns (giv_insn, giv_insn, bl2->biv->insn);
-		  compute_luids (after_giv, NEXT_INSN (giv_insn),
-				 INSN_LUID (p));
-		}
-	      /* Remove this biv from the chain.  */
-	      *backbl = bl->next;
-	    }
-
-	  /* If we can't make it a giv,
-	     let biv keep initial value of "itself".  */
-	  else if (loop_dump_stream)
-	    fprintf (loop_dump_stream, "is complex\n");
-	}
-    }
-
-  /* If a biv is unconditionally incremented several times in a row, convert
-     all but the last increment into a giv.  */
-
-  /* Get an upper bound for the number of registers
-     we might have after all bivs have been processed.  */
-  ivs->first_increment_giv = max_reg_num ();
-  for (n_extra_increment = 0, bl = ivs->loop_iv_list; bl; bl = bl->next)
-    n_extra_increment += bl->biv_count - 1;
-
-  /* If the loop contains volatile memory references do not allow any
-     replacements to take place, since this could loose the volatile
-     markers.  */
-  if (n_extra_increment  && ! loop_info->has_volatile)
-    {
-      unsigned int nregs = ivs->first_increment_giv + n_extra_increment;
-
-      /* Reallocate ivs->reg_iv_type and ivs->reg_iv_info.  */
-      VARRAY_GROW (ivs->reg_iv_type, nregs);
-      VARRAY_GROW (ivs->reg_iv_info, nregs);
-
-      for (bl = ivs->loop_iv_list; bl; bl = bl->next)
-	{
-	  struct induction **vp, *v, *next;
-	  int biv_dead_after_loop = 0;
-
-	  /* The biv increments lists are in reverse order.  Fix this
-             first.  */
-	  for (v = bl->biv, bl->biv = 0; v; v = next)
-	    {
-	      next = v->next_iv;
-	      v->next_iv = bl->biv;
-	      bl->biv = v;
-	    }
-
-	  /* We must guard against the case that an early exit between v->insn
-	     and next->insn leaves the biv live after the loop, since that
-	     would mean that we'd be missing an increment for the final
-	     value.  The following test to set biv_dead_after_loop is like
-	     the first part of the test to set bl->eliminable.
-	     We don't check here if we can calculate the final value, since
-	     this can't succeed if we already know that there is a jump
-	     between v->insn and next->insn, yet next->always_executed is
-	     set and next->maybe_multiple is cleared.  Such a combination
-	     implies that the jump destination is outside the loop.
-	     If we want to make this check more sophisticated, we should
-	     check each branch between v->insn and next->insn individually
-	     to see if the biv is dead at its destination.  */
-
-	  if (uid_luid[REGNO_LAST_UID (bl->regno)] < INSN_LUID (loop_end)
-	      && bl->init_insn
-	      && INSN_UID (bl->init_insn) < max_uid_for_loop
-	      && (uid_luid[REGNO_FIRST_UID (bl->regno)]
-		  >= INSN_LUID (bl->init_insn))
-#ifdef HAVE_decrement_and_branch_until_zero
-	      && ! bl->nonneg
-#endif
-	      && ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
-	    biv_dead_after_loop = 1;
-
-	  for (vp = &bl->biv, next = *vp; v = next, next = v->next_iv;)
-	    {
-	      HOST_WIDE_INT offset;
-	      rtx set, add_val, old_reg, dest_reg, last_use_insn, note;
-	      int old_regno, new_regno;
-	      rtx next_loc_insn;
-
-	      if (! v->always_executed
-		  || v->maybe_multiple
-		  || GET_CODE (v->add_val) != CONST_INT
-		  || ! next->always_executed
-		  || next->maybe_multiple
-		  || ! CONSTANT_P (next->add_val)
-		  || v->mult_val != const1_rtx
-		  || next->mult_val != const1_rtx
-		  || ! (biv_dead_after_loop
-			|| no_jumps_between_p (v->insn, next->insn)))
-		{
-		  vp = &v->next_iv;
-		  continue;
-		}
-	      offset = INTVAL (v->add_val);
-	      set = single_set (v->insn);
-	      add_val = plus_constant (next->add_val, offset);
-	      old_reg = v->dest_reg;
-	      dest_reg = gen_reg_rtx (v->mode);
-
-	      /* Unlike ivs->reg_iv_type / ivs->reg_iv_info, the other
-		 three arrays have been allocated with some slop
-		 space, so we may not actually need to reallocate
-		 them.  If we do, the following if statement will be
-		 executed just once in this loop.  */
-	      if ((unsigned) max_reg_num () > regs->n_times_set->num_elements)
-		{
-		  /* Grow all the remaining arrays.  */
-		  VARRAY_GROW (regs->set_in_loop, nregs);
-		  VARRAY_GROW (regs->n_times_set, nregs);
-		  VARRAY_GROW (regs->may_not_optimize, nregs);
-		  VARRAY_GROW (regs->single_usage, nregs);
-		}
-
-	      /* Some bivs are incremented with a multi-insn sequence.
-		 The first insn contains the add.  */
-	      next_loc_insn = next->insn;
-	      while (NOTE_P (next_loc_insn)
-		     || ! loc_mentioned_in_p (next->location,
-					      PATTERN (next_loc_insn)))
-		next_loc_insn = PREV_INSN (next_loc_insn);
-
-	      if (next_loc_insn == v->insn)
-		abort ();
-
-	      if (! validate_change (next_loc_insn, next->location, add_val, 0))
-		{
-		  vp = &v->next_iv;
-		  continue;
-		}
-
-	      /* Here we can try to eliminate the increment by combining
-		 it into the uses.  */
-
-	      /* Set last_use_insn so that we can check against it.  */
-
-	      for (last_use_insn = v->insn, p = NEXT_INSN (v->insn);
-		   p != next_loc_insn;
-		   p = next_insn_in_loop (loop, p))
-		{
-		  if (!INSN_P (p))
-		    continue;
-		  if (reg_mentioned_p (old_reg, PATTERN (p)))
-		    {
-		      last_use_insn = p;
-		    }
-		}
-
-	      /* If we can't get the LUIDs for the insns, we can't
-		 calculate the lifetime.  This is likely from unrolling
-		 of an inner loop, so there is little point in making this
-		 a DEST_REG giv anyways.  */
-	      if (INSN_UID (v->insn) >= max_uid_for_loop
-		  || INSN_UID (last_use_insn) >= max_uid_for_loop
-		  || ! validate_change (v->insn, &SET_DEST (set), dest_reg, 0))
-		{
-		  /* Change the increment at NEXT back to what it was.  */
-		  if (! validate_change (next_loc_insn, next->location,
-		      next->add_val, 0))
-		    abort ();
-		  vp = &v->next_iv;
-		  continue;
-		}
-	      next->add_val = add_val;
-	      v->dest_reg = dest_reg;
-	      v->giv_type = DEST_REG;
-	      v->location = &SET_SRC (set);
-	      v->cant_derive = 0;
-	      v->combined_with = 0;
-	      v->maybe_dead = 0;
-	      v->derive_adjustment = 0;
-	      v->same = 0;
-	      v->ignore = 0;
-	      v->new_reg = 0;
-	      v->final_value = 0;
-	      v->same_insn = 0;
-	      v->auto_inc_opt = 0;
-	      v->unrolled = 0;
-	      v->shared = 0;
-	      v->derived_from = 0;
-	      v->always_computable = 1;
-	      v->always_executed = 1;
-	      v->replaceable = 1;
-	      v->no_const_addval = 0;
-
-	      old_regno = REGNO (old_reg);
-	      new_regno = REGNO (dest_reg);
-	      VARRAY_INT (regs->set_in_loop, old_regno)--;
-	      VARRAY_INT (regs->set_in_loop, new_regno) = 1;
-	      VARRAY_INT (regs->n_times_set, old_regno)--;
-	      VARRAY_INT (regs->n_times_set, new_regno) = 1;
-	      VARRAY_CHAR (regs->may_not_optimize, new_regno) = 0;
-
-	      REG_IV_TYPE (ivs, new_regno) = GENERAL_INDUCT;
-	      REG_IV_INFO (ivs, new_regno) = v;
-
-	      /* If next_insn has a REG_EQUAL note that mentiones OLD_REG,
-		 it must be replaced.  */
-	      note = find_reg_note (next->insn, REG_EQUAL, NULL_RTX);
-	      if (note && reg_mentioned_p (old_reg, XEXP (note, 0)))
-		XEXP (note, 0) = copy_rtx (SET_SRC (single_set (next->insn)));
-
-	      /* Remove the increment from the list of biv increments,
-		 and record it as a giv.  */
-	      *vp = next;
-	      bl->biv_count--;
-	      v->next_iv = bl->giv;
-	      bl->giv = v;
-	      bl->giv_count++;
-	      v->benefit = rtx_cost (SET_SRC (set), SET);
-	      bl->total_benefit += v->benefit;
-
-	      /* Now replace the biv with DEST_REG in all insns between
-		 the replaced increment and the next increment, and
-		 remember the last insn that needed a replacement.  */
-	      for (last_use_insn = v->insn, p = NEXT_INSN (v->insn);
-		   p != next_loc_insn;
-		   p = next_insn_in_loop (loop, p))
-		{
-		  rtx note;
-
-		  if (! INSN_P (p))
-		    continue;
-		  if (reg_mentioned_p (old_reg, PATTERN (p)))
-		    {
-		      last_use_insn = p;
-		      if (! validate_replace_rtx (old_reg, dest_reg, p))
-			abort ();
-		    }
-		  for (note = REG_NOTES (p); note; note = XEXP (note, 1))
-		    {
-		      if (GET_CODE (note) == EXPR_LIST)
-			XEXP (note, 0)
-			  = replace_rtx (XEXP (note, 0), old_reg, dest_reg);
-		    }
-		}
-
-	      v->last_use = last_use_insn;
-	      v->lifetime = INSN_LUID (last_use_insn) - INSN_LUID (v->insn);
-	      /* If the lifetime is zero, it means that this register is really
-		 a dead store.  So mark this as a giv that can be ignored.
-		 This will not prevent the biv from being eliminated.  */
-	      if (v->lifetime == 0)
-		v->ignore = 1;
-
-	      if (loop_dump_stream)
-		fprintf (loop_dump_stream,
-			 "Increment %d of biv %d converted to giv %d.\n\n",
-			 INSN_UID (v->insn), old_regno, new_regno);
-	    }
 	}
+      /* If we can't make it a giv,
+       let biv keep initial value of "itself".  */
+      else if (loop_dump_stream)
+	fprintf (loop_dump_stream, "is complex\n");
     }
-  ivs->last_increment_giv = max_reg_num () - 1;
 
   /* Search the loop for general induction variables.  */
 
@@ -4308,7 +3864,6 @@ strength_reduce (loop, insn_count, flags
       int benefit;
       int all_reduced;
       rtx final_value = 0;
-      unsigned int nregs;
 
       /* Test whether it will be possible to eliminate this biv
 	 provided all givs are reduced.  This is possible if either
@@ -4486,17 +4041,9 @@ strength_reduce (loop, insn_count, flags
 	  if (v->ignore
 	      || (v->same && v->same->ignore))
 	    continue;
-
-	  if (v->last_use)
-	    {
-	      struct induction *v1;
 
-	      for (v1 = bl->giv; v1; v1 = v1->next_iv)
-		if (v->last_use == v1->insn)
-		  v->maybe_dead = 1;
-	    }
-	  else if (v->giv_type == DEST_REG
-		   && REGNO_FIRST_UID (REGNO (v->dest_reg)) == INSN_UID (v->insn))
+	  if (v->giv_type == DEST_REG
+	      && REGNO_FIRST_UID (REGNO (v->dest_reg)) == INSN_UID (v->insn))
 	    {
 	      struct induction *v1;
 
@@ -4506,25 +4053,6 @@ strength_reduce (loop, insn_count, flags
 	    }
 	}
 
-      /* Now that we know which givs will be reduced, try to rearrange the
-         combinations to reduce register pressure.
-         recombine_givs calls find_life_end, which needs ivs->reg_iv_type and
-	 ivs->reg_iv_info to be valid for all pseudos.  We do the necessary
-	 reallocation here since it allows to check if there are still
-	 more bivs to process.  */
-      nregs = max_reg_num ();
-      if (nregs > ivs->reg_iv_type->num_elements)
-	{
-	  /* If there are still more bivs to process, allocate some slack
-	     space so that we're not constantly reallocating these arrays.  */
-	  if (bl->next)
-	    nregs += nregs / 4;
-	  /* Reallocate ivs->reg_iv_type and ivs->reg_iv_info.  */
-	  VARRAY_GROW (ivs->reg_iv_type, nregs);
-	  VARRAY_GROW (ivs->reg_iv_info, nregs);
-	}
-      recombine_givs (loop, bl, flags & LOOP_UNROLL);
-
       /* Reduce each giv that we decided to reduce.  */
 
       for (v = bl->giv; v; v = v->next_iv)
@@ -4539,45 +4067,6 @@ strength_reduce (loop, insn_count, flags
 	      if (! v->new_reg)
 		v->new_reg = gen_reg_rtx (v->mode);
 
-	      if (v->derived_from)
-		{
-		  struct induction *d = v->derived_from;
-
-		  /* In case d->dest_reg is not replaceable, we have
-		     to replace it in v->insn now.  */
-		  if (! d->new_reg)
-		    d->new_reg = gen_reg_rtx (d->mode);
-		  PATTERN (v->insn)
-		    = replace_rtx (PATTERN (v->insn), d->dest_reg, d->new_reg);
-		  PATTERN (v->insn)
-		    = replace_rtx (PATTERN (v->insn), v->dest_reg, v->new_reg);
-		  /* For each place where the biv is incremented, add an
-		     insn to set the new, reduced reg for the giv.
-		     We used to do this only for biv_count != 1, but
-		     this fails when there is a giv after a single biv
-		     increment, e.g. when the last giv was expressed as
-		     pre-decrement.  */
-		  for (tv = bl->biv; tv; tv = tv->next_iv)
-		    {
-		      /* We always emit reduced giv increments before the
-			 biv increment when bl->biv_count != 1.  So by
-			 emitting the add insns for derived givs after the
-			 biv increment, they pick up the updated value of
-			 the reduced giv.
-			 If the reduced giv is processed with
-			 auto_inc_opt == 1, then it is incremented earlier
-			 than the biv, hence we'll still pick up the right
-			 value.
-			 If it's processed with auto_inc_opt == -1,
-			 that implies that the biv increment is before the
-			 first reduced giv's use.  The derived giv's lifetime
-			 is after the reduced giv's lifetime, hence in this
-			 case, the biv increment doesn't matter.  */
-		      emit_insn_after (copy_rtx (PATTERN (v->insn)), tv->insn);
-		    }
-		  continue;
-		}
-
 #ifdef AUTO_INC_DEC
 	      /* If the target has auto-increment addressing modes, and
 		 this is an address giv, then try to put the increment
@@ -4625,11 +4114,11 @@ strength_reduce (loop, insn_count, flags
 		  /* Check for case where increment is before the address
 		     giv.  Do this test in "loop order".  */
 		  else if ((INSN_LUID (v->insn) > INSN_LUID (bl->biv->insn)
-			    && (INSN_LUID (v->insn) < INSN_LUID (loop_scan_start)
+			    && (INSN_LUID (v->insn) < INSN_LUID (loop->scan_start)
 				|| (INSN_LUID (bl->biv->insn)
-				    > INSN_LUID (loop_scan_start))))
-			   || (INSN_LUID (v->insn) < INSN_LUID (loop_scan_start)
-			       && (INSN_LUID (loop_scan_start)
+				    > INSN_LUID (loop->scan_start))))
+			   || (INSN_LUID (v->insn) < INSN_LUID (loop->scan_start)
+			       && (INSN_LUID (loop->scan_start)
 				   < INSN_LUID (bl->biv->insn))))
 		    auto_inc_opt = -1;
 		  else
@@ -5364,8 +4853,6 @@ record_giv (loop, v, insn, src_reg, dest
   v->auto_inc_opt = 0;
   v->unrolled = 0;
   v->shared = 0;
-  v->derived_from = 0;
-  v->last_use = 0;
 
   /* The v->always_computable field is used in update_giv_derive, to
      determine whether a giv can be used to derive another giv.  For a
@@ -6157,8 +5644,6 @@ general_induction_var (loop, x, src_reg,
 
 static rtx sge_plus PARAMS ((enum machine_mode, rtx, rtx));
 static rtx sge_plus_constant PARAMS ((rtx, rtx));
-static int cmp_combine_givs_stats PARAMS ((const PTR, const PTR));
-static int cmp_recombine_givs_stats PARAMS ((const PTR, const PTR));
 
 static rtx
 simplify_giv_expr (loop, x, ext_val, benefit)
@@ -7373,444 +6858,6 @@ restart:
   free (can_combine);
 }
 
-struct recombine_givs_stats
-{
-  int giv_number;
-  int start_luid, end_luid;
-};
-
-/* Used below as comparison function for qsort.  We want a ascending luid
-   when scanning the array starting at the end, thus the arguments are
-   used in reverse.  */
-static int
-cmp_recombine_givs_stats (xp, yp)
-     const PTR xp;
-     const PTR yp;
-{
-  const struct recombine_givs_stats * const x =
-    (const struct recombine_givs_stats *) xp;
-  const struct recombine_givs_stats * const y =
-    (const struct recombine_givs_stats *) yp;
-  int d;
-  d = y->start_luid - x->start_luid;
-  /* Stabilize the sort.  */
-  if (!d)
-    d = y->giv_number - x->giv_number;
-  return d;
-}
-
-/* Scan X, which is a part of INSN, for the end of life of a giv.  Also
-   look for the start of life of a giv where the start has not been seen
-   yet to unlock the search for the end of its life.
-   Only consider givs that belong to BIV.
-   Return the total number of lifetime ends that have been found.  */
-static int
-find_life_end (loop, x, stats, insn, biv)
-     const struct loop *loop;
-     rtx x, insn, biv;
-     struct recombine_givs_stats *stats;
-{
-  struct loop_ivs *ivs = LOOP_IVS (loop);
-  enum rtx_code code;
-  const char *fmt;
-  int i, j;
-  int retval;
-
-  code = GET_CODE (x);
-  switch (code)
-    {
-    case SET:
-      {
-	rtx reg = SET_DEST (x);
-	if (GET_CODE (reg) == REG)
-	  {
-	    int regno = REGNO (reg);
-	    struct induction *v = REG_IV_INFO (ivs, regno);
-
-	    if (REG_IV_TYPE (ivs, regno) == GENERAL_INDUCT
-		&& ! v->ignore
-		&& v->src_reg == biv
-		&& stats[v->ix].end_luid <= 0)
-	      {
-		/* If we see a 0 here for end_luid, it means that we have
-		   scanned the entire loop without finding any use at all.
-		   We must not predicate this code on a start_luid match
-		   since that would make the test fail for givs that have
-		   been hoisted out of inner loops.  */
-		if (stats[v->ix].end_luid == 0)
-		  {
-		    stats[v->ix].end_luid = stats[v->ix].start_luid;
-		    return 1 + find_life_end (loop, SET_SRC (x), stats,
-					      insn, biv);
-		  }
-		else if (stats[v->ix].start_luid == INSN_LUID (insn))
-		  stats[v->ix].end_luid = 0;
-	      }
-	    return find_life_end (loop, SET_SRC (x), stats, insn, biv);
-	  }
-	break;
-      }
-    case REG:
-      {
-	int regno = REGNO (x);
-	struct induction *v = REG_IV_INFO (ivs, regno);
-
-	if (REG_IV_TYPE (ivs, regno) == GENERAL_INDUCT
-	    && ! v->ignore
-	    && v->src_reg == biv
-	    && stats[v->ix].end_luid == 0)
-	  {
-	    while (INSN_UID (insn) >= max_uid_for_loop)
-	      insn = NEXT_INSN (insn);
-	    stats[v->ix].end_luid = INSN_LUID (insn);
-	    return 1;
-	  }
-	return 0;
-      }
-    case LABEL_REF:
-    case CONST_DOUBLE:
-    case CONST_INT:
-    case CONST:
-      return 0;
-    default:
-      break;
-    }
-  fmt = GET_RTX_FORMAT (code);
-  retval = 0;
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-	retval += find_life_end (loop, XEXP (x, i), stats, insn, biv);
-
-      else if (fmt[i] == 'E')
-	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-	  retval += find_life_end (loop, XVECEXP (x, i, j), stats, insn, biv);
-    }
-  return retval;
-}
-
-/* For each giv that has been combined with another, look if
-   we can combine it with the most recently used one instead.
-   This tends to shorten giv lifetimes, and helps the next step:
-   try to derive givs from other givs.  */
-static void
-recombine_givs (loop, bl, unroll_p)
-     const struct loop *loop;
-     struct iv_class *bl;
-     int unroll_p;
-{
-  struct loop_regs *regs = LOOP_REGS (loop);
-  struct induction *v, **giv_array, *last_giv;
-  struct recombine_givs_stats *stats;
-  int giv_count;
-  int i, rescan;
-  int ends_need_computing;
-
-  for (giv_count = 0, v = bl->giv; v; v = v->next_iv)
-    {
-      if (! v->ignore)
-	giv_count++;
-    }
-  giv_array
-    = (struct induction **) xmalloc (giv_count * sizeof (struct induction *));
-  stats = (struct recombine_givs_stats *) xmalloc (giv_count * sizeof *stats);
-
-  /* Initialize stats and set up the ix field for each giv in stats to name
-     the corresponding index into stats.  */
-  for (i = 0, v = bl->giv; v; v = v->next_iv)
-    {
-      rtx p;
-
-      if (v->ignore)
-	continue;
-      giv_array[i] = v;
-      stats[i].giv_number = i;
-      /* If this giv has been hoisted out of an inner loop, use the luid of
-	 the previous insn.  */
-      for (p = v->insn; INSN_UID (p) >= max_uid_for_loop; )
-	p = PREV_INSN (p);
-      stats[i].start_luid = INSN_LUID (p);
-      i++;
-    }
-
-  qsort (stats, giv_count, sizeof (*stats), cmp_recombine_givs_stats);
-
-  /* Set up the ix field for each giv in stats to name
-     the corresponding index into stats, and
-     do the actual most-recently-used recombination.  */
-  for (last_giv = 0, i = giv_count - 1; i >= 0; i--)
-    {
-      v = giv_array[stats[i].giv_number];
-      v->ix = i;
-      if (v->same)
-	{
-	  struct induction *old_same = v->same;
-	  rtx new_combine;
-
-	  /* combine_givs_p actually says if we can make this transformation.
-	     The other tests are here only to avoid keeping a giv alive
-	     that could otherwise be eliminated.  */
-	  if (last_giv
-	      && ((old_same->maybe_dead && ! old_same->combined_with)
-		  || ! last_giv->maybe_dead
-		  || last_giv->combined_with)
-	      && (new_combine = combine_givs_p (last_giv, v)))
-	    {
-	      old_same->combined_with--;
-	      v->new_reg = new_combine;
-	      v->same = last_giv;
-	      last_giv->combined_with++;
-	      /* No need to update lifetimes / benefits here since we have
-		 already decided what to reduce.  */
-
-	      if (loop_dump_stream)
-		{
-		  fprintf (loop_dump_stream,
-			   "giv at %d recombined with giv at %d as ",
-			   INSN_UID (v->insn), INSN_UID (last_giv->insn));
-		  print_rtl (loop_dump_stream, v->new_reg);
-		  putc ('\n', loop_dump_stream);
-		}
-	      continue;
-	    }
-	  v = v->same;
-	}
-      else if (v->giv_type != DEST_REG)
-	continue;
-      if (! last_giv
-	  || (last_giv->maybe_dead && ! last_giv->combined_with)
-	  || ! v->maybe_dead
-	  || v->combined_with)
-	last_giv = v;
-    }
-
-  ends_need_computing = 0;
-  /* For each DEST_REG giv, compute lifetime starts, and try to compute
-     lifetime ends from regscan info.  */
-  for (i = giv_count - 1; i >= 0; i--)
-    {
-      v = giv_array[stats[i].giv_number];
-      if (v->ignore)
-	continue;
-      if (v->giv_type == DEST_ADDR)
-	{
-	  /* Loop unrolling of an inner loop can even create new DEST_REG
-	     givs.  */
-	  rtx p;
-	  for (p = v->insn; INSN_UID (p) >= max_uid_for_loop;)
-	    p = PREV_INSN (p);
-	  stats[i].start_luid = stats[i].end_luid = INSN_LUID (p);
-	  if (p != v->insn)
-	    stats[i].end_luid++;
-	}
-      else /* v->giv_type == DEST_REG */
-	{
-	  if (v->last_use)
-	    {
-	      stats[i].start_luid = INSN_LUID (v->insn);
-	      stats[i].end_luid = INSN_LUID (v->last_use);
-	    }
-	  else if (INSN_UID (v->insn) >= max_uid_for_loop)
-	    {
-	      rtx p;
-	      /* This insn has been created by loop optimization on an inner
-		 loop.  We don't have a proper start_luid that will match
-		 when we see the first set.  But we do know that there will
-		 be no use before the set, so we can set end_luid to 0 so that
-		 we'll start looking for the last use right away.  */
-	      for (p = PREV_INSN (v->insn); INSN_UID (p) >= max_uid_for_loop; )
-		p = PREV_INSN (p);
-	      stats[i].start_luid = INSN_LUID (p);
-	      stats[i].end_luid = 0;
-	      ends_need_computing++;
-	    }
-	  else
-	    {
-	      int regno = REGNO (v->dest_reg);
-	      int count = VARRAY_INT (regs->n_times_set, regno) - 1;
-	      rtx p = v->insn;
-
-	      /* Find the first insn that sets the giv, so that we can verify
-		 if this giv's lifetime wraps around the loop.  We also need
-		 the luid of the first setting insn in order to detect the
-		 last use properly.  */
-	      while (count)
-		{
-		  p = prev_nonnote_insn (p);
-		  if (reg_set_p (v->dest_reg, p))
-		    count--;
-		}
-
-	      stats[i].start_luid = INSN_LUID (p);
-	      if (stats[i].start_luid > uid_luid[REGNO_FIRST_UID (regno)])
-		{
-		  stats[i].end_luid = -1;
-		  ends_need_computing++;
-		}
-	      else
-		{
-		  stats[i].end_luid = uid_luid[REGNO_LAST_UID (regno)];
-		  if (stats[i].end_luid > INSN_LUID (loop->end))
-		    {
-		      stats[i].end_luid = -1;
-		      ends_need_computing++;
-		    }
-		}
-	    }
-	}
-    }
-
-  /* If the regscan information was unconclusive for one or more DEST_REG
-     givs, scan the all insn in the loop to find out lifetime ends.  */
-  if (ends_need_computing)
-    {
-      rtx biv = bl->biv->src_reg;
-      rtx p = loop->end;
-
-      do
-	{
-	  if (p == loop->start)
-	    p = loop->end;
-	  p = PREV_INSN (p);
-	  if (! INSN_P (p))
-	    continue;
-	  ends_need_computing -= find_life_end (loop, PATTERN (p),
-						stats, p, biv);
-	}
-      while (ends_need_computing);
-    }
-
-  /* Set start_luid back to the last insn that sets the giv.  This allows
-     more combinations.  */
-  for (i = giv_count - 1; i >= 0; i--)
-    {
-      v = giv_array[stats[i].giv_number];
-      if (v->ignore)
-	continue;
-      if (INSN_UID (v->insn) < max_uid_for_loop)
-	stats[i].start_luid = INSN_LUID (v->insn);
-    }
-
-  /* Now adjust lifetime ends by taking combined givs into account.  */
-  for (i = giv_count - 1; i >= 0; i--)
-    {
-      unsigned luid;
-      int j;
-
-      v = giv_array[stats[i].giv_number];
-      if (v->ignore)
-	continue;
-      if (v->same && ! v->same->ignore)
-	{
-	  j = v->same->ix;
-	  luid = stats[i].start_luid;
-	  /* Use unsigned arithmetic to model loop wrap-around.  */
-	  if (luid - stats[j].start_luid
-	      > (unsigned) stats[j].end_luid - stats[j].start_luid)
-	    stats[j].end_luid = luid;
-	}
-    }
-
-  qsort (stats, giv_count, sizeof (*stats), cmp_recombine_givs_stats);
-
-  /* Try to derive DEST_REG givs from previous DEST_REG givs with the
-     same mult_val and non-overlapping lifetime.  This reduces register
-     pressure.
-     Once we find a DEST_REG giv that is suitable to derive others from,
-     we set last_giv to this giv, and try to derive as many other DEST_REG
-     givs from it without joining overlapping lifetimes.  If we then
-     encounter a DEST_REG giv that we can't derive, we set rescan to the
-     index for this giv (unless rescan is already set).
-     When we are finished with the current LAST_GIV (i.e. the inner loop
-     terminates), we start again with rescan, which then becomes the new
-     LAST_GIV.  */
-  for (i = giv_count - 1; i >= 0; i = rescan)
-    {
-      int life_start = 0, life_end = 0;
-
-      for (last_giv = 0, rescan = -1; i >= 0; i--)
-	{
-	  rtx sum;
-
-	  v = giv_array[stats[i].giv_number];
-	  if (v->giv_type != DEST_REG || v->derived_from || v->same)
-	    continue;
-	  if (! last_giv)
-	    {
-	      /* Don't use a giv that's likely to be dead to derive
-		 others - that would be likely to keep that giv alive.  */
-	      if (! v->maybe_dead || v->combined_with)
-		{
-		  last_giv = v;
-		  life_start = stats[i].start_luid;
-		  life_end = stats[i].end_luid;
-		}
-	      continue;
-	    }
-	  /* Use unsigned arithmetic to model loop wrap around.  */
-	  if (((unsigned) stats[i].start_luid - life_start
-	       >= (unsigned) life_end - life_start)
-	      && ((unsigned) stats[i].end_luid - life_start
-		  > (unsigned) life_end - life_start)
-	      /*  Check that the giv insn we're about to use for deriving
-		  precedes all uses of that giv.  Note that initializing the
-		  derived giv would defeat the purpose of reducing register
-		  pressure.
-		  ??? We could arrange to move the insn.  */
-	      && ((unsigned) stats[i].end_luid - INSN_LUID (loop->start)
-                  > (unsigned) stats[i].start_luid - INSN_LUID (loop->start))
-	      && rtx_equal_p (last_giv->mult_val, v->mult_val)
-	      /* ??? Could handle libcalls, but would need more logic.  */
-	      && ! find_reg_note (v->insn, REG_RETVAL, NULL_RTX)
-	      /* We would really like to know if for any giv that v
-		 is combined with, v->insn or any intervening biv increment
-		 dominates that combined giv.  However, we
-		 don't have this detailed control flow information.
-		 N.B. since last_giv will be reduced, it is valid
-		 anywhere in the loop, so we don't need to check the
-		 validity of last_giv.
-		 We rely here on the fact that v->always_executed implies that
-		 there is no jump to someplace else in the loop before the
-		 giv insn, and hence any insn that is executed before the
-		 giv insn in the loop will have a lower luid.  */
-	      && (v->always_executed || ! v->combined_with)
-	      && (sum = express_from (last_giv, v))
-	      /* Make sure we don't make the add more expensive.  ADD_COST
-		 doesn't take different costs of registers and constants into
-		 account, so compare the cost of the actual SET_SRCs.  */
-	      && (rtx_cost (sum, SET)
-		  <= rtx_cost (SET_SRC (single_set (v->insn)), SET))
-	      /* ??? unroll can't understand anything but reg + const_int
-		 sums.  It would be cleaner to fix unroll.  */
-	      && ((GET_CODE (sum) == PLUS
-		   && GET_CODE (XEXP (sum, 0)) == REG
-		   && GET_CODE (XEXP (sum, 1)) == CONST_INT)
-		  || ! unroll_p)
-	      && validate_change (v->insn, &PATTERN (v->insn),
-				  gen_rtx_SET (VOIDmode, v->dest_reg, sum), 0))
-	    {
-	      v->derived_from = last_giv;
-	      life_end = stats[i].end_luid;
-
-	      if (loop_dump_stream)
-		{
-		  fprintf (loop_dump_stream,
-			   "giv at %d derived from %d as ",
-			   INSN_UID (v->insn), INSN_UID (last_giv->insn));
-		  print_rtl (loop_dump_stream, sum);
-		  putc ('\n', loop_dump_stream);
-		}
-	    }
-	  else if (rescan < 0)
-	    rescan = i;
-	}
-    }
-
-  /* Clean up.  */
-  free (giv_array);
-  free (stats);
-}
-
 /* EMIT code before INSERT_BEFORE to set REG = B * M + A.  */
 
 void
@@ -8693,22 +7740,6 @@ biv_elimination_giv_has_0_offset (biv, g
 	   && loop_insn_first_p (insn, biv->insn))
 	  || (loop_insn_first_p (biv->insn, insn)
 	      && loop_insn_first_p (insn, giv->insn))))
-    return 0;
-
-  /* If the giv V was derived from another giv, and INSN does
-     not occur between the giv insn and the biv insn, then we'd
-     have to adjust the value used here.  This is rare, so we don't
-     bother to make this possible.  */
-  if (giv->derived_from
-      && ! (giv->always_executed
-	    && loop_insn_first_p (giv->insn, insn)
-	    && loop_insn_first_p (insn, biv->insn)))
-    return 0;
-  if (giv->same
-      && giv->same->derived_from
-      && ! (giv->same->always_executed
-	    && loop_insn_first_p (giv->same->insn, insn)
-	    && loop_insn_first_p (insn, biv->insn)))
     return 0;
 
   return 1;
Index: loop.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/loop.h,v
retrieving revision 1.39
diff -u -p -r1.39 loop.h
--- loop.h	2000/09/14 01:20:34	1.39
+++ loop.h	2000/09/18 16:30:11
@@ -133,14 +133,10 @@ struct induction
   struct induction *same;	/* If this giv has been combined with another
 				   giv, this points to the base giv.  The base
 				   giv will have COMBINED_WITH non-zero.  */
-  struct induction *derived_from;/* For a giv, if we decided to derive this
-				   giv from another one.  */
   HOST_WIDE_INT const_adjust;	/* Used by loop unrolling, when an address giv
 				   is split, and a constant is eliminated from
 				   the address, the -constant is stored here
 				   for later use.  */
-  int ix;			/* Used by recombine_givs, as n index into
-				   the stats array.  */
   struct induction *same_insn;	/* If there are multiple identical givs in
 				   the same insn, then all but one have this
 				   field set, and they all point to the giv
@@ -201,12 +197,6 @@ struct loop_ivs
   /* The head of a list which links together (via the next field)
      every iv class for the current loop.  */
   struct iv_class *loop_iv_list;
-
-  /* Givs made from biv increments are always splittable for loop
-     unrolling.  Since there is no regscan info for them, we have to
-     keep track of them separately.  */
-  unsigned int first_increment_giv;
-  unsigned int last_increment_giv;
 };
 
 struct loop_regs
Index: unroll.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/unroll.c,v
retrieving revision 1.108
diff -u -p -r1.108 unroll.c
--- unroll.c	2000/09/12 14:43:25	1.108
+++ unroll.c	2000/09/18 16:30:12
@@ -190,10 +190,6 @@ static struct induction **addr_combined_
 static rtx *splittable_regs;
 
 /* Indexed by register number, if this is a splittable induction variable,
-   this indicates if it was made from a derived giv.  */
-static char *derived_regs;
-
-/* Indexed by register number, if this is a splittable induction variable,
    then this will hold the number of instructions in the loop that modify
    the induction variable.  Used to ensure that only the last insn modifying
    a split iv will update the original iv of the dest.  */
@@ -806,7 +802,6 @@ unroll_loop (loop, insn_count, end_inser
      to access the splittable_regs[] and addr_combined_regs[] arrays.  */
 
   splittable_regs = (rtx *) xcalloc (maxregnum, sizeof (rtx));
-  derived_regs = (char *) xcalloc (maxregnum, sizeof (char));
   splittable_regs_updates = (int *) xcalloc (maxregnum, sizeof (int));
   addr_combined_regs
     = (struct induction **) xcalloc (maxregnum, sizeof (struct induction *));
@@ -872,14 +867,6 @@ unroll_loop (loop, insn_count, end_inser
 			   r);
 	      }
 	  }
-      /* Givs that have been created from multiple biv increments always have
-	 local registers.  */
-      for (r = ivs->first_increment_giv; r <= ivs->last_increment_giv; r++)
-	{
-	  local_regno[r] = 1;
-	  if (loop_dump_stream)
-	    fprintf (loop_dump_stream, "Marked reg %d as local\n", r);
-	}
     }
 
   /* If this loop requires exit tests when unrolled, check to see if we
@@ -1346,7 +1333,6 @@ unroll_loop (loop, insn_count, end_inser
     }
   free (map->insn_map);
   free (splittable_regs);
-  free (derived_regs);
   free (splittable_regs_updates);
   free (addr_combined_regs);
   free (local_regno);
@@ -1792,8 +1778,7 @@ copy_loop_body (loop, copy_start, copy_e
 		 we might accidentally delete insns generated immediately
 		 below by emit_unrolled_add.  */
 
-	      if (! derived_regs[regno])
-		giv_inc = calculate_giv_inc (set, insn, regno);
+	      giv_inc = calculate_giv_inc (set, insn, regno);
 
 	      /* Now find all address giv's that were combined with this
 		 giv 'v'.  */
@@ -1880,23 +1865,12 @@ copy_loop_body (loop, copy_start, copy_e
 	      dest_reg_was_split = 1;
 
 	      giv_dest_reg = SET_DEST (set);
-	      if (derived_regs[regno])
-		{
-		  /* ??? This relies on SET_SRC (SET) to be of
-		     the form (plus (reg) (const_int)), and thus
-		     forces recombine_givs to restrict the kind
-		     of giv derivations it does before unrolling.  */
-		  giv_src_reg = XEXP (SET_SRC (set), 0);
-		  giv_inc = XEXP (SET_SRC (set), 1);
-		}
-	      else
-		{
-		  giv_src_reg = giv_dest_reg;
-		  /* Compute the increment value for the giv, if it wasn't
-		     already computed above.  */
-		  if (giv_inc == 0)
-		    giv_inc = calculate_giv_inc (set, insn, regno);
-		}
+	      giv_src_reg = giv_dest_reg;
+	      /* Compute the increment value for the giv, if it wasn't
+		 already computed above.  */
+	      if (giv_inc == 0)
+		giv_inc = calculate_giv_inc (set, insn, regno);
+
 	      src_regno = REGNO (giv_src_reg);
 
 	      if (unroll_type == UNROLL_COMPLETELY)
@@ -2724,10 +2698,6 @@ find_splittable_givs (loop, bl, unroll_t
 	      /* Line above always fails if INSN was moved by loop opt.  */
 	      || (uid_luid[REGNO_LAST_UID (REGNO (v->dest_reg))]
 		  >= INSN_LUID (loop->end)))
-	  /* Givs made from biv increments are missed by the above test, so
-	     test explicitly for them.  */
-	  && (REGNO (v->dest_reg) < ivs->first_increment_giv
-	      || REGNO (v->dest_reg) > ivs->last_increment_giv)
 	  && ! (final_value = v->final_value))
 	continue;
 
@@ -2829,7 +2799,6 @@ find_splittable_givs (loop, bl, unroll_t
 		}
 
 	      splittable_regs[REGNO (v->new_reg)] = value;
-	      derived_regs[REGNO (v->new_reg)] = v->derived_from != 0;
 	    }
 	  else
 	    {
@@ -2889,25 +2858,6 @@ find_splittable_givs (loop, bl, unroll_t
 		  rtx new_reg = v->new_reg;
 		  record_base_value (REGNO (tem), v->add_val, 0);
 
-		  if (same && same->derived_from)
-		    {
-		      /* calculate_giv_inc doesn't work for derived givs.
-			 copy_loop_body works around the problem for the
-			 DEST_REG givs themselves, but it can't handle
-			 DEST_ADDR givs that have been combined with
-			 a derived DEST_REG giv.
-			 So Handle V as if the giv from which V->SAME has
-			 been derived has been combined with V.
-			 recombine_givs only derives givs from givs that
-			 are reduced the ordinary, so we need not worry
-			 about same->derived_from being in turn derived.  */
-
-		      same = same->derived_from;
-		      new_reg = express_from (same, v);
-		      new_reg = replace_rtx (new_reg, same->dest_reg,
-					     same->new_reg);
-		    }
-
 		  /* If the address giv has a constant in its new_reg value,
 		     then this constant can be pulled out and put in value,
 		     instead of being part of the initialization code.  */
@@ -3015,17 +2965,6 @@ find_splittable_givs (loop, bl, unroll_t
 				 INSN_UID (v->insn));
 		      continue;
 		    }
-		  if (v->same && v->same->derived_from)
-		    {
-		      /* Handle V as if the giv from which V->SAME has
-			 been derived has been combined with V.  */
-
-		      v->same = v->same->derived_from;
-		      v->new_reg = express_from (v->same, v);
-		      v->new_reg = replace_rtx (v->new_reg, v->same->dest_reg,
-						v->same->new_reg);
-		    }
-
 		}
 
 	      /* Store the value of dest_reg into the insn.  This sharing
@@ -3048,7 +2987,6 @@ find_splittable_givs (loop, bl, unroll_t
 		     Make sure that it's giv is marked as splittable here.  */
 
 		  splittable_regs[REGNO (v->new_reg)] = value;
-		  derived_regs[REGNO (v->new_reg)] = v->derived_from != 0;
 
 		  /* Make it appear to depend upon itself, so that the
 		     giv will be properly split in the main loop above.  */
@@ -3091,11 +3029,6 @@ find_splittable_givs (loop, bl, unroll_t
 	  int count = 1;
 	  if (! v->ignore)
 	    count = ivs->reg_biv_class[REGNO (v->src_reg)]->biv_count;
-
-	  if (count > 1 && v->derived_from)
-	     /* In this case, there is one set where the giv insn was and one
-		set each after each biv increment.  (Most are likely dead.)  */
-	    count++;
 
 	  splittable_regs_updates[REGNO (v->new_reg)] = count;
 	}



More information about the Gcc-patches mailing list