OSDN Git Service

2005-07-14 Eric Christopher <echristo@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop-ivopts.c
index 1d8e308..84c68ab 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;
@@ -791,7 +791,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 +805,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 +993,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 +1064,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 +1389,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 +1430,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 +1440,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 +1451,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 +1491,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 +1513,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 +1537,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 +1608,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 +1626,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 +1695,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 +1886,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 +1913,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 +2566,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 +2662,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 +2847,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 +2914,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 +2937,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 +2963,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 +2982,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 +3013,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 +3059,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 +3069,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 +3155,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 +3205,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 +3227,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 +3243,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 +3294,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 +3306,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 +3325,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 +3338,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 +3358,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 +3374,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 +3389,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;
     
@@ -3708,7 +3739,7 @@ get_computation_cost_at (struct ivopts_data *data,
 
   /* CSTEPI is removed from the offset in case statement is after the
      increment.  If the step is not constant, we use zero instead.
-     This is a bit inprecise (there is the extra addition), but
+     This is a bit imprecise (there is the extra addition), but
      redundancy elimination is likely to transform the code so that
      it uses value of the variable before increment anyway,
      so it is not that much unrealistic.  */
@@ -3888,9 +3919,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 +3933,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 +4032,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 +5334,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 +5419,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 +5481,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 +5527,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 +5588,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 +5677,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 +5987,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);
 }