OSDN Git Service

PR tree-optimization/20773
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop-ivopts.c
index eb53945..fda17f9 100644 (file)
@@ -15,8 +15,8 @@ for more details.
    
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /* This pass tries to find the optimal set of induction variables for the loop.
    It optimizes just the basic linear induction variables (although adding
@@ -358,7 +358,7 @@ loop_data (struct loop *loop)
 
 /* The single loop exit if it dominates the latch, NULL otherwise.  */
 
-static edge
+edge
 single_dom_exit (struct loop *loop)
 {
   edge exit = loop->single_exit;
@@ -712,7 +712,8 @@ niter_for_exit (struct ivopts_data *data, edge exit)
       nfe_desc = xmalloc (sizeof (struct nfe_cache_elt));
       nfe_desc->exit = exit;
       nfe_desc->valid_p = number_of_iterations_exit (data->current_loop,
-                                                    exit, &nfe_desc->niter);
+                                                    exit, &nfe_desc->niter,
+                                                    true);
       *slot = nfe_desc;
     }
   else
@@ -791,7 +792,8 @@ determine_base_object (tree expr)
       if (TREE_CODE (base) == INDIRECT_REF)
        return determine_base_object (TREE_OPERAND (base, 0));
 
-      return fold (build1 (ADDR_EXPR, ptr_type_node, base));
+      return fold_convert (ptr_type_node,
+                          build_fold_addr_expr (base));
 
     case PLUS_EXPR:
     case MINUS_EXPR:
@@ -804,9 +806,9 @@ determine_base_object (tree expr)
       if (!op0)
        return (code == PLUS_EXPR
                ? op1
-               : fold (build1 (NEGATE_EXPR, ptr_type_node, op1)));
+               : fold_build1 (NEGATE_EXPR, ptr_type_node, op1));
 
-      return fold (build (code, ptr_type_node, op0, op1));
+      return fold_build2 (code, ptr_type_node, op0, op1);
 
     case NOP_EXPR:
     case CONVERT_EXPR:
@@ -992,6 +994,7 @@ find_bivs (struct ivopts_data *data)
        continue;
 
       base = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
+      base = expand_simple_operations (base);
       if (contains_abnormal_ssa_name_p (base)
          || contains_abnormal_ssa_name_p (step))
        continue;
