[killloop] Make loop-iv.c use df.c

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Tue Aug 30 09:39:00 GMT 2005


Hello,

loop-iv.c used very primitive version of UD chains.  Now that
performance problems of df.c are more or less solved, this is just
a bad design and limits usefulness of loop-iv.c.  This patch makes
the rtl iv analysis use df.c instead.

Zdenek

	* cfgloop.h (struct rtx_iv): Remove analysed field.  Added biv_p field.
	(iv_get_reaching_def): Removed.
	(iv_analyze_result, iv_analyze_expr): Declare.
	& df.c (df_bitmaps_free, df_bb_modify): Only work on the specified part
	of cfg.
	(df_find_use): Handle subregs.
	* Makefile.in (loop-iv.o): Add DF_H dependency.
	* loop-iv.c: Include df.h.
	(enum iv_grd_result): New enum.
	(DF_REF_IV, DF_REF_IV_SET): New macros.
	(df): New global variable.
	(struct insn_info, insn_info, last_def, bivs, max_insn_no, max_reg_no,
	assign_luids, mark_sets, kill_sets, mark_single_set, simple_set_p):
	Removed.
	(clear_iv_info, latch_dominating_def, record_iv, iv_analyze_expr,
	iv_analyze_result, iv_analyze_def): New functions.
	(iv_analysis_loop_init, iv_get_reaching_def, simple_reg_p,
	get_biv_step_1, get_biv_step, iv_analyze_biv, iv_analyze_op,
	iv_analyze, biv_p, iv_analysis_done): Work with df representation of
	UD chains.
	(iv_constant, iv_subreg, iv_extend, iv_mult, iv_shift): Initialize
	biv_p, do not set analysed.
	(iv_number_of_iterations): Use new interface to iv analysis.
	* loop-unroll.c (analyze_iv_to_split_insn): Ditto.
	* loop-unswitch.c (may_unswitch_on): Ditto.
	

Index: cfgloop.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloop.h,v
retrieving revision 1.48
diff -c -3 -p -r1.48 cfgloop.h
*** cfgloop.h	25 Jun 2005 01:59:29 -0000	1.48
--- cfgloop.h	30 Aug 2005 09:02:00 -0000
*************** struct rtx_iv
*** 350,360 ****
    /* The mode the variable iterates in.  */
    enum machine_mode mode;
  
-   /* Whether we have already filled the remaining fields.  */
-   unsigned analysed : 1;
- 
    /* Whether the first iteration needs to be handled specially.  */
    unsigned first_special : 1;
  };
  
  /* The description of an exit from the loop and of the number of iterations
--- 350,360 ----
    /* The mode the variable iterates in.  */
    enum machine_mode mode;
  
    /* Whether the first iteration needs to be handled specially.  */
    unsigned first_special : 1;
+ 
+   /* True if this is a biv.  */
+   unsigned biv_p : 1;
  };
  
  /* The description of an exit from the loop and of the number of iterations
*************** struct niter_desc
*** 402,409 ****
  };
  
  extern void iv_analysis_loop_init (struct loop *);
- extern rtx iv_get_reaching_def (rtx, rtx);
  extern bool iv_analyze (rtx, rtx, struct rtx_iv *);
  extern rtx get_iv_value (struct rtx_iv *, rtx);
  extern bool biv_p (rtx, rtx);
  extern void find_simple_exit (struct loop *, struct niter_desc *);
--- 402,410 ----
  };
  
  extern void iv_analysis_loop_init (struct loop *);
  extern bool iv_analyze (rtx, rtx, struct rtx_iv *);
+ extern bool iv_analyze_result (rtx, rtx, struct rtx_iv *);
+ extern bool iv_analyze_expr (rtx, rtx, enum machine_mode, struct rtx_iv *);
  extern rtx get_iv_value (struct rtx_iv *, rtx);
  extern bool biv_p (rtx, rtx);
  extern void find_simple_exit (struct loop *, struct niter_desc *);
Index: df.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/df.c,v
retrieving revision 1.86.2.1
diff -c -3 -p -r1.86.2.1 df.c
*** df.c	30 Aug 2005 07:42:24 -0000	1.86.2.1
--- df.c	30 Aug 2005 09:02:00 -0000
*************** df_bitmaps_alloc (struct df *df, bitmap 
*** 451,464 ****
  static void
  df_bitmaps_free (struct df *df, int flags)
  {
!   basic_block bb;
! 
!   FOR_EACH_BB (bb)
      {
!       struct bb_info *bb_info = DF_BB_INFO (df, bb);
! 
!       if (!bb_info)
! 	continue;
  
        if ((flags & DF_RD) && bb_info->rd_in)
  	{
--- 451,461 ----
  static void
  df_bitmaps_free (struct df *df, int flags)
  {
!   unsigned i;
!       
!   for (i = 0; i < df->n_bbs; i++)
      {
!       struct bb_info *bb_info = &df->bbs[i];
  
        if ((flags & DF_RD) && bb_info->rd_in)
  	{
*************** static void
*** 2648,2654 ****
  df_bb_modify (struct df *df, basic_block bb)
  {
    if ((unsigned) bb->index >= df->n_bbs)
!     df_bb_table_realloc (df, df->n_bbs);
  
    bitmap_set_bit (df->bbs_modified, bb->index);
  }
--- 2645,2651 ----
  df_bb_modify (struct df *df, basic_block bb)
  {
    if ((unsigned) bb->index >= df->n_bbs)
!     df_bb_table_realloc (df, bb->index);
  
    bitmap_set_bit (df->bbs_modified, bb->index);
  }
*************** df_find_use (struct df *df, rtx insn, rt
*** 3060,3067 ****
    struct df_link *uses;
  
    for (uses = DF_INSN_USES (df, insn); uses; uses = uses->next)
!     if (rtx_equal_p (DF_REF_REG (uses->ref), reg))
!       return uses->ref;
  
    return NULL;
  }
--- 3057,3070 ----
    struct df_link *uses;
  
    for (uses = DF_INSN_USES (df, insn); uses; uses = uses->next)
!     {
!       rtx areg = DF_REF_REG (uses->ref);
!       if (GET_CODE (areg) == SUBREG)
! 	areg = SUBREG_REG (areg);
! 
!       if (rtx_equal_p (areg, reg))
! 	return uses->ref;
!     }
  
    return NULL;
  }
Index: loop-iv.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-iv.c,v
retrieving revision 2.35
diff -c -3 -p -r2.35 loop-iv.c
*** loop-iv.c	21 Jul 2005 07:24:07 -0000	2.35
--- loop-iv.c	30 Aug 2005 09:02:00 -0000
*************** along with GCC; see the file COPYING.  I
*** 18,47 ****
  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.  */
  