@@ -1062,6 +1065,7 @@ find_givs_in_stmt_scev (struct ivopts_data *data, tree stmt,
 
   if (!simple_iv (loop, stmt, TREE_OPERAND (stmt, 1), base, step, true))
     return false;
+  *base = expand_simple_operations (*base);
 
   if (contains_abnormal_ssa_name_p (*base)
       || contains_abnormal_ssa_name_p (*step))
@@ -1386,7 +1390,7 @@ idx_find_step (tree base, tree *idx, void *data)
 {
   struct ifs_ivopts_data *dta = data;
   struct iv *iv;
-  tree step, type, iv_type, iv_step, lbound, off;
+  tree step, iv_step, lbound, off;
   struct loop *loop = dta->ivopts_data->current_loop;
 
   if (TREE_CODE (base) == MISALIGNED_INDIRECT_REF
@@ -1427,8 +1431,6 @@ idx_find_step (tree base, tree *idx, void *data)
   if (!iv->step)
     return true;
 
-  iv_type = TREE_TYPE (iv->base);
-  type = build_pointer_type (TREE_TYPE (base));
   if (TREE_CODE (base) == ARRAY_REF)
     {
       step = array_ref_element_size (base);
@@ -1439,13 +1441,10 @@ idx_find_step (tree base, tree *idx, void *data)
     }
   else
     /* The step for pointer arithmetics already is 1 byte.  */
-    step = build_int_cst (type, 1);
+    step = build_int_cst (sizetype, 1);
 
-  if (TYPE_PRECISION (iv_type) < TYPE_PRECISION (type))
-    iv_step = can_count_iv_in_wider_type (dta->ivopts_data->current_loop,
-                                         type, iv->base, iv->step, dta->stmt);
-  else
-    iv_step = fold_convert (iv_type, iv->step);
+  iv_step = convert_step (dta->ivopts_data->current_loop,
+                         sizetype, iv->base, iv->step, dta->stmt);
 
   if (!iv_step)
     {
@@ -1453,12 +1452,12 @@ idx_find_step (tree base, tree *idx, void *data)
       return false;
     }
 
-  step = fold_build2 (MULT_EXPR, type, step, iv_step);
+  step = fold_build2 (MULT_EXPR, sizetype, step, iv_step);
 
   if (!*dta->step_p)
     *dta->step_p = step;
   else
-    *dta->step_p = fold_build2 (PLUS_EXPR, type, *dta->step_p, step);
+    *dta->step_p = fold_build2 (PLUS_EXPR, sizetype, *dta->step_p, step);
 
   return true;
 }
@@ -1493,6 +1492,11 @@ may_be_unaligned_p (tree ref)
   int unsignedp, volatilep;
   unsigned base_align;
 
+  /* TARGET_MEM_REFs are translated directly to valid MEMs on the target,
+     thus they are not misaligned.  */
+  if (TREE_CODE (ref) == TARGET_MEM_REF)
+    return false;
+
   /* The test below is basically copy of what expr.c:normal_inner_ref
      does to check whether the object must be loaded by parts when
      STRICT_ALIGNMENT is true.  */
@@ -1510,31 +1514,12 @@ may_be_unaligned_p (tree ref)
   return false;
 }
 
-/* Builds ADDR_EXPR of object OBJ.  If OBJ is an INDIRECT_REF, the indirect_ref
-   is stripped instead.  */
-
-static tree
-build_addr_strip_iref (tree obj)
-{
-  tree type;
-
-  if (TREE_CODE (obj) == INDIRECT_REF)
-    {
-      type = build_pointer_type (TREE_TYPE (obj));
-      obj = fold_convert (type, TREE_OPERAND (obj, 0));
-    }
-  else
-    obj = build_addr (obj);
-
-  return obj;
-}
-
 /* Finds addresses in *OP_P inside STMT.  */
 
 static void
 find_interesting_uses_address (struct ivopts_data *data, tree stmt, tree *op_p)
 {
-  tree base = unshare_expr (*op_p), step = NULL;
+  tree base = *op_p, step = NULL;
   struct iv *civ;
   struct ifs_ivopts_data ifs_ivopts_data;
 
@@ -1553,17 +1538,63 @@ find_interesting_uses_address (struct ivopts_data *data, tree stmt, tree *op_p)
       && may_be_unaligned_p (base))
     goto fail;
 
-  ifs_ivopts_data.ivopts_data = data;
-  ifs_ivopts_data.stmt = stmt;
-  ifs_ivopts_data.step_p = &step;
-  if (!for_each_index (&base, idx_find_step, &ifs_ivopts_data)
-      || zero_p (step))
-    goto fail;
+  base = unshare_expr (base);
 
-  gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
-  gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
+  if (TREE_CODE (base) == TARGET_MEM_REF)
+    {
+      tree type = build_pointer_type (TREE_TYPE (base));
+      tree astep;
 
-  base = build_addr_strip_iref (base);
+      if (TMR_BASE (base)
+         && TREE_CODE (TMR_BASE (base)) == SSA_NAME)
+       {
+         civ = get_iv (data, TMR_BASE (base));
+         if (!civ)
+           goto fail;
+
+         TMR_BASE (base) = civ->base;
+         step = civ->step;
+       }
+      if (TMR_INDEX (base)
+         && TREE_CODE (TMR_INDEX (base)) == SSA_NAME)
+       {
+         civ = get_iv (data, TMR_INDEX (base));
+         if (!civ)
+           goto fail;
+
+         TMR_INDEX (base) = civ->base;
+         astep = civ->step;
+
+         if (astep)
+           {
+             if (TMR_STEP (base))
+               astep = fold_build2 (MULT_EXPR, type, TMR_STEP (base), astep);
+
+             if (step)
+               step = fold_build2 (PLUS_EXPR, type, step, astep);
+             else
+               step = astep;
+           }
+       }
+
+      if (zero_p (step))
+       goto fail;
+      base = tree_mem_ref_addr (type, base);
+    }
+  else
+    {
+      ifs_ivopts_data.ivopts_data = data;
+      ifs_ivopts_data.stmt = stmt;
+      ifs_ivopts_data.step_p = &step;
+      if (!for_each_index (&base, idx_find_step, &ifs_ivopts_data)
+         || zero_p (step))
+       goto fail;
+
+      gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
+      gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
+
+      base = build_fold_addr_expr (base);
+    }
 
   civ = alloc_iv (base, step);
   record_use (data, op_p, civ, stmt, USE_ADDRESS);
@@ -1578,25 +1609,13 @@ fail:
 static void
 find_invariants_stmt (struct ivopts_data *data, tree stmt)
 {
-  use_optype uses = NULL;
-  unsigned i, n;
+  ssa_op_iter iter;
+  use_operand_p use_p;
   tree op;
 
-  if (TREE_CODE (stmt) == PHI_NODE)
-    n = PHI_NUM_ARGS (stmt);
-  else
+  FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
     {
-      uses = STMT_USE_OPS (stmt);
-      n = NUM_USES (uses);
-    }
-
-  for (i = 0; i < n; i++)
-    {
-      if (TREE_CODE (stmt) == PHI_NODE)
-       op = PHI_ARG_DEF (stmt, i);
-      else
-       op = USE_OP (uses, i);
-
+      op = USE_FROM_PTR (use_p);
       record_invariant (data, op, false);
     }
 }
@@ -1608,8 +1627,8 @@ find_interesting_uses_stmt (struct ivopts_data *data, tree stmt)
 {
   struct iv *iv;
   tree op, lhs, rhs;
-  use_optype uses = NULL;
-  unsigned i, n;
+  ssa_op_iter iter;
+  use_operand_p use_p;
 
   find_invariants_stmt (data, stmt);
 
@@ -1677,20 +1696,9 @@ find_interesting_uses_stmt (struct ivopts_data *data, tree stmt)
        return;
     }
 
-  if (TREE_CODE (stmt) == PHI_NODE)
-    n = PHI_NUM_ARGS (stmt);
-  else
-    {
-      uses = STMT_USE_OPS (stmt);
-      n = NUM_USES (uses);
-    }
-
-  for (i = 0; i < n; i++)
+  FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
     {
-      if (TREE_CODE (stmt) == PHI_NODE)
-       op = PHI_ARG_DEF (stmt, i);
-      else
-       op = USE_OP (uses, i);
+      op = USE_FROM_PTR (use_p);
 
       if (TREE_CODE (op) != SSA_NAME)
        continue;
@@ -1879,7 +1887,7 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
       if (op0 == TREE_OPERAND (expr, 0))
        return orig_expr;
 
-      expr = build_addr_strip_iref (op0);
+      expr = build_fold_addr_expr (op0);
       return fold_convert (orig_type, expr);
 
     case INDIRECT_REF:
@@ -1906,7 +1914,7 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
     TREE_OPERAND (expr, 1) = op1;
 
   /* Inside address, we might strip the top level component references,
-     thus changing type of the expresion.  Handling of ADDR_EXPR
+     thus changing type of the expression.  Handling of ADDR_EXPR
      will fix that.  */
   expr = fold_convert (orig_type, expr);
 
@@ -2559,7 +2567,7 @@ var_at_stmt (struct loop *loop, struct iv_cand *cand, tree stmt)
 /* Return the most significant (sign) bit of T.  Similar to tree_int_cst_msb,
    but the bit is determined from TYPE_PRECISION, not MODE_BITSIZE.  */
 
-static int
+int
 tree_int_cst_sign_bit (tree t)
 {
   unsigned bitno = TYPE_PRECISION (TREE_TYPE (t)) - 1;
@@ -2655,33 +2663,6 @@ constant_multiple_of (tree type, tree top, tree bot)
     }
 }
 
-/* Affine combination of trees.  We keep track of at most MAX_AFF_ELTS elements
-   to make things simpler; this is sufficient in most cases.  */
-
-#define MAX_AFF_ELTS 8
-
-struct affine_tree_combination
-{
-  /* Type of the result of the combination.  */
-  tree type;
-
-  /* Mask modulo that the operations are performed.  */
-  unsigned HOST_WIDE_INT mask;
-
-  /* Constant offset.  */
-  unsigned HOST_WIDE_INT offset;
-
-  /* Number of elements of the combination.  */
-  unsigned n;
-
-  /* Elements and their coefficients.  */
-  tree elts[MAX_AFF_ELTS];
-  unsigned HOST_WIDE_INT coefs[MAX_AFF_ELTS];
-
-  /* Remainder of the expression.  */
-  tree rest;
-};
-
 /* Sets COMB to CST.  */
 
 static void
@@ -2867,7 +2848,7 @@ tree_to_aff_combination (tree expr, tree type,
       if (bitpos % BITS_PER_UNIT != 0)
        break;
       aff_combination_const (comb, type, bitpos / BITS_PER_UNIT);
-      core = build_addr_strip_iref (core);
+      core = build_fold_addr_expr (core);
       if (TREE_CODE (core) == ADDR_EXPR)
        aff_combination_add_elt (comb, core, 1);
       else
@@ -2934,6 +2915,19 @@ add_elt_to_tree (tree expr, tree type, tree elt, unsigned HOST_WIDE_INT scale,
   return fold_build2 (code, type, expr, elt);
 }
 
+/* Copies the tree elements of COMB to ensure that they are not shared.  */
+
+static void
+unshare_aff_combination (struct affine_tree_combination *comb)
+{
+  unsigned i;
+
+  for (i = 0; i < comb->n; i++)
+    comb->elts[i] = unshare_expr (comb->elts[i]);
+  if (comb->rest)
+    comb->rest = unshare_expr (comb->rest);
+}
+
 /* Makes tree from the affine combination COMB.  */
 
 static tree
@@ -2944,6 +2938,11 @@ aff_combination_to_tree (struct affine_tree_combination *comb)
   unsigned i;
   unsigned HOST_WIDE_INT off, sgn;
 
+  /* Handle the special case produced by get_computation_aff when
+     the type does not fit in HOST_WIDE_INT.  */
+  if (comb->n == 0 && comb->offset == 0)
+    return fold_convert (type, expr);
+
   gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE);
 
   for (i = 0; i < comb->n; i++)
@@ -2965,49 +2964,14 @@ aff_combination_to_tree (struct affine_tree_combination *comb)
                          comb->mask);
 }
 
-/* Folds X + RATIO * Y in TYPE.  */
-
-static tree
-fold_affine_sum (tree type, tree x, tree y, HOST_WIDE_INT ratio)
-{
-  enum tree_code code;
-  tree cst;
-  struct affine_tree_combination cx, cy;
-
-  if (TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT)
-    {
-      if (ratio == 1)
-       return fold_build2 (PLUS_EXPR, type, x, y);
-      if (ratio == -1)
-       return fold_build2 (MINUS_EXPR, type, x, y);
-
-      if (ratio < 0)
-       {
-         code = MINUS_EXPR;
-         ratio = -ratio;
-       }
-      else
-       code = PLUS_EXPR;
-
-      cst = build_int_cst_type (type, ratio);
-      y = fold_build2 (MULT_EXPR, type, y, cst);
-      return fold_build2 (code, type, x, y);
-    }
-
-  tree_to_aff_combination (x, type, &cx);
-  tree_to_aff_combination (y, type, &cy);
-  aff_combination_scale (&cy, ratio);
-  aff_combination_add (&cx, &cy);
-
-  return aff_combination_to_tree (&cx);
-}
-
 /* Determines the expression by that USE is expressed from induction variable
-   CAND at statement AT in LOOP.  */
+   CAND at statement AT in LOOP.  The expression is stored in a decomposed
+   form into AFF.  Returns false if USE cannot be expressed using CAND.  */
 