! /* This is just a very simplistic analysis of induction variables of the loop.
!    The major use is for determining the number of iterations of a loop for
!    loop unrolling, doloop optimization and branch prediction.  For this we
!    are only interested in bivs and a fairly limited set of givs that are
!    needed in the exit condition.  We also only compute the iv information on
!    demand.
! 
!    The interesting registers are determined.  A register is interesting if
! 
!    -- it is set only in the blocks that dominate the latch of the current loop
!    -- all its sets are simple -- i.e. in the form we understand
! 
!    We also number the insns sequentially in each basic block.  For a use of the
!    interesting reg, it is now easy to find a reaching definition (there may be
!    only one).
  
!    Induction variable is then simply analyzed by walking the use-def
!    chains.
     
!    Usage:
  
     iv_analysis_loop_init (loop);
!    insn = iv_get_reaching_def (where, reg);
!    if (iv_analyze (insn, reg, &iv))
       {
         ...
       }
--- 18,34 ----
  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.  */
  
! /* This is a simple analysis of induction variables of the loop.  The major use
!    is for determining the number of iterations of a loop for loop unrolling,
!    doloop optimization and branch prediction.  The iv information is computed
!    on demand.
  
!    Induction variable is analyzed by walking the use-def chains.
     
!    Usage (REG must be used in WHERE):
  
     iv_analysis_loop_init (loop);
!    if (iv_analyze (where, reg, &iv))
       {
         ...
       }
*************** Software Foundation, 51 Franklin Street,
*** 60,99 ****
  #include "intl.h"
  #include "output.h"
  #include "toplev.h"
  
! /* The insn information.  */
  
! struct insn_info
  {
!   /* Id of the insn.  */
!   unsigned luid;
  
!   /* The previous definition of the register defined by the single
!      set in the insn.  */
!   rtx prev_def;
  
!   /* The description of the iv.  */
!   struct rtx_iv iv;
! };
! 
! static struct insn_info *insn_info;
  
! /* The last definition of register.  */
! 
! static rtx *last_def;
  
! /* The bivs.  */
  
! static struct rtx_iv *bivs;
  
! /* Maximal insn number for that there is place in insn_info array.  */
  
! static unsigned max_insn_no;
  
! /* Maximal register number for that there is place in bivs and last_def
!    arrays.  */
  
! static unsigned max_reg_no;
  
  /* Dumps information about IV to FILE.  */
  
--- 47,87 ----
  #include "intl.h"
  #include "output.h"
  #include "toplev.h"
+ #include "df.h"
  
! /* Possible return values of iv_get_reaching_def.  */
  
! enum iv_grd_result
  {
!   /* More than one reaching def, or reaching def that does not
!      dominate the use.  */
!   GRD_INVALID,
  
!   /* The use is trivial invariant of the loop, i.e. is not changed
!      inside the loop.  */
!   GRD_INVARIANT,
  
!   /* The use is reached by initial value and a value from the
!      previous iteration.  */
!   GRD_MAYBE_BIV,
  
!   /* The use has single dominating def.  */
!   GRD_SINGLE_DOM
! };
  
! /* Induction variable stored at the reference.  */
! #define DF_REF_IV(REF) ((struct rtx_iv *) DF_REF_DATA (REF))
! #define DF_REF_IV_SET(REF, IV) DF_REF_DATA (REF) = (IV)
  
! /* The current loop.  */
  
! struct loop *current_loop;
  
! /* Dataflow information for the current loop.  */
  
! struct df *df;
  
! static bool iv_analyze_op (rtx, rtx, struct rtx_iv *);
  
  /* Dumps information about IV to FILE.  */
  
*************** dump_iv_info (FILE *file, struct rtx_iv 
*** 139,161 ****
      fprintf (file, " (first special)");
  }
  
- /* Assigns luids to insns in basic block BB.  */
- 
- static void
- assign_luids (basic_block bb)
- {
-   unsigned i = 0, uid;
-   rtx insn;
- 
-   FOR_BB_INSNS (bb, insn)
-     {
-       uid = INSN_UID (insn);
-       insn_info[uid].luid = i++;
-       insn_info[uid].prev_def = NULL_RTX;
-       insn_info[uid].iv.analysed = false;
-     }
- }
- 
  /* Generates a subreg to get the least significant part of EXPR (in mode
     INNER_MODE) to OUTER_MODE.  */
  
--- 127,132 ----
*************** simple_reg_p (rtx reg)
*** 191,419 ****
    if (GET_MODE_CLASS (GET_MODE (reg)) != MODE_INT)
      return false;
  
-   if (last_def[r] == const0_rtx)
-     return false;
- 
    return true;
  }
  
! /* Checks whether assignment LHS = RHS is simple enough for us to process.  */
  
! static bool
! simple_set_p (rtx lhs, rtx rhs)
  {
!   rtx op0, op1;
! 
!   if (!REG_P (lhs)
!       || !simple_reg_p (lhs))
!     return false;
! 
!   if (CONSTANT_P (rhs))
!     return true;
  
!   switch (GET_CODE (rhs))
      {
!     case SUBREG:
!     case REG:
!       return simple_reg_p (rhs);
! 
!     case SIGN_EXTEND:
!     case ZERO_EXTEND:
!     case NEG:
!       return simple_reg_p (XEXP (rhs, 0));
! 
!     case PLUS:
!     case MINUS:
!     case MULT:
!     case ASHIFT:
!       op0 = XEXP (rhs, 0);
!       op1 = XEXP (rhs, 1);
! 
!       if (!simple_reg_p (op0)
! 	  && !CONSTANT_P (op0))
! 	return false;
! 
!       if (!simple_reg_p (op1)
! 	  && !CONSTANT_P (op1))
! 	return false;
! 
!       if (GET_CODE (rhs) == MULT
! 	  && !CONSTANT_P (op0)
! 	  && !CONSTANT_P (op1))
! 	return false;
! 
!       if (GET_CODE (rhs) == ASHIFT
! 	  && CONSTANT_P (op0))
! 	return false;
! 
!       return true;
  
!     default:
!       return false;
      }
  }
  
! /* Mark single SET in INSN.  */
! 
! static rtx
! mark_single_set (rtx insn, rtx set)
! {
!   rtx def = SET_DEST (set), src;
!   unsigned regno, uid;
! 
!   src = find_reg_equal_equiv_note (insn);
!   if (src)
!     src = XEXP (src, 0);
!   else
!     src = SET_SRC (set);
! 
!   if (!simple_set_p (SET_DEST (set), src))
!     return NULL_RTX;
! 
!   regno = REGNO (def);
!   uid = INSN_UID (insn);
! 
!   bivs[regno].analysed = false;
!   insn_info[uid].prev_def = last_def[regno];
!   last_def[regno] = insn;
! 
!   return def;
! }
! 
! /* Invalidate register REG unless it is equal to EXCEPT.  */
  