-static tree
-get_computation_at (struct loop *loop,
-                   struct iv_use *use, struct iv_cand *cand, tree at)
+static bool
+get_computation_aff (struct loop *loop,
+                    struct iv_use *use, struct iv_cand *cand, tree at,
+                    struct affine_tree_combination *aff)
 {
   tree ubase = use->iv->base;
   tree ustep = use->iv->step;
@@ -3019,11 +2983,13 @@ get_computation_at (struct loop *loop,
   tree ratio;
   unsigned HOST_WIDE_INT ustepi, cstepi;
   HOST_WIDE_INT ratioi;
+  struct affine_tree_combination cbase_aff, expr_aff;
+  tree cstep_orig = cstep, ustep_orig = ustep;
 
   if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype))
     {
       /* We do not have a precision to express the values of use.  */
-      return NULL_TREE;
+      return false;
     }
 
   expr = var_at_stmt (loop, cand, at);
@@ -3048,29 +3014,34 @@ get_computation_at (struct loop *loop,
       expr = fold_convert (uutype, expr);
       cbase = fold_convert (uutype, cbase);
       cstep = fold_convert (uutype, cstep);
+
+      /* If the conversion is not noop, we must take it into account when
+        considering the value of the step.  */
+      if (TYPE_PRECISION (utype) < TYPE_PRECISION (ctype))
+       cstep_orig = cstep;
     }
 
-  if (cst_and_fits_in_hwi (cstep)
-      && cst_and_fits_in_hwi (ustep))
+  if (cst_and_fits_in_hwi (cstep_orig)
+      && cst_and_fits_in_hwi (ustep_orig))
     {
-      ustepi = int_cst_value (ustep);
-      cstepi = int_cst_value (cstep);
+      ustepi = int_cst_value (ustep_orig);
+      cstepi = int_cst_value (cstep_orig);
 
       if (!divide (TYPE_PRECISION (uutype), ustepi, cstepi, &ratioi))
        {
          /* TODO maybe consider case when ustep divides cstep and the ratio is
             a power of 2 (so that the division is fast to execute)?  We would
             need to be much more careful with overflows etc. then.  */
-         return NULL_TREE;
+         return false;
        }
 
       ratio = build_int_cst_type (uutype, ratioi);
     }
   else
     {
-      ratio = constant_multiple_of (uutype, ustep, cstep);
+      ratio = constant_multiple_of (uutype, ustep_orig, cstep_orig);
       if (!ratio)
-       return NULL_TREE;
+       return false;
 
       /* Ratioi is only used to detect special cases when the multiplicative
         factor is 1 or -1, so if we cannot convert ratio to HOST_WIDE_INT,
@@ -3089,7 +3060,7 @@ get_computation_at (struct loop *loop,
 
   /* We may need to shift the value if we are after the increment.  */
   if (stmt_after_increment (loop, cand, at))
-    cbase = fold (build2 (PLUS_EXPR, uutype, cbase, cstep));
+    cbase = fold_build2 (PLUS_EXPR, uutype, cbase, cstep);
 
   /* use = ubase - ratio * cbase + ratio * var.
 
@@ -3099,34 +3070,71 @@ get_computation_at (struct loop *loop,
      happen, fold is able to apply the distributive law to obtain this form
      anyway.  */
 
-  if (ratioi == 1)
+  if (TYPE_PRECISION (uutype) > HOST_BITS_PER_WIDE_INT)
     {
-      delta = fold_affine_sum (uutype, ubase, cbase, -1);
-      expr = fold_build2 (PLUS_EXPR, uutype, expr, delta);
-    }
-  else if (ratioi == -1)
-    {
-      delta = fold_affine_sum (uutype, ubase, cbase, 1);
-      expr = fold_build2 (MINUS_EXPR, uutype, delta, expr);
-    }
-  else
-    {
-      if (ratioi)
-       delta = fold_affine_sum (uutype, ubase, cbase, -ratioi);
+      /* Let's compute in trees and just return the result in AFF.  This case
+        should not be very common, and fold itself is not that bad either,
+        so making the aff. functions more complicated to handle this case
+        is not that urgent.  */
+      if (ratioi == 1)
+       {
+         delta = fold_build2 (MINUS_EXPR, uutype, ubase, cbase);
+         expr = fold_build2 (PLUS_EXPR, uutype, expr, delta);
+       }
+      else if (ratioi == -1)
+       {
+         delta = fold_build2 (PLUS_EXPR, uutype, ubase, cbase);
+         expr = fold_build2 (MINUS_EXPR, uutype, delta, expr);
+       }
       else
        {
-         delta = fold_build2 (MULT_EXPR, uutype, ratio, cbase);
-         delta = fold_affine_sum (uutype, ubase, delta, -1);
+         delta = fold_build2 (MULT_EXPR, uutype, cbase, ratio);
+         delta = fold_build2 (MINUS_EXPR, uutype, ubase, delta);
+         expr = fold_build2 (MULT_EXPR, uutype, ratio, expr);
+         expr = fold_build2 (PLUS_EXPR, uutype, delta, expr);
        }
-      expr = fold_build2 (MULT_EXPR, uutype, ratio, expr);
-      expr = fold_build2 (PLUS_EXPR, uutype, delta, expr);
+
+      aff->type = uutype;
+      aff->n = 0;
+      aff->offset = 0;
+      aff->mask = 0;
+      aff->rest = expr;
+      return true;
     }
 
-  return fold_convert (utype, expr);
+  /* If we got here, the types fits in HOST_WIDE_INT, thus it must be
+     possible to compute ratioi.  */
+  gcc_assert (ratioi);
+
+  tree_to_aff_combination (ubase, uutype, aff);
+  tree_to_aff_combination (cbase, uutype, &cbase_aff);
+  tree_to_aff_combination (expr, uutype, &expr_aff);
+  aff_combination_scale (&cbase_aff, -ratioi);
+  aff_combination_scale (&expr_aff, ratioi);
+  aff_combination_add (aff, &cbase_aff);
+  aff_combination_add (aff, &expr_aff);
+
+  return true;
+}
+
+/* Determines the expression by that USE is expressed from induction variable
+   CAND at statement AT in LOOP.  The computation is unshared.  */
+
+static tree
+get_computation_at (struct loop *loop,
+                   struct iv_use *use, struct iv_cand *cand, tree at)
+{
+  struct affine_tree_combination aff;
+  tree type = TREE_TYPE (use->iv->base);
+
+  if (!get_computation_aff (loop, use, cand, at, &aff))
+    return NULL_TREE;
+  unshare_aff_combination (&aff);
+  return fold_convert (type, aff_combination_to_tree (&aff));
 }
 
 /* Determines the expression by that USE is expressed from induction variable
-   CAND in LOOP.  */
+   CAND in LOOP.  The computation is unshared.  */
 
 static tree
 get_computation (struct loop *loop, struct iv_use *use, struct iv_cand *cand)
@@ -3148,8 +3156,8 @@ add_cost (enum machine_mode mode)
 
   start_sequence ();
   force_operand (gen_rtx_fmt_ee (PLUS, mode,
-                                gen_raw_REG (mode, FIRST_PSEUDO_REGISTER),
-                                gen_raw_REG (mode, FIRST_PSEUDO_REGISTER + 1)),
+                                gen_raw_REG (mode, LAST_VIRTUAL_REGISTER + 1),
+                                gen_raw_REG (mode, LAST_VIRTUAL_REGISTER + 2)),
                 NULL_RTX);
   seq = get_insns ();
   end_sequence ();
@@ -3198,7 +3206,7 @@ mbc_entry_eq (const void *entry1, const void *entry2)
 
 /* Returns cost of multiplication by constant CST in MODE.  */
 
-static unsigned
+unsigned
 multiply_by_cost (HOST_WIDE_INT cst, enum machine_mode mode)
 {
   static htab_t costs;
@@ -3220,8 +3228,8 @@ multiply_by_cost (HOST_WIDE_INT cst, enum machine_mode mode)
   (*cached)->cst = cst;
 
   start_sequence ();
-  expand_mult (mode, gen_raw_REG (mode, FIRST_PSEUDO_REGISTER), GEN_INT (cst),
-              NULL_RTX, 0);
+  expand_mult (mode, gen_raw_REG (mode, LAST_VIRTUAL_REGISTER + 1),
+              gen_int_mode (cst, mode), NULL_RTX, 0);
   seq = get_insns ();
   end_sequence ();
   
@@ -3236,6 +3244,47 @@ multiply_by_cost (HOST_WIDE_INT cst, enum machine_mode mode)
   return cost;
 }
 