! static void
! kill_sets (rtx reg, rtx by ATTRIBUTE_UNUSED, void *except)
  {
!   if (GET_CODE (reg) == SUBREG)
!     reg = SUBREG_REG (reg);
!   if (!REG_P (reg))
!     return;
!   if (reg == except)
!     return;
! 
!   last_def[REGNO (reg)] = const0_rtx;
! }
  
! /* Marks sets in basic block BB.  If DOM is true, BB dominates the loop
!    latch.  */
  
! static void
! mark_sets (basic_block bb, bool dom)
! {
!   rtx insn, set, def;
  
!   FOR_BB_INSNS (bb, insn)
      {
!       if (!INSN_P (insn))
! 	continue;
  
!       if (dom
! 	  && (set = single_set (insn)))
! 	def = mark_single_set (insn, set);
!       else
! 	def = NULL_RTX;
  
!       note_stores (PATTERN (insn), kill_sets, def);
      }
  }
  
! /* Prepare the data for an induction variable analysis of a LOOP.  */
  
! void
! iv_analysis_loop_init (struct loop *loop)
  {
!   basic_block *body = get_loop_body_in_dom_order (loop);
!   unsigned b;
  
!   if ((unsigned) get_max_uid () >= max_insn_no)
      {
!       /* Add some reserve for insns and registers produced in optimizations.  */
!       max_insn_no = get_max_uid () + 100;
!       if (insn_info)
! 	free (insn_info);
!       insn_info = xmalloc (max_insn_no * sizeof (struct insn_info));
!     }
  
!   if ((unsigned) max_reg_num () >= max_reg_no)
!     {
!       max_reg_no = max_reg_num () + 100;
!       if (last_def)
! 	free (last_def);
!       last_def = xmalloc (max_reg_no * sizeof (rtx));
!       if (bivs)
! 	free (bivs);
!       bivs = xmalloc (max_reg_no * sizeof (struct rtx_iv));
!     }
  
!   memset (last_def, 0, max_reg_num () * sizeof (rtx));
  
!   for (b = 0; b < loop->num_nodes; b++)
!     {
!       assign_luids (body[b]);
!       mark_sets (body[b], just_once_each_iteration_p (loop, body[b]));
      }
  
!   free (body);
  }
  
! /* Gets definition of REG reaching the INSN.  If REG is not simple, const0_rtx
!    is returned.  If INSN is before the first def in the loop, NULL_RTX is
!    returned.  */
  
! rtx
! iv_get_reaching_def (rtx insn, rtx reg)
  {
!   unsigned regno, luid, auid;
!   rtx ainsn;
!   basic_block bb, abb;
! 
    if (GET_CODE (reg) == SUBREG)
!     {
!       if (!subreg_lowpart_p (reg))
! 	return const0_rtx;
!       reg = SUBREG_REG (reg);
!     }
!   if (!REG_P (reg))
!     return NULL_RTX;
  
!   regno = REGNO (reg);
!   if (!last_def[regno]
!       || last_def[regno] == const0_rtx)
!     return last_def[regno];
  
!   bb = BLOCK_FOR_INSN (insn);
!   luid = insn_info[INSN_UID (insn)].luid;
  
!   ainsn = last_def[regno];
!   while (1)
!     {
!       abb = BLOCK_FOR_INSN (ainsn);
  
!       if (dominated_by_p (CDI_DOMINATORS, bb, abb))
! 	break;
  
!       auid = INSN_UID (ainsn);
!       ainsn = insn_info[auid].prev_def;
! 
!       if (!ainsn)
! 	return NULL_RTX;
!     }
  
!   while (1)
      {
!       abb = BLOCK_FOR_INSN (ainsn);
!       if (abb != bb)
! 	return ainsn;
! 
!       auid = INSN_UID (ainsn);
!       if (luid > insn_info[auid].luid)
! 	return ainsn;
! 
!       ainsn = insn_info[auid].prev_def;
!       if (!ainsn)
! 	return NULL_RTX;
      }
  }
  
  /* Sets IV to invariant CST in MODE.  Always returns true (just for
--- 162,315 ----
    if (GET_MODE_CLASS (GET_MODE (reg)) != MODE_INT)
      return false;
  
    return true;
  }
  
! /* Clears the information about ivs stored in df.  */
  
! static void
! clear_iv_info (void)
  {
!   unsigned i;
!   struct rtx_iv *iv;
  
!   for (i = 0; i < df->n_defs; i++)
      {
!       if (!df->defs[i])
! 	continue;
  
!       iv = DF_REF_IV (df->defs[i]);
!       if (!iv)
! 	continue;
!       free (iv);
!       DF_REF_IV_SET (df->defs[i], NULL);
      }
  }
  
! /* Prepare the data for an induction variable analysis of a LOOP.  */
  
! void
! iv_analysis_loop_init (struct loop *loop)
  {
!   basic_block *body = get_loop_body_in_dom_order (loop), bb;
!   bitmap blocks = BITMAP_ALLOC (NULL);
!   unsigned i;
!   rtx insn;
!   bool first_time = (df == NULL);
  
!   current_loop = loop;
  
!   /* Clear the information from the analysis of the previous loop.  */
!   if (first_time)
!     df = df_init ();
!   else
!     clear_iv_info ();
  
!   for (i = 0; i < loop->num_nodes; i++)
      {
!       bb = body[i];
!       bitmap_set_bit (blocks, bb->index);
  
!       if (first_time)
! 	continue;
  
!       /* Mark everything in the body of the loop as modified, since this may be
! 	 the case, and we do not keep track of what changes.  */
!       FOR_BB_INSNS (bb, insn)
! 	{
! 	  df_insn_modify (df, bb, insn);
! 	}
      }
+ 
+   df_analyze_subcfg (df, blocks, DF_UD_CHAIN | DF_EQUIV_NOTES);
+   BITMAP_FREE (blocks);
+   free (body);
  }
  
! /* Finds the definition of REG that dominates loop latch and stores
!    it to DEF.  Returns false if there is not a single definition
!    dominating the latch.  If REG has no definition in loop, DEF
!    is set to NULL and true is returned.  */
  
! static bool
! latch_dominating_def (rtx reg, struct ref **def)
  {
!   struct ref *single_rd = NULL, *adef;
!   struct df_link *def_link;
!   unsigned regno = REGNO (reg);
!   struct bb_info *bb_info = DF_BB_INFO (df, current_loop->latch);
  
!   for (def_link = df->regs[regno].defs; def_link; def_link = def_link->next)
      {
!       adef = def_link->ref;
  
!       if (!bitmap_bit_p (bb_info->rd_out, DF_REF_ID (adef)))
! 	continue;
  
!       /* More than one reaching definition.  */
!       if (single_rd)
! 	return false;
  
!       if (!just_once_each_iteration_p (current_loop, DF_REF_BB (adef)))
! 	return false;
! 
!       single_rd = adef;
      }
  
!   *def = single_rd;
!   return true;
  }
  
! /* Gets definition of REG reaching its use in INSN and stores it to DEF.  */
  
! static enum iv_grd_result
! iv_get_reaching_def (rtx insn, rtx reg, struct ref **def)
  {
!   struct ref *use, *adef;
!   basic_block def_bb, use_bb;
!   rtx def_insn;
!   bool dom_p;
!   
!   *def = NULL;
!   if (!simple_reg_p (reg))
!     return GRD_INVALID;
    if (GET_CODE (reg) == SUBREG)
!     reg = SUBREG_REG (reg);
!   gcc_assert (REG_P (reg));
  
!   use = df_find_use (df, insn, reg);
!   gcc_assert (use != NULL);
  
!   if (!DF_REF_CHAIN (use))
!     return GRD_INVARIANT;
  
!   /* More than one reaching def.  */
!   if (DF_REF_CHAIN (use)->next)
!     return GRD_INVALID;
  
!   adef = DF_REF_CHAIN (use)->ref;
!   def_insn = DF_REF_INSN (adef);
!   def_bb = DF_REF_BB (adef);
!   use_bb = BLOCK_FOR_INSN (insn);
  
!   if (use_bb == def_bb)
!     dom_p = (DF_INSN_LUID (df, def_insn) < DF_INSN_LUID (df, insn));
!   else
!     dom_p = dominated_by_p (CDI_DOMINATORS, use_bb, def_bb);
  
!   if (dom_p)
      {
!       *def = adef;
!       return GRD_SINGLE_DOM;
      }
+ 
+   /* The definition does not dominate the use.  This is still OK if
+      this may be a use of a biv, i.e. if the def_bb dominates loop
+      latch.  */
+   if (just_once_each_iteration_p (current_loop, def_bb))
+     return GRD_MAYBE_BIV;
+ 
+   return GRD_INVALID;
  }
  
  /* Sets IV to invariant CST in MODE.  Always returns true (just for
*************** iv_constant (struct rtx_iv *iv, rtx cst,
*** 425,431 ****
    if (mode == VOIDmode)
      mode = GET_MODE (cst);
  
-   iv->analysed = true;
    iv->mode = mode;
    iv->base = cst;
    iv->step = const0_rtx;
--- 321,326 ----
*************** iv_constant (struct rtx_iv *iv, rtx cst,
*** 434,439 ****
--- 329,335 ----
    iv->extend_mode = iv->mode;
    iv->delta = const0_rtx;
    iv->mult = const1_rtx;
+   iv->biv_p = false;
  
    return true;
  }
*************** iv_constant (struct rtx_iv *iv, rtx cst,
*** 443,448 ****
--- 339,346 ----
  static bool
  iv_subreg (struct rtx_iv *iv, enum machine_mode mode)
  {
+   iv->biv_p = false;
+ 
    /* If iv is invariant, just calculate the new value.  */
    if (iv->step == const0_rtx
        && !iv->first_special)