+/* Returns true if multiplying by RATIO is allowed in address.  */
+
+bool
+multiplier_allowed_in_address_p (HOST_WIDE_INT ratio)
+{
+#define MAX_RATIO 128
+  static sbitmap valid_mult;
+  
+  if (!valid_mult)
+    {
+      rtx reg1 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
+      rtx addr;
+      HOST_WIDE_INT i;
+
+      valid_mult = sbitmap_alloc (2 * MAX_RATIO + 1);
+      sbitmap_zero (valid_mult);
+      addr = gen_rtx_fmt_ee (MULT, Pmode, reg1, NULL_RTX);
+      for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
+       {
+         XEXP (addr, 1) = gen_int_mode (i, Pmode);
+         if (memory_address_p (Pmode, addr))
+           SET_BIT (valid_mult, i + MAX_RATIO);
+       }
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "  allowed multipliers:");
+         for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
+           if (TEST_BIT (valid_mult, i + MAX_RATIO))
+             fprintf (dump_file, " %d", (int) i);
+         fprintf (dump_file, "\n");
+         fprintf (dump_file, "\n");
+       }
+    }
+
+  if (ratio > MAX_RATIO || ratio < -MAX_RATIO)
+    return false;
+
+  return TEST_BIT (valid_mult, ratio + MAX_RATIO);
+}
+
 /* Returns cost of address in shape symbol + var + OFFSET + RATIO * index.
    If SYMBOL_PRESENT is false, symbol is omitted.  If VAR_PRESENT is false,
    variable is omitted.  The created memory accesses MODE.
@@ -3246,8 +3295,7 @@ static unsigned
 get_address_cost (bool symbol_present, bool var_present,
                  unsigned HOST_WIDE_INT offset, HOST_WIDE_INT ratio)
 {
-#define MAX_RATIO 128
-  static sbitmap valid_mult;
+  static bool initialized = false;
   static HOST_WIDE_INT rat, off;
   static HOST_WIDE_INT min_offset, max_offset;
   static unsigned costs[2][2][2][2];
@@ -3259,16 +3307,17 @@ get_address_cost (bool symbol_present, bool var_present,
   unsigned HOST_WIDE_INT mask;
   unsigned bits;
 
-  if (!valid_mult)
+  if (!initialized)
     {
       HOST_WIDE_INT i;
+      initialized = true;
 
-      reg1 = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER);
+      reg1 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
 
       addr = gen_rtx_fmt_ee (PLUS, Pmode, reg1, NULL_RTX);
       for (i = 1; i <= 1 << 20; i <<= 1)
        {
-         XEXP (addr, 1) = GEN_INT (i);
+         XEXP (addr, 1) = gen_int_mode (i, Pmode);
          if (!memory_address_p (Pmode, addr))
            break;
        }
@@ -3277,7 +3326,7 @@ get_address_cost (bool symbol_present, bool var_present,
 
       for (i = 1; i <= 1 << 20; i <<= 1)
        {
-         XEXP (addr, 1) = GEN_INT (-i);
+         XEXP (addr, 1) = gen_int_mode (-i, Pmode);
          if (!memory_address_p (Pmode, addr))
            break;
        }
@@ -3290,29 +3339,13 @@ get_address_cost (bool symbol_present, bool var_present,
          fprintf (dump_file, "  max offset %d\n", (int) max_offset);
        }
 
-      valid_mult = sbitmap_alloc (2 * MAX_RATIO + 1);
-      sbitmap_zero (valid_mult);
       rat = 1;
-      addr = gen_rtx_fmt_ee (MULT, Pmode, reg1, NULL_RTX);
-      for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
-       {
-         XEXP (addr, 1) = GEN_INT (i);
-         if (memory_address_p (Pmode, addr))
-           {
-             SET_BIT (valid_mult, i + MAX_RATIO);
-             rat = i;
-           }
-       }
-
-      if (dump_file && (dump_flags & TDF_DETAILS))
-       {
-         fprintf (dump_file, "  allowed multipliers:");
-         for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
-           if (TEST_BIT (valid_mult, i + MAX_RATIO))
-             fprintf (dump_file, " %d", (int) i);
-         fprintf (dump_file, "\n");
-         fprintf (dump_file, "\n");
-       }
+      for (i = 2; i <= MAX_RATIO; i++)
+       if (multiplier_allowed_in_address_p (i))
+         {
+           rat = i;
+           break;
+         }
     }
 
   bits = GET_MODE_BITSIZE (Pmode);
@@ -3326,8 +3359,7 @@ get_address_cost (bool symbol_present, bool var_present,
   offset_p = (s_offset != 0
              && min_offset <= s_offset && s_offset <= max_offset);
   ratio_p = (ratio != 1
-            && -MAX_RATIO <= ratio && ratio <= MAX_RATIO
-            && TEST_BIT (valid_mult, ratio + MAX_RATIO));
+            && multiplier_allowed_in_address_p (ratio));
 
   if (ratio != 1 && !ratio_p)
     cost += multiply_by_cost (ratio, Pmode);
@@ -3343,10 +3375,10 @@ get_address_cost (bool symbol_present, bool var_present,
     {
       acost = 0;
       
-      addr = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER);
-      reg1 = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER + 1);
+      addr = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
+      reg1 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 2);
       if (ratio_p)
-       addr = gen_rtx_fmt_ee (MULT, Pmode, addr, GEN_INT (rat));
+       addr = gen_rtx_fmt_ee (MULT, Pmode, addr, gen_int_mode (rat, Pmode));
 
       if (var_present)
        addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, reg1);
@@ -3358,10 +3390,10 @@ get_address_cost (bool symbol_present, bool var_present,
            base = gen_rtx_fmt_e (CONST, Pmode,
                                  gen_rtx_fmt_ee (PLUS, Pmode,
                                                  base,
-                                                 GEN_INT (off)));
+                                                 gen_int_mode (off, Pmode)));
        }
       else if (offset_p)
-       base = GEN_INT (off);
+       base = gen_int_mode (off, Pmode);
       else
        base = NULL_RTX;
     
@@ -3888,9 +3920,9 @@ iv_value (struct iv *iv, tree niter)
   tree type = TREE_TYPE (iv->base);
 
   niter = fold_convert (type, niter);
-  val = fold (build2 (MULT_EXPR, type, iv->step, niter));
+  val = fold_build2 (MULT_EXPR, type, iv->step, niter);
 
-  return fold (build2 (PLUS_EXPR, type, iv->base, val));
+  return fold_build2 (PLUS_EXPR, type, iv->base, val);
 }
 
 /* Computes value of candidate CAND at position AT in iteration NITER.  */
@@ -3902,7 +3934,7 @@ cand_value_at (struct loop *loop, struct iv_cand *cand, tree at, tree niter)
   tree type = TREE_TYPE (cand->iv->base);
 
   if (stmt_after_increment (loop, cand, at))
-    val = fold (build2 (PLUS_EXPR, type, val, cand->iv->step));
+    val = fold_build2 (PLUS_EXPR, type, val, cand->iv->step);
 
   return val;
 }
@@ -4001,9 +4033,9 @@ may_eliminate_iv (struct ivopts_data *data,
   else
     wider_type = nit_type;
 
-  if (!integer_nonzerop (fold (build2 (GE_EXPR, boolean_type_node,
-                                      fold_convert (wider_type, period),
-                                      fold_convert (wider_type, nit)))))
+  if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
+                                     fold_convert (wider_type, period),
+                                     fold_convert (wider_type, nit))))
     return false;
 
   *bound = cand_value_at (loop, cand, use->stmt, nit);
@@ -5303,8 +5335,7 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
        return;
     }
 
-  comp = unshare_expr (get_computation (data->current_loop,
-                                       use, cand));
+  comp = get_computation (data->current_loop, use, cand);
   switch (TREE_CODE (use->stmt))
     {
     case PHI_NODE:
@@ -5389,79 +5420,60 @@ unshare_and_remove_ssa_names (tree ref)
   return ref;
 }
 
-/* Rewrites base of memory access OP with expression WITH in statement
-   pointed to by BSI.  */
+/* Extract the alias analysis info for the memory reference REF.  There are
+   several ways how this information may be stored and what precisely is
+   its semantics depending on the type of the reference, but there always is
+   somewhere hidden one _DECL node that is used to determine the set of
+   virtual operands for the reference.  The code below deciphers this jungle
+   and extracts this single useful piece of information.  */
 
-static void
-rewrite_address_base (block_stmt_iterator *bsi, tree *op, tree with)
+static tree
+get_ref_tag (tree ref)
 {
-  tree bvar, var, new_name, copy, name;
-  tree orig;
-
-  var = bvar = get_base_address (*op);
+  tree var = get_base_address (ref);
+  tree tag;
 
-  if (!var || TREE_CODE (with) != SSA_NAME)
-    goto do_rewrite;
+  if (!var)
+    return NULL_TREE;
 
-  gcc_assert (TREE_CODE (var) != ALIGN_INDIRECT_REF);
-  gcc_assert (TREE_CODE (var) != MISALIGNED_INDIRECT_REF);
   if (TREE_CODE (var) == INDIRECT_REF)
     var = TREE_OPERAND (var, 0);
   if (TREE_CODE (var) == SSA_NAME)
     {
-      name = var;
+      if (SSA_NAME_PTR_INFO (var))
+       {
+         tag = SSA_NAME_PTR_INFO (var)->name_mem_tag;
+         if (tag)
+           return tag;
+       }
       var = SSA_NAME_VAR (var);
     }
-  else if (DECL_P (var))
-    name = NULL_TREE;
-  else
-    goto do_rewrite;
-    
-  /* We need to add a memory tag for the variable.  But we do not want
-     to add it to the temporary used for the computations, since this leads
-     to problems in redundancy elimination when there are common parts
-     in two computations referring to the different arrays.  So we copy
-     the variable to a new temporary.  */
-  copy = build2 (MODIFY_EXPR, void_type_node, NULL_TREE, with);
-
-  if (name)
-    new_name = duplicate_ssa_name (name, copy);
-  else
+  if (DECL_P (var))
     {
-      tree tag = var_ann (var)->type_mem_tag;
-      tree new_ptr = create_tmp_var (TREE_TYPE (with), "ruatmp");
-      add_referenced_tmp_var (new_ptr);
+      tag = var_ann (var)->type_mem_tag;
       if (tag)
-       var_ann (new_ptr)->type_mem_tag = tag;
-      else
-       add_type_alias (new_ptr, var);
-      new_name = make_ssa_name (new_ptr, copy);
-    }
-
-  TREE_OPERAND (copy, 0) = new_name;
-  update_stmt (copy);
-  bsi_insert_before (bsi, copy, BSI_SAME_STMT);
-  with = new_name;
+       return tag;
 
-do_rewrite:
-
-  orig = NULL_TREE;
-  gcc_assert (TREE_CODE (*op) != ALIGN_INDIRECT_REF);
-  gcc_assert (TREE_CODE (*op) != MISALIGNED_INDIRECT_REF);
-
-  if (TREE_CODE (*op) == INDIRECT_REF)
-    orig = REF_ORIGINAL (*op);
-  if (!orig)
-    orig = unshare_and_remove_ssa_names (*op);
+      return var;
+    }
 