*************** iv_subreg (struct rtx_iv *iv, enum machi
*** 483,488 ****
--- 381,388 ----
  static bool
  iv_extend (struct rtx_iv *iv, enum rtx_code extend, enum machine_mode mode)
  {
+   iv->biv_p = false;
+ 
    /* If iv is invariant, just calculate the new value.  */
    if (iv->step == const0_rtx
        && !iv->first_special)
*************** iv_extend (struct rtx_iv *iv, enum rtx_c
*** 515,520 ****
--- 415,422 ----
  static bool
  iv_neg (struct rtx_iv *iv)
  {
+   iv->biv_p = false;
+ 
    if (iv->extend == UNKNOWN)
      {
        iv->base = simplify_gen_unary (NEG, iv->extend_mode,
*************** iv_add (struct rtx_iv *iv0, struct rtx_i
*** 541,546 ****
--- 443,450 ----
    enum machine_mode mode;
    rtx arg;
  
+   iv0->biv_p = false;
+ 
    /* Extend the constant to extend_mode of the other operand if necessary.  */
    if (iv0->extend == UNKNOWN
        && iv0->mode == iv0->extend_mode
*************** iv_mult (struct rtx_iv *iv, rtx mby)
*** 609,614 ****
--- 513,520 ----
  {
    enum machine_mode mode = iv->extend_mode;
  
+   iv->biv_p = false;
+ 
    if (GET_MODE (mby) != VOIDmode
        && GET_MODE (mby) != mode)
      return false;
*************** iv_shift (struct rtx_iv *iv, rtx mby)
*** 634,639 ****
--- 540,547 ----
  {
    enum machine_mode mode = iv->extend_mode;
  
+   iv->biv_p = false;
+ 
    if (GET_MODE (mby) != VOIDmode
        && GET_MODE (mby) != mode)
      return false;
*************** iv_shift (struct rtx_iv *iv, rtx mby)
*** 653,672 ****
  }
  
  /* The recursive part of get_biv_step.  Gets the value of the single value
!    defined in INSN wrto initial value of REG inside loop, in shape described
     at get_biv_step.  */
  
  static bool
! get_biv_step_1 (rtx insn, rtx reg,
  		rtx *inner_step, enum machine_mode *inner_mode,
  		enum rtx_code *extend, enum machine_mode outer_mode,
  		rtx *outer_step)
  {
    rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX;
!   rtx next, nextr, def_insn, tmp;
    enum rtx_code code;
  
    set = single_set (insn);
    rhs = find_reg_equal_equiv_note (insn);
    if (rhs)
      rhs = XEXP (rhs, 0);
--- 561,586 ----
  }
  
  /* The recursive part of get_biv_step.  Gets the value of the single value
!    defined by DEF wrto initial value of REG inside loop, in shape described
     at get_biv_step.  */
  
  static bool
! get_biv_step_1 (struct ref *def, rtx reg,
  		rtx *inner_step, enum machine_mode *inner_mode,
  		enum rtx_code *extend, enum machine_mode outer_mode,
  		rtx *outer_step)
  {
    rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX;
!   rtx next, nextr, tmp;
    enum rtx_code code;
+   rtx insn = DF_REF_INSN (def);
+   struct ref *next_def;
+   enum iv_grd_result res;
  
    set = single_set (insn);
+   if (!set)
+     return false;
+ 
    rhs = find_reg_equal_equiv_note (insn);
    if (rhs)
      rhs = XEXP (rhs, 0);
*************** get_biv_step_1 (rtx insn, rtx reg,
*** 742,752 ****
    else
      nextr = next;
  
!   def_insn = iv_get_reaching_def (insn, nextr);
!   if (def_insn == const0_rtx)
      return false;
  
!   if (!def_insn)
      {
        if (!rtx_equal_p (nextr, reg))
  	return false;
--- 656,667 ----
    else
      nextr = next;
  
!   res = iv_get_reaching_def (insn, nextr, &next_def);
! 
!   if (res == GRD_INVALID || res == GRD_INVARIANT)
      return false;
  
!   if (res == GRD_MAYBE_BIV)
      {
        if (!rtx_equal_p (nextr, reg))
  	return false;
*************** get_biv_step_1 (rtx insn, rtx reg,
*** 756,762 ****
        *inner_mode = outer_mode;
        *outer_step = const0_rtx;
      }
!   else if (!get_biv_step_1 (def_insn, reg,
  			    inner_step, inner_mode, extend, outer_mode,
  			    outer_step))
      return false;
--- 671,677 ----
        *inner_mode = outer_mode;
        *outer_step = const0_rtx;
      }
!   else if (!get_biv_step_1 (next_def, reg,
  			    inner_step, inner_mode, extend, outer_mode,
  			    outer_step))
      return false;
*************** get_biv_step_1 (rtx insn, rtx reg,
*** 803,809 ****
        break;
  
      default:
!       gcc_unreachable ();
      }
  
    return true;
--- 718,724 ----
        break;
  
      default:
!       return false;
      }
  
    return true;
*************** get_biv_step_1 (rtx insn, rtx reg,
*** 813,828 ****
  
     OUTER_STEP + EXTEND_{OUTER_MODE} (SUBREG_{INNER_MODE} (REG + INNER_STEP))
  
!    If the operation cannot be described in this shape, return false.  */
  
  static bool
! get_biv_step (rtx reg, rtx *inner_step, enum machine_mode *inner_mode,
! 	      enum rtx_code *extend, enum machine_mode *outer_mode,
! 	      rtx *outer_step)
  {
    *outer_mode = GET_MODE (reg);
  
!   if (!get_biv_step_1 (last_def[REGNO (reg)], reg,
  		       inner_step, inner_mode, extend, *outer_mode,
  		       outer_step))
      return false;
--- 728,744 ----
  
     OUTER_STEP + EXTEND_{OUTER_MODE} (SUBREG_{INNER_MODE} (REG + INNER_STEP))
  
!    If the operation cannot be described in this shape, return false.
!    LAST_DEF is the definition of REG that dominates loop latch.  */
  
  static bool
! get_biv_step (struct ref *last_def, rtx reg, rtx *inner_step,
! 	      enum machine_mode *inner_mode, enum rtx_code *extend,
! 	      enum machine_mode *outer_mode, rtx *outer_step)
  {
    *outer_mode = GET_MODE (reg);
  
!   if (!get_biv_step_1 (last_def, reg,
  		       inner_step, inner_mode, extend, *outer_mode,
  		       outer_step))
      return false;
*************** get_biv_step (rtx reg, rtx *inner_step, 
*** 833,848 ****
    return true;
  }
  
  /* Determines whether DEF is a biv and if so, stores its description
     to *IV.  */
  
  static bool
  iv_analyze_biv (rtx def, struct rtx_iv *iv)
  {
-   unsigned regno;
    rtx inner_step, outer_step;
    enum machine_mode inner_mode, outer_mode;
    enum rtx_code extend;
  
    if (dump_file)
      {
--- 749,775 ----
    return true;
  }
  
+ /* Records information that DEF is induction variable IV.  */
+ 
+ static void
+ record_iv (struct ref *def, struct rtx_iv *iv)
+ {
+   struct rtx_iv *recorded_iv = xmalloc (sizeof (struct rtx_iv));
+ 
+   *recorded_iv = *iv;
+   DF_REF_IV_SET (def, recorded_iv);
+ }
+ 
  /* Determines whether DEF is a biv and if so, stores its description
     to *IV.  */
  
  static bool
  iv_analyze_biv (rtx def, struct rtx_iv *iv)
  {
    rtx inner_step, outer_step;
    enum machine_mode inner_mode, outer_mode;
    enum rtx_code extend;
+   struct ref *last_def;
  
    if (dump_file)
      {
*************** iv_analyze_biv (rtx def, struct rtx_iv *
*** 859,889 ****
        return iv_constant (iv, def, VOIDmode);
      }
  
!   regno = REGNO (def);
!   if (last_def[regno] == const0_rtx)
      {
        if (dump_file)
  	fprintf (dump_file, "  not simple.\n");
        return false;
      }
  
!   if (last_def[regno] && bivs[regno].analysed)
      {
        if (dump_file)
  	fprintf (dump_file, "  already analysed.\n");
  
!       *iv = bivs[regno];
        return iv->base != NULL_RTX;
      }
  
!   if (!last_def[regno])
!     {
!       iv_constant (iv, def, VOIDmode);
!       goto end;
!     }
! 
!   iv->analysed = true;
!   if (!get_biv_step (def, &inner_step, &inner_mode, &extend,
  		     &outer_mode, &outer_step))
      {
        iv->base = NULL_RTX;
--- 786,811 ----
        return iv_constant (iv, def, VOIDmode);
      }
  
!   if (!latch_dominating_def (def, &last_def))
      {
        if (dump_file)
  	fprintf (dump_file, "  not simple.\n");
        return false;
      }
  
!   if (!last_def)
!     return iv_constant (iv, def, VOIDmode);
! 
!   if (DF_REF_IV (last_def))
      {
        if (dump_file)
  	fprintf (dump_file, "  already analysed.\n");
  
!       *iv = *DF_REF_IV (last_def);
        return iv->base != NULL_RTX;
      }
  
!   if (!get_biv_step (last_def, def, &inner_step, &inner_mode, &extend,
  		     &outer_mode, &outer_step))
      {
        iv->base = NULL_RTX;
*************** iv_analyze_biv (rtx def, struct rtx_iv *
*** 904,909 ****
--- 826,832 ----
    iv->mult = const1_rtx;
    iv->delta = outer_step;
    iv->first_special = inner_mode != outer_mode;
+   iv->biv_p = true;
  
   end:
    if (dump_file)
*************** iv_analyze_biv (rtx def, struct rtx_iv *
*** 913,1031 ****
        fprintf (dump_file, "\n");
      }
  
!   bivs[regno] = *iv;
! 
    return iv->base != NULL_RTX;
  }
  
! /* Analyzes operand OP of INSN and stores the result to *IV.  */
  
! static bool
! iv_analyze_op (rtx insn, rtx op, struct rtx_iv *iv)
  {
!   rtx def_insn;
!   unsigned regno;
!   bool inv = CONSTANT_P (op);
! 
!   if (dump_file)
!     {
!       fprintf (dump_file, "Analyzing operand ");
!       print_rtl (dump_file, op);
!       fprintf (dump_file, " of insn ");
!       print_rtl_single (dump_file, insn);
!     }
! 
!   if (GET_CODE (op) == SUBREG)
!     {
!       if (!subreg_lowpart_p (op))
! 	return false;
  
!       if (!iv_analyze_op (insn, SUBREG_REG (op), iv))
! 	return false;
  
!       return iv_subreg (iv, GET_MODE (op));
!     }
  
!   if (!inv)
      {
!       regno = REGNO (op);
!       if (!last_def[regno])
! 	inv = true;
!       else if (last_def[regno] == const0_rtx)
  	{
! 	  if (dump_file)
! 	    fprintf (dump_file, "  not simple.\n");
! 	  return false;
  	}
      }
  
!   if (inv)
      {
!       iv_constant (iv, op, VOIDmode);
  
!       if (dump_file)
  	{
! 	  fprintf (dump_file, "  ");
! 	  dump_iv_info (dump_file, iv);
! 	  fprintf (dump_file, "\n");
  	}
!       return true;
!     }
  
!   def_insn = iv_get_reaching_def (insn, op);
!   if (def_insn == const0_rtx)
!     {
!       if (dump_file)
! 	fprintf (dump_file, "  not simple.\n");
        return false;
      }
  
!   return iv_analyze (def_insn, op, iv);
! }
! 
! /* Analyzes iv DEF defined in INSN and stores the result to *IV.  */
! 
! bool
! iv_analyze (rtx insn, rtx def, struct rtx_iv *iv)
! {
!   unsigned uid;
!   rtx set, rhs, mby = NULL_RTX, tmp;
!   rtx op0 = NULL_RTX, op1 = NULL_RTX;
!   struct rtx_iv iv0, iv1;
!   enum machine_mode amode;
!   enum rtx_code code;
  
!   if (insn == const0_rtx)
      return false;
  
!   if (GET_CODE (def) == SUBREG)
      {
!       if (!subreg_lowpart_p (def))
  	return false;
  
!       if (!iv_analyze (insn, SUBREG_REG (def), iv))
  	return false;
  
!       return iv_subreg (iv, GET_MODE (def));
      }
  
!   if (!insn)
!     return iv_analyze_biv (def, iv);
  
    if (dump_file)
      {
!       fprintf (dump_file, "Analyzing def of ");
!       print_rtl (dump_file, def);
        fprintf (dump_file, " in insn ");
        print_rtl_single (dump_file, insn);
      }
  
!   uid = INSN_UID (insn);
!   if (insn_info[uid].iv.analysed)
      {
        if (dump_file)
  	fprintf (dump_file, "  already analysed.\n");
!       *iv = insn_info[uid].iv;
        return iv->base != NULL_RTX;
      }
  
--- 836,990 ----
        fprintf (dump_file, "\n");
      }
  
!   record_iv (last_def, iv);
    return iv->base != NULL_RTX;
  }
  
! /* Analyzes expression RHS used at INSN and stores the result to *IV. 
!    The mode of the induction variable is MODE.  */
  
! bool
! iv_analyze_expr (rtx insn, rtx rhs, enum machine_mode mode, struct rtx_iv *iv)
  {
!   rtx mby = NULL_RTX, tmp;
!   rtx op0 = NULL_RTX, op1 = NULL_RTX;
!   struct rtx_iv iv0, iv1;
!   enum rtx_code code = GET_CODE (rhs);
!   enum machine_mode omode = mode;
  
!   iv->mode = VOIDmode;
!   iv->base = NULL_RTX;
!   iv->step = NULL_RTX;
  
!   gcc_assert (GET_MODE (rhs) == mode || GET_MODE (rhs) == VOIDmode);
  
!   if (CONSTANT_P (rhs)
!       || REG_P (rhs)
!       || code == SUBREG)
      {
!       if (!iv_analyze_op (insn, rhs, iv))
! 	return false;
! 	
!       if (iv->mode == VOIDmode)
  	{
! 	  iv->mode = mode;
! 	  iv->extend_mode = mode;
  	}
+ 
+       return true;
      }
  
!   switch (code)
      {
!     case REG:
!       op0 = rhs;
!       break;
  
!     case SIGN_EXTEND:
!     case ZERO_EXTEND:
!     case NEG:
!       op0 = XEXP (rhs, 0);
!       omode = GET_MODE (op0);
!       break;
! 
!     case PLUS:
!     case MINUS:
!       op0 = XEXP (rhs, 0);
!       op1 = XEXP (rhs, 1);
!       break;
! 
!     case MULT:
!       op0 = XEXP (rhs, 0);
!       mby = XEXP (rhs, 1);
!       if (!CONSTANT_P (mby))
  	{
! 	  tmp = op0;
! 	  op0 = mby;
! 	  mby = tmp;
  	}
!       if (!CONSTANT_P (mby))
! 	return false;
!       break;
  
!     case ASHIFT:
!       op0 = XEXP (rhs, 0);
!       mby = XEXP (rhs, 1);
!       if (!CONSTANT_P (mby))
! 	return false;
!       break;
! 
!     default:
        return false;
      }
  
!   if (op0
!       && !iv_analyze_expr (insn, op0, omode, &iv0))
!     return false;
  
!   if (op1
!       && !iv_analyze_expr (insn, op1, omode, &iv1))
      return false;
  
!   switch (code)
      {
!     case SIGN_EXTEND:
!     case ZERO_EXTEND:
!       if (!iv_extend (&iv0, code, mode))
  	return false;
+       break;
  
!     case NEG:
!       if (!iv_neg (&iv0))
  	return false;
+       break;
+ 
+     case PLUS:
+     case MINUS:
+       if (!iv_add (&iv0, &iv1, code))
+ 	return false;
+       break;
+ 
+     case MULT:
+       if (!iv_mult (&iv0, mby))
+ 	return false;
+       break;
  
!     case ASHIFT:
!       if (!iv_shift (&iv0, mby))
! 	return false;
!       break;
! 
!     default:
!       iv0.biv_p = false;
!       break;
      }
  
!   *iv = iv0;
!   return iv->base != NULL_RTX;
! }
! 
! /* Analyzes iv DEF and stores the result to *IV.  */
! 
! static bool
! iv_analyze_def (struct ref *def, struct rtx_iv *iv)
! {
!   rtx insn = DF_REF_INSN (def);
!   rtx reg = DF_REF_REG (def);
!   rtx set, rhs;
  
    if (dump_file)
      {
!       fprintf (dump_file, "Analysing def of ");
!       print_rtl (dump_file, reg);
        fprintf (dump_file, " in insn ");
        print_rtl_single (dump_file, insn);
      }
  
!   if (DF_REF_IV (def))
      {
        if (dump_file)
  	fprintf (dump_file, "  already analysed.\n");
!       *iv = *DF_REF_IV (def);
        return iv->base != NULL_RTX;
      }
  
*************** iv_analyze (rtx insn, rtx def, struct rt
*** 1034,1179 ****
    iv->step = NULL_RTX;
  
    set = single_set (insn);
    rhs = find_reg_equal_equiv_note (insn);
    if (rhs)
      rhs = XEXP (rhs, 0);
    else
      rhs = SET_SRC (set);
-   code = GET_CODE (rhs);
  
!   if (CONSTANT_P (rhs))
      {
!       op0 = rhs;
!       amode = GET_MODE (def);
      }
-   else
-     {
-       switch (code)
- 	{
- 	case SUBREG:
- 	  if (!subreg_lowpart_p (rhs))
- 	    goto end;
- 	  op0 = rhs;
- 	  break;
- 	  
- 	case REG:
- 	  op0 = rhs;
- 	  break;
  
! 	case SIGN_EXTEND:
! 	case ZERO_EXTEND:
! 	case NEG:
! 	  op0 = XEXP (rhs, 0);
! 	  break;
  
! 	case PLUS:
! 	case MINUS:
! 	  op0 = XEXP (rhs, 0);
! 	  op1 = XEXP (rhs, 1);
! 	  break;
  
! 	case MULT:
! 	  op0 = XEXP (rhs, 0);
! 	  mby = XEXP (rhs, 1);
! 	  if (!CONSTANT_P (mby))
! 	    {
! 	      gcc_assert (CONSTANT_P (op0));
! 	      tmp = op0;
! 	      op0 = mby;
! 	      mby = tmp;
! 	    }
! 	  break;
  
! 	case ASHIFT:
! 	  gcc_assert (!CONSTANT_P (XEXP (rhs, 0)));
! 	  op0 = XEXP (rhs, 0);
! 	  mby = XEXP (rhs, 1);
! 	  break;
  
! 	default:
! 	  gcc_unreachable ();
! 	}
  
!       amode = GET_MODE (rhs);
!     }
  
!   if (op0)
      {
!       if (!iv_analyze_op (insn, op0, &iv0))
! 	goto end;
! 	
!       if (iv0.mode == VOIDmode)
  	{
! 	  iv0.mode = amode;
! 	  iv0.extend_mode = amode;
  	}
      }
  
!   if (op1)
      {
!       if (!iv_analyze_op (insn, op1, &iv1))
! 	goto end;
  
!       if (iv1.mode == VOIDmode)
  	{
! 	  iv1.mode = amode;
! 	  iv1.extend_mode = amode;
  	}
      }
  
!   switch (code)
!     {
!     case SIGN_EXTEND:
!     case ZERO_EXTEND:
!       if (!iv_extend (&iv0, code, amode))
! 	goto end;
!       break;
  
!     case NEG:
!       if (!iv_neg (&iv0))
! 	goto end;
!       break;
  
!     case PLUS:
!     case MINUS:
!       if (!iv_add (&iv0, &iv1, code))
! 	goto end;
!       break;
  
!     case MULT:
!       if (!iv_mult (&iv0, mby))
! 	goto end;
!       break;
  
!     case ASHIFT:
!       if (!iv_shift (&iv0, mby))
! 	goto end;
!       break;
  
!     default:
!       break;
      }
  
!   *iv = iv0;
  
!  end:
!   iv->analysed = true;
!   insn_info[uid].iv = *iv;
  
!   if (dump_file)
!     {
!       print_rtl (dump_file, def);
!       fprintf (dump_file, " in insn ");
!       print_rtl_single (dump_file, insn);
!       fprintf (dump_file, "  is ");
!       dump_iv_info (dump_file, iv);
!       fprintf (dump_file, "\n");
!     }
  
!   return iv->base != NULL_RTX;
  }
  
! /* Checks whether definition of register REG in INSN a basic induction
     variable.  IV analysis must have been initialized (via a call to
     iv_analysis_loop_init) for this function to produce a result.  */
  
--- 993,1121 ----
    iv->step = NULL_RTX;
  
    set = single_set (insn);
+   if (!set || SET_DEST (set) != reg)
+     return false;
+ 
    rhs = find_reg_equal_equiv_note (insn);
    if (rhs)
      rhs = XEXP (rhs, 0);
    else
      rhs = SET_SRC (set);
  
!   iv_analyze_expr (insn, rhs, GET_MODE (reg), iv);
!   record_iv (def, iv);
! 
!   if (dump_file)
      {
!       print_rtl (dump_file, reg);
!       fprintf (dump_file, " in insn ");
!       print_rtl_single (dump_file, insn);
!       fprintf (dump_file, "  is ");
!       dump_iv_info (dump_file, iv);
!       fprintf (dump_file, "\n");
      }
  
!   return iv->base != NULL_RTX;
! }
  
! /* Analyzes operand OP of INSN and stores the result to *IV.  */
  
! static bool
! iv_analyze_op (rtx insn, rtx op, struct rtx_iv *iv)
! {
!   struct ref *def = NULL;
!   enum iv_grd_result res;
  
!   if (dump_file)
!     {
!       fprintf (dump_file, "Analysing operand ");
!       print_rtl (dump_file, op);
!       fprintf (dump_file, " of insn ");
!       print_rtl_single (dump_file, insn);
!     }
  
!   if (CONSTANT_P (op))
!     res = GRD_INVARIANT;
!   else if (GET_CODE (op) == SUBREG)
!     {
!       if (!subreg_lowpart_p (op))
! 	return false;
  
!       if (!iv_analyze_op (insn, SUBREG_REG (op), iv))
! 	return false;
  
!       return iv_subreg (iv, GET_MODE (op));
!     }
!   else
      {
!       res = iv_get_reaching_def (insn, op, &def);
!       if (res == GRD_INVALID)
  	{
! 	  if (dump_file)
! 	    fprintf (dump_file, "  not simple.\n");
! 	  return false;
  	}
      }
  
!   if (res == GRD_INVARIANT)
      {
!       iv_constant (iv, op, VOIDmode);
  
!       if (dump_file)
  	{
! 	  fprintf (dump_file, "  ");
! 	  dump_iv_info (dump_file, iv);
! 	  fprintf (dump_file, "\n");
  	}
+       return true;
      }
  
!   if (res == GRD_MAYBE_BIV)
!     return iv_analyze_biv (op, iv);
  
!   return iv_analyze_def (def, iv);
! }
  
! /* Analyzes value VAL at INSN and stores the result to *IV.  */
  
! bool
! iv_analyze (rtx insn, rtx val, struct rtx_iv *iv)
! {
!   rtx reg;
  
!   /* We must find the insn in that val is used, so that we get to UD chains.
!      Since the function is sometimes called on result of get_condition,
!      this does not necessarily have to be directly INSN; scan also the
!      following insns.  */
!   if (simple_reg_p (val))
!     {
!       if (GET_CODE (val) == SUBREG)
! 	reg = SUBREG_REG (val);
!       else
! 	reg = val;
  
!       while (!df_find_use (df, insn, reg))
! 	insn = NEXT_INSN (insn);
      }
  
!   return iv_analyze_op (insn, val, iv);
! }
  
! /* Analyzes definition of DEF in INSN and stores the result to IV.  */
  
! bool
! iv_analyze_result (rtx insn, rtx def, struct rtx_iv *iv)
! {
!   struct ref *adef;
  
!   adef = df_find_def (df, insn, def);
!   if (!adef)
!     return false;
! 
!   return iv_analyze_def (adef, iv);
  }
  
! /* Checks whether definition of register REG in INSN is a basic induction
     variable.  IV analysis must have been initialized (via a call to
     iv_analysis_loop_init) for this function to produce a result.  */
  
*************** bool
*** 1181,1194 ****
  biv_p (rtx insn, rtx reg)
  {
    struct rtx_iv iv;
  
!   if (!REG_P (reg))
      return false;
  
!   if (last_def[REGNO (reg)] != insn)
      return false;
  
!   return iv_analyze_biv (reg, &iv);
  }
  
  /* Calculates value of IV at ITERATION-th iteration.  */
--- 1123,1144 ----
  biv_p (rtx insn, rtx reg)
  {
    struct rtx_iv iv;
+   struct ref *def, *last_def;
  
!   if (!simple_reg_p (reg))
      return false;
  
!   def = df_find_def (df, insn, reg);
!   gcc_assert (def != NULL);
!   if (!latch_dominating_def (reg, &last_def))
!     return false;
!   if (last_def != def)
      return false;
  
!   if (!iv_analyze_biv (reg, &iv))
!     return false;
! 
!   return iv.biv_p;
  }
  
  /* Calculates value of IV at ITERATION-th iteration.  */
*************** get_iv_value (struct rtx_iv *iv, rtx ite
*** 1230,1251 ****
  void
  iv_analysis_done (void)
  {
!   max_insn_no = 0;
!   max_reg_no = 0;
!   if (insn_info)
!     {
!       free (insn_info);
!       insn_info = NULL;
!     }
!   if (last_def)
!     {
!       free (last_def);
!       last_def = NULL;
!     }
!   if (bivs)
      {
!       free (bivs);
!       bivs = NULL;
      }
  }
  
--- 1180,1190 ----
  void
  iv_analysis_done (void)
  {
!   if (df)
      {
!       clear_iv_info ();
!       df_finish (df);
!       df = NULL;
      }
  }
  
*************** static void
*** 1996,2002 ****
  iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
  			 struct niter_desc *desc)
  {
!   rtx op0, op1, delta, step, bound, may_xform, def_insn, tmp, tmp0, tmp1;
    struct rtx_iv iv0, iv1, tmp_iv;
    rtx assumption, may_not_xform;
    enum rtx_code cond;
--- 1935,1941 ----
  iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
  			 struct niter_desc *desc)
  {
!   rtx op0, op1, delta, step, bound, may_xform, tmp, tmp0, tmp1;
    struct rtx_iv iv0, iv1, tmp_iv;
    rtx assumption, may_not_xform;
    enum rtx_code cond;
*************** iv_number_of_iterations (struct loop *lo
*** 2038,2052 ****
      goto fail;
  
    op0 = XEXP (condition, 0);
!   def_insn = iv_get_reaching_def (insn, op0);
!   if (!iv_analyze (def_insn, op0, &iv0))
      goto fail;
    if (iv0.extend_mode == VOIDmode)
      iv0.mode = iv0.extend_mode = mode;
    
    op1 = XEXP (condition, 1);
!   def_insn = iv_get_reaching_def (insn, op1);
!   if (!iv_analyze (def_insn, op1, &iv1))
      goto fail;
    if (iv1.extend_mode == VOIDmode)
      iv1.mode = iv1.extend_mode = mode;
--- 1977,1989 ----
      goto fail;
  
    op0 = XEXP (condition, 0);
!   if (!iv_analyze (insn, op0, &iv0))
      goto fail;
    if (iv0.extend_mode == VOIDmode)
      iv0.mode = iv0.extend_mode = mode;
    
    op1 = XEXP (condition, 1);
!   if (!iv_analyze (insn, op1, &iv1))
      goto fail;
    if (iv1.extend_mode == VOIDmode)
      iv1.mode = iv1.extend_mode = mode;
Index: loop-unroll.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-unroll.c,v
retrieving revision 1.36
diff -c -3 -p -r1.36 loop-unroll.c
*** loop-unroll.c	25 Jun 2005 02:00:35 -0000	1.36
--- loop-unroll.c	30 Aug 2005 09:02:01 -0000
*************** analyze_iv_to_split_insn (rtx insn)
*** 1657,1663 ****
    if (!biv_p (insn, dest))
      return NULL;
  
!   ok = iv_analyze (insn, dest, &iv);
    gcc_assert (ok);
  
    if (iv.step == const0_rtx
--- 1666,1672 ----
    if (!biv_p (insn, dest))
      return NULL;
  
!   ok = iv_analyze_result (insn, dest, &iv);
    gcc_assert (ok);
  
    if (iv.step == const0_rtx
Index: loop-unswitch.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-unswitch.c,v
retrieving revision 1.32
diff -c -3 -p -r1.32 loop-unswitch.c
*** loop-unswitch.c	25 Jun 2005 02:00:36 -0000	1.32
--- loop-unswitch.c	30 Aug 2005 09:02:01 -0000
*************** unswitch_loops (struct loops *loops)
*** 172,178 ****
  static rtx
  may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
  {
!   rtx test, at, insn, op[2], stest;
    struct rtx_iv iv;
    unsigned i;
    enum machine_mode mode;
--- 172,178 ----
  static rtx
  may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
  {
!   rtx test, at, op[2], stest;
    struct rtx_iv iv;
    unsigned i;
    enum machine_mode mode;
*************** may_unswitch_on (basic_block bb, struct 
*** 205,212 ****
        if (CONSTANT_P (op[i]))
  	continue;
  
!       insn = iv_get_reaching_def (at, op[i]);
!       if (!iv_analyze (insn, op[i], &iv))
  	return NULL_RTX;
        if (iv.step != const0_rtx
  	  || iv.first_special)
--- 205,211 ----
        if (CONSTANT_P (op[i]))
  	continue;
  
!       if (!iv_analyze (at, op[i], &iv))
  	return NULL_RTX;
        if (iv.step != const0_rtx
  	  || iv.first_special)
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1530.2.1
diff -c -3 -p -r1.1530.2.1 Makefile.in
*** Makefile.in	30 Aug 2005 07:42:22 -0000	1.1530.2.1
--- Makefile.in	30 Aug 2005 09:10:12 -0000
*************** cfgloopanal.o : cfgloopanal.c $(CONFIG_H
*** 2295,2301 ****
     $(OBSTACK_H) output.h
  loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(BASIC_BLOCK_H) \
     hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H) \
!    output.h intl.h
  loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
     $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h \
     $(TM_H) function.h $(FLAGS_H) $(DF_H) $(OBSTACK_H) output.h \
--- 2295,2301 ----
     $(OBSTACK_H) output.h
  loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(BASIC_BLOCK_H) \
     hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H) \
!    output.h intl.h $(DF_H)
  loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
     $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h \
     $(TM_H) function.h $(FLAGS_H) $(DF_H) $(OBSTACK_H) output.h \



More information about the Gcc-patches mailing list