-  *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
+  return NULL_TREE;
+}
 
-  /* Record the original reference, for purposes of alias analysis.  */
-  REF_ORIGINAL (*op) = orig;
+/* Copies the reference information from OLD_REF to NEW_REF.  */
 
-  /* Virtual operands in the original statement may have to be renamed
-     because of the replacement.  */
-  mark_new_vars_to_rename (bsi_stmt (*bsi));
+static void
+copy_ref_info (tree new_ref, tree old_ref)
+{
+  if (TREE_CODE (old_ref) == TARGET_MEM_REF)
+    copy_mem_ref_info (new_ref, old_ref);
+  else
+    {
+      TMR_TAG (new_ref) = get_ref_tag (old_ref);
+      TMR_ORIGINAL (new_ref) = unshare_and_remove_ssa_names (old_ref);
+    }
 }
 
 /* Rewrites USE (address that is an iv) using candidate CAND.  */
@@ -5470,16 +5482,16 @@ static void
 rewrite_use_address (struct ivopts_data *data,
                     struct iv_use *use, struct iv_cand *cand)
 {
-  tree comp = unshare_expr (get_computation (data->current_loop,
-                                            use, cand));
+  struct affine_tree_combination aff;
   block_stmt_iterator bsi = bsi_for_stmt (use->stmt);
-  tree stmts;
-  tree op = force_gimple_operand (comp, &stmts, true, NULL_TREE);
+  tree ref;
 
-  if (stmts)
-    bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
+  get_computation_aff (data->current_loop, use, cand, use->stmt, &aff);
+  unshare_aff_combination (&aff);
 
-  rewrite_address_base (&bsi, use->op_p, op);
+  ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff);
+  copy_ref_info (ref, *use->op_p);
+  *use->op_p = ref;
 }
 
 /* Rewrites USE (the condition such that one of the arguments is an iv) using
@@ -5516,7 +5528,7 @@ rewrite_use_compare (struct ivopts_data *data,
 
   /* The induction variable elimination failed; just express the original
      giv.  */
-  comp = unshare_expr (get_computation (data->current_loop, use, cand));
+  comp = get_computation (data->current_loop, use, cand);
 
   cond = *use->op_p;
   op_p = &TREE_OPERAND (cond, 0);
@@ -5577,22 +5589,11 @@ protect_loop_closed_ssa_form_use (edge exit, use_operand_p op_p)
 static void
 protect_loop_closed_ssa_form (edge exit, tree stmt)
 {
-  use_optype uses;
-  vuse_optype vuses;
-  v_may_def_optype v_may_defs;
-  unsigned i;
+  ssa_op_iter iter;
+  use_operand_p use_p;
 
-  uses = STMT_USE_OPS (stmt);
-  for (i = 0; i < NUM_USES (uses); i++)
-    protect_loop_closed_ssa_form_use (exit, USE_OP_PTR (uses, i));
-
-  vuses = STMT_VUSE_OPS (stmt);
-  for (i = 0; i < NUM_VUSES (vuses); i++)
-    protect_loop_closed_ssa_form_use (exit, VUSE_OP_PTR (vuses, i));
-
-  v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
-  for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
-    protect_loop_closed_ssa_form_use (exit, V_MAY_DEF_OP_PTR (v_may_defs, i));
+  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+    protect_loop_closed_ssa_form_use (exit, use_p);
 }
 
 /* STMTS compute a value of a phi argument OP on EXIT of a loop.  Arrange things
@@ -5677,13 +5678,12 @@ rewrite_use_outer (struct ivopts_data *data,
       if (!cand->iv)
        {
          struct cost_pair *cp = get_use_iv_cost (data, use, cand);
-         value = cp->value;
+         value = unshare_expr (cp->value);
        }
       else
        value = get_computation_at (data->current_loop,
                                    use, cand, last_stmt (exit->src));
 
-      value = unshare_expr (value);
       op = force_gimple_operand (value, &stmts, true, SSA_NAME_VAR (tgt));
          
       /* If we will preserve the iv anyway and we would need to perform
@@ -5988,25 +5988,5 @@ tree_ssa_iv_optimize (struct loops *loops)
        loop = loop->outer;
     }
 
-  /* FIXME.  IV opts introduces new aliases and call-clobbered
-     variables, which need to be renamed.  However, when we call the
-     renamer, not all statements will be scanned for operands.  In
-     particular, the newly introduced aliases may appear in statements
-     that are considered "unmodified", so the renamer will not get a
-     chance to rename those operands.
-
-     Work around this problem by forcing an operand re-scan on every
-     statement.  This will not be necessary once the new operand
-     scanner is implemented.  */
-  if (need_ssa_update_p ())
-    {
-      basic_block bb;
-      block_stmt_iterator si;
-      FOR_EACH_BB (bb)
-       for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
-         update_stmt (bsi_stmt (si));
-    }
-
-  rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
   tree_ssa_iv_optimize_finalize (loops, &data);
 }