OSDN Git Service

2009-04-18 Manuel López-Ibáñez <manu@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / lambda-code.c
index 84ad869..852be11 100644 (file)
@@ -1,5 +1,6 @@
 /*  Loop transformation code generation
-    Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
+    Free Software Foundation, Inc.
     Contributed by Daniel Berlin <dberlin@dberlin.org>
 
     This file is part of GCC.
@@ -42,6 +43,7 @@
 #include "vec.h"
 #include "lambda.h"
 #include "vecprim.h"
+#include "pointer-set.h"
 
 /* This loop nest code generation is based on non-singular matrix
    math.
@@ -146,7 +148,6 @@ static lambda_lattice lambda_lattice_new (int, int, struct obstack *);
 static lambda_lattice lambda_lattice_compute_base (lambda_loopnest,
                                                    struct obstack *);
 
-static tree find_induction_var_from_exit_cond (struct loop *);
 static bool can_convert_to_perfect_nest (struct loop *);
 
 /* Create a new lambda body vector.  */
@@ -1230,16 +1231,16 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
                         VEC(tree,heap) * outerinductionvars,
                         VEC(tree,heap) ** lboundvars,
                         VEC(tree,heap) ** uboundvars,
-                         VEC(int,heap) ** steps,
+                        VEC(int,heap) ** steps,
                          struct obstack * lambda_obstack)
 {
-  tree phi;
-  tree exit_cond;
+  gimple phi;
+  gimple exit_cond;
   tree access_fn, inductionvar;
   tree step;
   lambda_loop lloop = NULL;
   lambda_linear_expression lbound, ubound;
-  tree test;
+  tree test_lhs, test_rhs;
   int stepint;
   int extra = 0;
   tree lboundvar, uboundvar, uboundresult;
@@ -1256,9 +1257,7 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
       return NULL;
     }
 
-  test = TREE_OPERAND (exit_cond, 0);
-
-  if (SSA_NAME_DEF_STMT (inductionvar) == NULL_TREE)
+  if (SSA_NAME_DEF_STMT (inductionvar) == NULL)
     {
 
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1269,10 +1268,10 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
     }
 
   phi = SSA_NAME_DEF_STMT (inductionvar);
-  if (TREE_CODE (phi) != PHI_NODE)
+  if (gimple_code (phi) != GIMPLE_PHI)
     {
-      phi = SINGLE_SSA_TREE_OPERAND (phi, SSA_OP_USE);
-      if (!phi)
+      tree op = SINGLE_SSA_TREE_OPERAND (phi, SSA_OP_USE);
+      if (!op)
        {
 
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1282,16 +1281,14 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
          return NULL;
        }
 
-      phi = SSA_NAME_DEF_STMT (phi);
-      if (TREE_CODE (phi) != PHI_NODE)
+      phi = SSA_NAME_DEF_STMT (op);
+      if (gimple_code (phi) != GIMPLE_PHI)
        {
-
          if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file,
                     "Unable to convert loop: Cannot find PHI node for induction variable\n");
          return NULL;
        }
-
     }
 
   /* The induction variable name/version we want to put in the array is the
@@ -1330,7 +1327,7 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
 
   /* Only want phis for induction vars, which will have two
      arguments.  */
-  if (PHI_NUM_ARGS (phi) != 2)
+  if (gimple_phi_num_args (phi) != 2)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file,
@@ -1340,8 +1337,8 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
 
   /* Another induction variable check. One argument's source should be
      in the loop, one outside the loop.  */
-  if (flow_bb_inside_loop_p (loop, PHI_ARG_EDGE (phi, 0)->src)
-      && flow_bb_inside_loop_p (loop, PHI_ARG_EDGE (phi, 1)->src))
+  if (flow_bb_inside_loop_p (loop, gimple_phi_arg_edge (phi, 0)->src)
+      && flow_bb_inside_loop_p (loop, gimple_phi_arg_edge (phi, 1)->src))
     {
 
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1351,7 +1348,7 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
       return NULL;
     }
 
-  if (flow_bb_inside_loop_p (loop, PHI_ARG_EDGE (phi, 0)->src))
+  if (flow_bb_inside_loop_p (loop, gimple_phi_arg_edge (phi, 0)->src))
     {
       lboundvar = PHI_ARG_DEF (phi, 1);
       lbound = gcc_tree_to_linear_expression (depth, lboundvar,
@@ -1377,21 +1374,23 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
     }
   /* One part of the test may be a loop invariant tree.  */
   VEC_reserve (tree, heap, *invariants, 1);
-  if (TREE_CODE (TREE_OPERAND (test, 1)) == SSA_NAME
-      && invariant_in_loop_and_outer_loops (loop, TREE_OPERAND (test, 1)))
-    VEC_quick_push (tree, *invariants, TREE_OPERAND (test, 1));
-  else if (TREE_CODE (TREE_OPERAND (test, 0)) == SSA_NAME
-          && invariant_in_loop_and_outer_loops (loop, TREE_OPERAND (test, 0)))
-    VEC_quick_push (tree, *invariants, TREE_OPERAND (test, 0));
+  test_lhs = gimple_cond_lhs (exit_cond);
+  test_rhs = gimple_cond_rhs (exit_cond);
+
+  if (TREE_CODE (test_rhs) == SSA_NAME
+      && invariant_in_loop_and_outer_loops (loop, test_rhs))
+    VEC_quick_push (tree, *invariants, test_rhs);
+  else if (TREE_CODE (test_lhs) == SSA_NAME
+          && invariant_in_loop_and_outer_loops (loop, test_lhs))
+    VEC_quick_push (tree, *invariants, test_lhs);
   
   /* The non-induction variable part of the test is the upper bound variable.
    */
-  if (TREE_OPERAND (test, 0) == inductionvar)
-    uboundvar = TREE_OPERAND (test, 1);
+  if (test_lhs == inductionvar)
+    uboundvar = test_rhs;
   else
-    uboundvar = TREE_OPERAND (test, 0);
+    uboundvar = test_lhs;
     
-
   /* We only size the vectors assuming we have, at max, 2 times as many
      invariants as we do loops (one for each bound).
      This is just an arbitrary number, but it has to be matched against the
@@ -1400,13 +1399,13 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
   
 
   /* We might have some leftover.  */
-  if (TREE_CODE (test) == LT_EXPR)
+  if (gimple_cond_code (exit_cond) == LT_EXPR)
     extra = -1 * stepint;
-  else if (TREE_CODE (test) == NE_EXPR)
+  else if (gimple_cond_code (exit_cond) == NE_EXPR)
     extra = -1 * stepint;
-  else if (TREE_CODE (test) == GT_EXPR)
+  else if (gimple_cond_code (exit_cond) == GT_EXPR)
     extra = -1 * stepint;
-  else if (TREE_CODE (test) == EQ_EXPR)
+  else if (gimple_cond_code (exit_cond) == EQ_EXPR)
     extra = 1 * stepint;
   
   ubound = gcc_tree_to_linear_expression (depth, uboundvar,
@@ -1435,27 +1434,26 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
 /* Given a LOOP, find the induction variable it is testing against in the exit
    condition.  Return the induction variable if found, NULL otherwise.  */
 
-static tree
+tree
 find_induction_var_from_exit_cond (struct loop *loop)
 {
-  tree expr = get_loop_exit_condition (loop);
+  gimple expr = get_loop_exit_condition (loop);
   tree ivarop;
-  tree test;
-  if (expr == NULL_TREE)
-    return NULL_TREE;
-  if (TREE_CODE (expr) != COND_EXPR)
+  tree test_lhs, test_rhs;
+  if (expr == NULL)
     return NULL_TREE;
-  test = TREE_OPERAND (expr, 0);
-  if (!COMPARISON_CLASS_P (test))
+  if (gimple_code (expr) != GIMPLE_COND)
     return NULL_TREE;
+  test_lhs = gimple_cond_lhs (expr);
+  test_rhs = gimple_cond_rhs (expr);
 
   /* Find the side that is invariant in this loop. The ivar must be the other
      side.  */
   
-  if (expr_invariant_in_loop_p (loop, TREE_OPERAND (test, 0)))
-      ivarop = TREE_OPERAND (test, 1);
-  else if (expr_invariant_in_loop_p (loop, TREE_OPERAND (test, 1)))
-      ivarop = TREE_OPERAND (test, 0);
+  if (expr_invariant_in_loop_p (loop, test_lhs))
+      ivarop = test_rhs;
+  else if (expr_invariant_in_loop_p (loop, test_rhs))
+      ivarop = test_lhs;
   else
     return NULL_TREE;
 
@@ -1547,7 +1545,7 @@ gcc_loopnest_to_lambda_loopnest (struct loop *loop_nest,
 static tree
 lbv_to_gcc_expression (lambda_body_vector lbv, 
                       tree type, VEC(tree,heap) *induction_vars, 
-                      tree *stmts_to_insert)
+                      gimple_seq *stmts_to_insert)
 {
   int k;
   tree resvar;
@@ -1582,7 +1580,7 @@ lle_to_gcc_expression (lambda_linear_expression lle,
                       tree type,
                       VEC(tree,heap) *induction_vars,
                       VEC(tree,heap) *invariants,
-                      enum tree_code wrap, tree *stmts_to_insert)
+                      enum tree_code wrap, gimple_seq *stmts_to_insert)
 {
   int k;
   tree resvar;
@@ -1640,17 +1638,19 @@ lle_to_gcc_expression (lambda_linear_expression lle,
 /* Remove the induction variable defined at IV_STMT.  */
 
 void
-remove_iv (tree iv_stmt)
+remove_iv (gimple iv_stmt)
 {
-  if (TREE_CODE (iv_stmt) == PHI_NODE)
+  gimple_stmt_iterator si = gsi_for_stmt (iv_stmt);
+
+  if (gimple_code (iv_stmt) == GIMPLE_PHI)
     {
-      int i;
+      unsigned i;
 
-      for (i = 0; i < PHI_NUM_ARGS (iv_stmt); i++)
+      for (i = 0; i < gimple_phi_num_args (iv_stmt); i++)
        {
-         tree stmt;
+         gimple stmt;
          imm_use_iterator imm_iter;
-         tree arg = PHI_ARG_DEF (iv_stmt, i);
+         tree arg = gimple_phi_arg_def (iv_stmt, i);
          bool used = false;
 
          if (TREE_CODE (arg) != SSA_NAME)
@@ -1664,18 +1664,15 @@ remove_iv (tree iv_stmt)
            remove_iv (SSA_NAME_DEF_STMT (arg));
        }
 
-      remove_phi_node (iv_stmt, NULL_TREE, true);
+      remove_phi_node (&si, true);
     }
   else
     {
-      block_stmt_iterator bsi = bsi_for_stmt (iv_stmt);
-
-      bsi_remove (&bsi, true);
+      gsi_remove (&si, true);
       release_defs (iv_stmt); 
     }
 }
 
-
 /* Transform a lambda loopnest NEW_LOOPNEST, which had TRANSFORM applied to
    it, back into gcc code.  This changes the
    loops, their induction variables, and their bodies, so that they
@@ -1692,22 +1689,23 @@ void
 lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
                                 VEC(tree,heap) *old_ivs,
                                 VEC(tree,heap) *invariants,
-                                VEC(tree,heap) **remove_ivs,
+                                VEC(gimple,heap) **remove_ivs,
                                 lambda_loopnest new_loopnest,
                                  lambda_trans_matrix transform,
                                  struct obstack * lambda_obstack)
 {
   struct loop *temp;
   size_t i = 0;
+  unsigned j;
   size_t depth = 0;
   VEC(tree,heap) *new_ivs = NULL;
   tree oldiv;
-  
-  block_stmt_iterator bsi;
+  gimple_stmt_iterator bsi;
+
+  transform = lambda_trans_matrix_inverse (transform);
 
   if (dump_file)
     {
-      transform = lambda_trans_matrix_inverse (transform);
       fprintf (dump_file, "Inverse of transformation matrix:\n");
       print_lambda_trans_matrix (dump_file, transform);
     }
@@ -1719,13 +1717,15 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
       lambda_loop newloop;
       basic_block bb;
       edge exit;
-      tree ivvar, ivvarinced, exitcond, stmts;
+      tree ivvar, ivvarinced;
+      gimple exitcond;
+      gimple_seq stmts;
       enum tree_code testtype;
       tree newupperbound, newlowerbound;
       lambda_linear_expression offset;
       tree type;
       bool insert_after;
-      tree inc_stmt;
+      gimple inc_stmt;
 
       oldiv = VEC_index (tree, old_ivs, i);
       type = TREE_TYPE (oldiv);
@@ -1748,6 +1748,7 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
            
       /* Now build the  new lower bounds, and insert the statements
          necessary to generate it on the loop preheader.  */
+      stmts = NULL;
       newlowerbound = lle_to_gcc_expression (LL_LOWER_BOUND (newloop),
                                             LL_LINEAR_OFFSET (newloop),
                                             type,
@@ -1756,11 +1757,12 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
 
       if (stmts)
        {
-         bsi_insert_on_edge (loop_preheader_edge (temp), stmts);
-         bsi_commit_edge_inserts ();
+         gsi_insert_seq_on_edge (loop_preheader_edge (temp), stmts);
+         gsi_commit_edge_inserts ();
        }
       /* Build the new upper bound and insert its statements in the
          basic block of the exit condition */
+      stmts = NULL;
       newupperbound = lle_to_gcc_expression (LL_UPPER_BOUND (newloop),
                                             LL_LINEAR_OFFSET (newloop),
                                             type,
@@ -1768,10 +1770,10 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
                                             invariants, MIN_EXPR, &stmts);
       exit = single_exit (temp);
       exitcond = get_loop_exit_condition (temp);
-      bb = bb_for_stmt (exitcond);
-      bsi = bsi_after_labels (bb);
+      bb = gimple_bb (exitcond);
+      bsi = gsi_after_labels (bb);
       if (stmts)
-       bsi_insert_before (&bsi, stmts, BSI_NEW_STMT);
+       gsi_insert_seq_before (&bsi, stmts, GSI_NEW_STMT);
 
       /* Create the new iv.  */
 
@@ -1785,13 +1787,14 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
         dominate the block containing the exit condition.
         So we simply create our own incremented iv to use in the new exit
         test,  and let redundancy elimination sort it out.  */
-      inc_stmt = build2 (PLUS_EXPR, type, 
-                        ivvar, build_int_cst (type, LL_STEP (newloop)));
-      inc_stmt = build_gimple_modify_stmt (SSA_NAME_VAR (ivvar), inc_stmt);
+      inc_stmt = gimple_build_assign_with_ops (PLUS_EXPR, SSA_NAME_VAR (ivvar),
+                                              ivvar,
+                                              build_int_cst (type, LL_STEP (newloop)));
+
       ivvarinced = make_ssa_name (SSA_NAME_VAR (ivvar), inc_stmt);
-      GIMPLE_STMT_OPERAND (inc_stmt, 0) = ivvarinced;
-      bsi = bsi_for_stmt (exitcond);
-      bsi_insert_before (&bsi, inc_stmt, BSI_SAME_STMT);
+      gimple_assign_set_lhs (inc_stmt, ivvarinced);
+      bsi = gsi_for_stmt (exitcond);
+      gsi_insert_before (&bsi, inc_stmt, GSI_SAME_STMT);
 
       /* Replace the exit condition with the new upper bound
          comparison.  */
@@ -1805,9 +1808,7 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
       if (exit->flags & EDGE_FALSE_VALUE)
        testtype = swap_tree_comparison (testtype);
 
-      COND_EXPR_COND (exitcond) = build2 (testtype,
-                                         boolean_type_node,
-                                         newupperbound, ivvarinced);
+      gimple_cond_set_condition (exitcond, testtype, newupperbound, ivvarinced);
       update_stmt (exitcond);
       VEC_replace (tree, new_ivs, i, ivvar);
 
@@ -1823,10 +1824,10 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
       imm_use_iterator imm_iter;
       use_operand_p use_p;
       tree oldiv_def;
-      tree oldiv_stmt = SSA_NAME_DEF_STMT (oldiv);
-      tree stmt;
+      gimple oldiv_stmt = SSA_NAME_DEF_STMT (oldiv);
+      gimple stmt;
 
-      if (TREE_CODE (oldiv_stmt) == PHI_NODE)
+      if (gimple_code (oldiv_stmt) == GIMPLE_PHI)
         oldiv_def = PHI_RESULT (oldiv_stmt);
       else
        oldiv_def = SINGLE_SSA_TREE_OPERAND (oldiv_stmt, SSA_OP_DEF);
@@ -1834,11 +1835,10 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
 
       FOR_EACH_IMM_USE_STMT (stmt, imm_iter, oldiv_def)
         {
-         tree newiv, stmts;
+         tree newiv;
+         gimple_seq stmts;
          lambda_body_vector lbv, newlbv;
 
-         gcc_assert (TREE_CODE (stmt) != PHI_NODE);
-
          /* Compute the new expression for the induction
             variable.  */
          depth = VEC_length (tree, new_ivs);
@@ -1848,21 +1848,29 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
           newlbv = lambda_body_vector_compute_new (transform, lbv,
                                                    lambda_obstack);
 
+         stmts = NULL;
          newiv = lbv_to_gcc_expression (newlbv, TREE_TYPE (oldiv),
                                         new_ivs, &stmts);
-         if (stmts)
+
+         if (stmts && gimple_code (stmt) != GIMPLE_PHI)
            {
-             bsi = bsi_for_stmt (stmt);
-             bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
+             bsi = gsi_for_stmt (stmt);
+             gsi_insert_seq_before (&bsi, stmts, GSI_SAME_STMT);
            }
 
          FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
            propagate_value (use_p, newiv);
+
+         if (stmts && gimple_code (stmt) == GIMPLE_PHI)
+           for (j = 0; j < gimple_phi_num_args (stmt); j++)
+             if (gimple_phi_arg_def (stmt, j) == newiv)
+               gsi_insert_seq_on_edge (gimple_phi_arg_edge (stmt, j), stmts);
+
          update_stmt (stmt);
        }
 
       /* Remove the now unused induction variable.  */
-      VEC_safe_push (tree, heap, *remove_ivs, oldiv_stmt);
+      VEC_safe_push (gimple, heap, *remove_ivs, oldiv_stmt);
     }
   VEC_free (tree, heap, new_ivs);
 }
@@ -1871,13 +1879,13 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
    determining if we have a perfect loop nest.  */
 
 static bool
-not_interesting_stmt (tree stmt)
+not_interesting_stmt (gimple stmt)
 {
   /* Note that COND_EXPR's aren't interesting because if they were exiting the
      loop, we would have already failed the number of exits tests.  */
-  if (TREE_CODE (stmt) == LABEL_EXPR
-      || TREE_CODE (stmt) == GOTO_EXPR
-      || TREE_CODE (stmt) == COND_EXPR)
+  if (gimple_code (stmt) == GIMPLE_LABEL
+      || gimple_code (stmt) == GIMPLE_GOTO
+      || gimple_code (stmt) == GIMPLE_COND)
     return true;
   return false;
 }
@@ -1885,11 +1893,11 @@ not_interesting_stmt (tree stmt)
 /* Return TRUE if PHI uses DEF for it's in-the-loop edge for LOOP.  */
 
 static bool
-phi_loop_edge_uses_def (struct loop *loop, tree phi, tree def)
+phi_loop_edge_uses_def (struct loop *loop, gimple phi, tree def)
 {
-  int i;
-  for (i = 0; i < PHI_NUM_ARGS (phi); i++)
-    if (flow_bb_inside_loop_p (loop, PHI_ARG_EDGE (phi, i)->src))
+  unsigned i;
+  for (i = 0; i < gimple_phi_num_args (phi); i++)
+    if (flow_bb_inside_loop_p (loop, gimple_phi_arg_edge (phi, i)->src))
       if (PHI_ARG_DEF (phi, i) == def)
        return true;
   return false;
@@ -1898,7 +1906,7 @@ phi_loop_edge_uses_def (struct loop *loop, tree phi, tree def)
 /* Return TRUE if STMT is a use of PHI_RESULT.  */
 
 static bool
-stmt_uses_phi_result (tree stmt, tree phi_result)
+stmt_uses_phi_result (gimple stmt, tree phi_result)
 {
   tree use = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_USE);
   
@@ -1914,9 +1922,9 @@ stmt_uses_phi_result (tree stmt, tree phi_result)
         i_3 = PHI (0, i_29);  */
 
 static bool
-stmt_is_bumper_for_loop (struct loop *loop, tree stmt)
+stmt_is_bumper_for_loop (struct loop *loop, gimple stmt)
 {
-  tree use;
+  gimple use;
   tree def;
   imm_use_iterator iter;
   use_operand_p use_p;
@@ -1928,7 +1936,7 @@ stmt_is_bumper_for_loop (struct loop *loop, tree stmt)
   FOR_EACH_IMM_USE_FAST (use_p, iter, def)
     {
       use = USE_STMT (use_p);
-      if (TREE_CODE (use) == PHI_NODE)
+      if (gimple_code (use) == GIMPLE_PHI)
        {
          if (phi_loop_edge_uses_def (loop, use, def))
            if (stmt_uses_phi_result (stmt, PHI_RESULT (use)))
@@ -1970,34 +1978,44 @@ perfect_nest_p (struct loop *loop)
 {
   basic_block *bbs;
   size_t i;
-  tree exit_cond;
+  gimple exit_cond;
 
+  /* Loops at depth 0 are perfect nests.  */
   if (!loop->inner)
     return true;
+
   bbs = get_loop_body (loop);
   exit_cond = get_loop_exit_condition (loop);
+
   for (i = 0; i < loop->num_nodes; i++)
     {
       if (bbs[i]->loop_father == loop)
        {
-         block_stmt_iterator bsi;
-         for (bsi = bsi_start (bbs[i]); !bsi_end_p (bsi); bsi_next (&bsi))
+         gimple_stmt_iterator bsi;
+
+         for (bsi = gsi_start_bb (bbs[i]); !gsi_end_p (bsi); gsi_next (&bsi))
            {
-             tree stmt = bsi_stmt (bsi);
+             gimple stmt = gsi_stmt (bsi);
+
+             if (gimple_code (stmt) == GIMPLE_COND
+                 && exit_cond != stmt)
+               goto non_perfectly_nested;
+
              if (stmt == exit_cond
                  || not_interesting_stmt (stmt)
                  || stmt_is_bumper_for_loop (loop, stmt))
                continue;
+
+           non_perfectly_nested:
              free (bbs);
              return false;
            }
        }
     }
+
   free (bbs);
-  /* See if the inner loops are perfectly nested as well.  */
-  if (loop->inner)    
-    return perfect_nest_p (loop->inner);
-  return true;
+
+  return perfect_nest_p (loop->inner);
 }
 
 /* Replace the USES of X in STMT, or uses with the same step as X with Y.
@@ -2007,10 +2025,10 @@ perfect_nest_p (struct loop *loop)
    of body basic block.  */
 
 static void
-replace_uses_equiv_to_x_with_y (struct loop *loop, tree stmt, tree x, 
+replace_uses_equiv_to_x_with_y (struct loop *loop, gimple stmt, tree x, 
                                int xstep, tree y, tree yinit,
                                htab_t replacements,
-                               block_stmt_iterator *firstbsi)
+                               gimple_stmt_iterator *firstbsi)
 {
   ssa_op_iter iter;
   use_operand_p use_p;
@@ -2019,7 +2037,8 @@ replace_uses_equiv_to_x_with_y (struct loop *loop, tree stmt, tree x,
     {
       tree use = USE_FROM_PTR (use_p);
       tree step = NULL_TREE;
-      tree scev, init, val, var, setstmt;
+      tree scev, init, val, var;
+      gimple setstmt;
       struct tree_map *h, in;
       void **loc;
 
@@ -2082,12 +2101,12 @@ replace_uses_equiv_to_x_with_y (struct loop *loop, tree stmt, tree x,
         which sets Y.  */
       var = create_tmp_var (TREE_TYPE (use), "perfecttmp");
       add_referenced_var (var);
-      val = force_gimple_operand_bsi (firstbsi, val, false, NULL,
-                                     true, BSI_SAME_STMT);
-      setstmt = build_gimple_modify_stmt (var, val);
+      val = force_gimple_operand_gsi (firstbsi, val, false, NULL,
+                                     true, GSI_SAME_STMT);
+      setstmt = gimple_build_assign (var, val);
       var = make_ssa_name (var, setstmt);
-      GIMPLE_STMT_OPERAND (setstmt, 0) = var;
-      bsi_insert_before (firstbsi, setstmt, BSI_SAME_STMT);
+      gimple_assign_set_lhs (setstmt, var);
+      gsi_insert_before (firstbsi, setstmt, GSI_SAME_STMT);
       update_stmt (setstmt);
       SET_USE (use_p, var);
       h = GGC_NEW (struct tree_map);
@@ -2103,12 +2122,11 @@ replace_uses_equiv_to_x_with_y (struct loop *loop, tree stmt, tree x,
 /* Return true if STMT is an exit PHI for LOOP */
 
 static bool
-exit_phi_for_loop_p (struct loop *loop, tree stmt)
+exit_phi_for_loop_p (struct loop *loop, gimple stmt)
 {
-  
-  if (TREE_CODE (stmt) != PHI_NODE
-      || PHI_NUM_ARGS (stmt) != 1
-      || bb_for_stmt (stmt) != single_exit (loop)->dest)
+  if (gimple_code (stmt) != GIMPLE_PHI
+      || gimple_phi_num_args (stmt) != 1
+      || gimple_bb (stmt) != single_exit (loop)->dest)
     return false;
   
   return true;
@@ -2118,21 +2136,21 @@ exit_phi_for_loop_p (struct loop *loop, tree stmt)
    copying it to the beginning of that loop and changing the uses.  */
 
 static bool
-can_put_in_inner_loop (struct loop *inner, tree stmt)
+can_put_in_inner_loop (struct loop *inner, gimple stmt)
 {
   imm_use_iterator imm_iter;
   use_operand_p use_p;
   
-  gcc_assert (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT);
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)
-      || !expr_invariant_in_loop_p (inner, GIMPLE_STMT_OPERAND (stmt, 1)))
+  gcc_assert (is_gimple_assign (stmt));
+  if (gimple_vuse (stmt)
+      || !stmt_invariant_in_loop_p (inner, stmt))
     return false;
   
-  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, GIMPLE_STMT_OPERAND (stmt, 0))
+  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_assign_lhs (stmt))
     {
       if (!exit_phi_for_loop_p (inner, USE_STMT (use_p)))
        {
-         basic_block immbb = bb_for_stmt (USE_STMT (use_p));
+         basic_block immbb = gimple_bb (USE_STMT (use_p));
 
          if (!flow_bb_inside_loop_p (inner, immbb))
            return false;
@@ -2142,20 +2160,21 @@ can_put_in_inner_loop (struct loop *inner, tree stmt)
 }
 
 /* Return true if STMT can be put *after* the inner loop of LOOP.  */
+
 static bool
-can_put_after_inner_loop (struct loop *loop, tree stmt)
+can_put_after_inner_loop (struct loop *loop, gimple stmt)
 {
   imm_use_iterator imm_iter;
   use_operand_p use_p;
 
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+  if (gimple_vuse (stmt))
     return false;
   
-  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, GIMPLE_STMT_OPERAND (stmt, 0))
+  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_assign_lhs (stmt))
     {
       if (!exit_phi_for_loop_p (loop, USE_STMT (use_p)))
        {
-         basic_block immbb = bb_for_stmt (USE_STMT (use_p));
+         basic_block immbb = gimple_bb (USE_STMT (use_p));
          
          if (!dominated_by_p (CDI_DOMINATORS,
                               immbb,
@@ -2167,6 +2186,124 @@ can_put_after_inner_loop (struct loop *loop, tree stmt)
   return true;
 }
 
+/* Return true when the induction variable IV is simple enough to be
+   re-synthesized.  */
+
+static bool
+can_duplicate_iv (tree iv, struct loop *loop)
+{
+  tree scev = instantiate_parameters
+    (loop, analyze_scalar_evolution (loop, iv));
+
+  if (!automatically_generated_chrec_p (scev))
+    {
+      tree step = evolution_part_in_loop_num (scev, loop->num);
+
+      if (step && step != chrec_dont_know && TREE_CODE (step) == INTEGER_CST)
+       return true;
+    }
+
+  return false;
+}
+
+/* If this is a scalar operation that can be put back into the inner
+   loop, or after the inner loop, through copying, then do so. This
+   works on the theory that any amount of scalar code we have to
+   reduplicate into or after the loops is less expensive that the win
+   we get from rearranging the memory walk the loop is doing so that
+   it has better cache behavior.  */
+
+static bool
+cannot_convert_modify_to_perfect_nest (gimple stmt, struct loop *loop)
+{
+  use_operand_p use_a, use_b;
+  imm_use_iterator imm_iter;
+  ssa_op_iter op_iter, op_iter1;
+  tree op0 = gimple_assign_lhs (stmt);
+
+  /* The statement should not define a variable used in the inner
+     loop.  */
+  if (TREE_CODE (op0) == SSA_NAME
+      && !can_duplicate_iv (op0, loop))
+    FOR_EACH_IMM_USE_FAST (use_a, imm_iter, op0)
+      if (gimple_bb (USE_STMT (use_a))->loop_father == loop->inner)
+       return true;
+
+  FOR_EACH_SSA_USE_OPERAND (use_a, stmt, op_iter, SSA_OP_USE)
+    {
+      gimple node;
+      tree op = USE_FROM_PTR (use_a);
+
+      /* The variables should not be used in both loops.  */
+      if (!can_duplicate_iv (op, loop))
+       FOR_EACH_IMM_USE_FAST (use_b, imm_iter, op)
+         if (gimple_bb (USE_STMT (use_b))->loop_father == loop->inner)
+           return true;
+
+      /* The statement should not use the value of a scalar that was
+        modified in the loop.  */
+      node = SSA_NAME_DEF_STMT (op);
+      if (gimple_code (node) == GIMPLE_PHI)
+       FOR_EACH_PHI_ARG (use_b, node, op_iter1, SSA_OP_USE)
+         {
+           tree arg = USE_FROM_PTR (use_b);
+
+           if (TREE_CODE (arg) == SSA_NAME)
+             {
+               gimple arg_stmt = SSA_NAME_DEF_STMT (arg);
+
+               if (gimple_bb (arg_stmt)
+                   && (gimple_bb (arg_stmt)->loop_father == loop->inner))
+                 return true;
+             }
+         }
+    }
+
+  return false;
+}
+/* Return true when BB contains statements that can harm the transform
+   to a perfect loop nest.  */
+
+static bool
+cannot_convert_bb_to_perfect_nest (basic_block bb, struct loop *loop)
+{
+  gimple_stmt_iterator bsi;
+  gimple exit_condition = get_loop_exit_condition (loop);
+
+  for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+    { 
+      gimple stmt = gsi_stmt (bsi);
+
+      if (stmt == exit_condition
+         || not_interesting_stmt (stmt)
+         || stmt_is_bumper_for_loop (loop, stmt))
+       continue;
+
+      if (is_gimple_assign (stmt))
+       {
+         if (cannot_convert_modify_to_perfect_nest (stmt, loop))
+           return true;
+
+         if (can_duplicate_iv (gimple_assign_lhs (stmt), loop))
+           continue;
+
+         if (can_put_in_inner_loop (loop->inner, stmt)
+             || can_put_after_inner_loop (loop, stmt))
+           continue;
+       }
+
+      /* If the bb of a statement we care about isn't dominated by the
+        header of the inner loop, then we can't handle this case
+        right now.  This test ensures that the statement comes
+        completely *after* the inner loop.  */
+      if (!dominated_by_p (CDI_DOMINATORS,
+                          gimple_bb (stmt), 
+                          loop->inner->header))
+       return true;
+    }
+
+  return false;
+}
 
 
 /* Return TRUE if LOOP is an imperfect nest that we can convert to a
@@ -2177,118 +2314,25 @@ static bool
 can_convert_to_perfect_nest (struct loop *loop)
 {
   basic_block *bbs;
-  tree exit_condition, phi;
   size_t i;
-  block_stmt_iterator bsi;
-  basic_block exitdest;
+  gimple_stmt_iterator si;
 
   /* Can't handle triply nested+ loops yet.  */
   if (!loop->inner || loop->inner->inner)
     return false;
   
   bbs = get_loop_body (loop);
-  exit_condition = get_loop_exit_condition (loop);
   for (i = 0; i < loop->num_nodes; i++)
-    {
-      if (bbs[i]->loop_father == loop)
-       {
-         for (bsi = bsi_start (bbs[i]); !bsi_end_p (bsi); bsi_next (&bsi))
-           { 
-             tree stmt = bsi_stmt (bsi);
-
-             if (stmt == exit_condition
-                 || not_interesting_stmt (stmt)
-                 || stmt_is_bumper_for_loop (loop, stmt))
-               continue;
-
-             /* If this is a scalar operation that can be put back
-                into the inner loop, or after the inner loop, through
-                copying, then do so. This works on the theory that
-                any amount of scalar code we have to reduplicate
-                into or after the loops is less expensive that the
-                win we get from rearranging the memory walk
-                the loop is doing so that it has better
-                cache behavior.  */
-             if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
-               {
-                 use_operand_p use_a, use_b;
-                 imm_use_iterator imm_iter;
-                 ssa_op_iter op_iter, op_iter1;
-                 tree op0 = GIMPLE_STMT_OPERAND (stmt, 0);
-                 tree scev = instantiate_parameters
-                   (loop, analyze_scalar_evolution (loop, op0));
-
-                 /* If the IV is simple, it can be duplicated.  */
-                 if (!automatically_generated_chrec_p (scev))
-                   {
-                     tree step = evolution_part_in_loop_num (scev, loop->num);
-                     if (step && step != chrec_dont_know 
-                         && TREE_CODE (step) == INTEGER_CST)
-                       continue;
-                   }
-
-                 /* The statement should not define a variable used
-                    in the inner loop.  */
-                 if (TREE_CODE (op0) == SSA_NAME)
-                   FOR_EACH_IMM_USE_FAST (use_a, imm_iter, op0)
-                     if (bb_for_stmt (USE_STMT (use_a))->loop_father
-                         == loop->inner)
-                       goto fail;
-
-                 FOR_EACH_SSA_USE_OPERAND (use_a, stmt, op_iter, SSA_OP_USE)
-                   {
-                     tree node, op = USE_FROM_PTR (use_a);
-
-                     /* The variables should not be used in both loops.  */
-                     FOR_EACH_IMM_USE_FAST (use_b, imm_iter, op)
-                     if (bb_for_stmt (USE_STMT (use_b))->loop_father
-                         == loop->inner)
-                       goto fail;
-
-                     /* The statement should not use the value of a
-                        scalar that was modified in the loop.  */
-                     node = SSA_NAME_DEF_STMT (op);
-                     if (TREE_CODE (node) == PHI_NODE)
-                       FOR_EACH_PHI_ARG (use_b, node, op_iter1, SSA_OP_USE)
-                         {
-                           tree arg = USE_FROM_PTR (use_b);
-
-                           if (TREE_CODE (arg) == SSA_NAME)
-                             {
-                               tree arg_stmt = SSA_NAME_DEF_STMT (arg);
-
-                               if (bb_for_stmt (arg_stmt)
-                                   && (bb_for_stmt (arg_stmt)->loop_father
-                                       == loop->inner))
-                                 goto fail;
-                             }
-                         }
-                   }
-
-                 if (can_put_in_inner_loop (loop->inner, stmt)
-                     || can_put_after_inner_loop (loop, stmt))
-                   continue;
-               }
-
-             /* Otherwise, if the bb of a statement we care about isn't
-                dominated by the header of the inner loop, then we can't
-                handle this case right now.  This test ensures that the
-                statement comes completely *after* the inner loop.  */
-             if (!dominated_by_p (CDI_DOMINATORS,
-                                  bb_for_stmt (stmt), 
-                                  loop->inner->header))
-               goto fail;
-           }
-       }
-    }
+    if (bbs[i]->loop_father == loop
+       && cannot_convert_bb_to_perfect_nest (bbs[i], loop))
+      goto fail;
 
   /* We also need to make sure the loop exit only has simple copy phis in it,
-     otherwise we don't know how to transform it into a perfect nest right
-     now.  */
-  exitdest = single_exit (loop)->dest;
-  
-  for (phi = phi_nodes (exitdest); phi; phi = PHI_CHAIN (phi))
-    if (PHI_NUM_ARGS (phi) != 1)
+     otherwise we don't know how to transform it into a perfect nest.  */
+  for (si = gsi_start_phis (single_exit (loop)->dest);
+       !gsi_end_p (si);
+       gsi_next (&si))
+    if (gimple_phi_num_args (gsi_stmt (si)) != 1)
       goto fail;
   
   free (bbs);
@@ -2343,17 +2387,17 @@ perfect_nestify (struct loop *loop,
                 VEC(tree,heap) *loopivs)
 {
   basic_block *bbs;
-  tree exit_condition;
-  tree cond_stmt;
+  gimple exit_condition;
+  gimple cond_stmt;
   basic_block preheaderbb, headerbb, bodybb, latchbb, olddest;
   int i;
-  block_stmt_iterator bsi, firstbsi;
+  gimple_stmt_iterator bsi, firstbsi;
   bool insert_after;
   edge e;
   struct loop *newloop;
-  tree phi;
+  gimple phi;
   tree uboundvar;
-  tree stmt;
+  gimple stmt;
   tree oldivvar, ivvar, ivvarinced;
   VEC(tree,heap) *phis = NULL;
   htab_t replacements = NULL;
@@ -2364,8 +2408,9 @@ perfect_nestify (struct loop *loop,
   headerbb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
   
   /* Push the exit phi nodes that we are moving.  */
-  for (phi = phi_nodes (olddest); phi; phi = PHI_CHAIN (phi))
+  for (bsi = gsi_start_phis (olddest); !gsi_end_p (bsi); gsi_next (&bsi))
     {
+      phi = gsi_stmt (bsi);
       VEC_reserve (tree, heap, phis, 2);
       VEC_quick_push (tree, phis, PHI_RESULT (phi));
       VEC_quick_push (tree, phis, PHI_ARG_DEF (phi, 0));
@@ -2373,8 +2418,8 @@ perfect_nestify (struct loop *loop,
   e = redirect_edge_and_branch (single_succ_edge (preheaderbb), headerbb);
 
   /* Remove the exit phis from the old basic block.  */
-  while (phi_nodes (olddest) != NULL)
-    remove_phi_node (phi_nodes (olddest), NULL, false);
+  for (bsi = gsi_start_phis (olddest); !gsi_end_p (bsi); )
+    remove_phi_node (&bsi, false);
 
   /* and add them back to the new basic block.  */
   while (VEC_length (tree, phis) != 0)
@@ -2392,13 +2437,10 @@ perfect_nestify (struct loop *loop,
   bodybb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
   latchbb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
   make_edge (headerbb, bodybb, EDGE_FALLTHRU); 
-  cond_stmt = build3 (COND_EXPR, void_type_node,
-                     build2 (NE_EXPR, boolean_type_node, 
-                             integer_one_node, 
-                             integer_zero_node), 
-                     NULL_TREE, NULL_TREE);
-  bsi = bsi_start (bodybb);
-  bsi_insert_after (&bsi, cond_stmt, BSI_NEW_STMT);
+  cond_stmt = gimple_build_cond (NE_EXPR, integer_one_node, integer_zero_node,
+                                NULL_TREE, NULL_TREE);
+  bsi = gsi_start_bb (bodybb);
+  gsi_insert_after (&bsi, cond_stmt, GSI_NEW_STMT);
   e = make_edge (bodybb, olddest, EDGE_FALSE_VALUE);
   make_edge (bodybb, latchbb, EDGE_TRUE_VALUE);
   make_edge (latchbb, headerbb, EDGE_FALLTHRU);
@@ -2430,21 +2472,19 @@ perfect_nestify (struct loop *loop,
      it to one just in case.  */
 
   exit_condition = get_loop_exit_condition (newloop);
-  uboundvar = create_tmp_var (integer_type_node, "uboundvar");
+  uboundvar = create_tmp_var (TREE_TYPE (VEC_index (tree, ubounds, 0)),
+                             "uboundvar");
   add_referenced_var (uboundvar);
-  stmt = build_gimple_modify_stmt (uboundvar, VEC_index (tree, ubounds, 0));
+  stmt = gimple_build_assign (uboundvar, VEC_index (tree, ubounds, 0));
   uboundvar = make_ssa_name (uboundvar, stmt);
-  GIMPLE_STMT_OPERAND (stmt, 0) = uboundvar;
+  gimple_assign_set_lhs (stmt, uboundvar);
 
   if (insert_after)
-    bsi_insert_after (&bsi, stmt, BSI_SAME_STMT);
+    gsi_insert_after (&bsi, stmt, GSI_SAME_STMT);
   else
-    bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
+    gsi_insert_before (&bsi, stmt, GSI_SAME_STMT);
   update_stmt (stmt);
-  COND_EXPR_COND (exit_condition) = build2 (GE_EXPR, 
-                                           boolean_type_node,
-                                           uboundvar,
-                                           ivvarinced);
+  gimple_cond_set_condition (exit_condition, GE_EXPR, uboundvar, ivvarinced);
   update_stmt (exit_condition);
   replacements = htab_create_ggc (20, tree_map_hash,
                                  tree_map_eq, NULL);
@@ -2452,10 +2492,10 @@ perfect_nestify (struct loop *loop,
   /* Now move the statements, and replace the induction variable in the moved
      statements with the correct loop induction variable.  */
   oldivvar = VEC_index (tree, loopivs, 0);
-  firstbsi = bsi_start (bodybb);
+  firstbsi = gsi_start_bb (bodybb);
   for (i = loop->num_nodes - 1; i >= 0 ; i--)
     {
-      block_stmt_iterator tobsi = bsi_last (bodybb);
+      gimple_stmt_iterator tobsi = gsi_last_bb (bodybb);
       if (bbs[i]->loop_father == loop)
        {
          /* If this is true, we are *before* the inner loop.
@@ -2471,22 +2511,22 @@ perfect_nestify (struct loop *loop,
 
          if (dominated_by_p (CDI_DOMINATORS, loop->inner->header, bbs[i]))
            {
-             block_stmt_iterator header_bsi 
-               = bsi_after_labels (loop->inner->header);
+             gimple_stmt_iterator header_bsi 
+               = gsi_after_labels (loop->inner->header);
 
-             for (bsi = bsi_start (bbs[i]); !bsi_end_p (bsi);)
+             for (bsi = gsi_start_bb (bbs[i]); !gsi_end_p (bsi);)
                { 
-                 tree stmt = bsi_stmt (bsi);
+                 gimple stmt = gsi_stmt (bsi);
 
                  if (stmt == exit_condition
                      || not_interesting_stmt (stmt)
                      || stmt_is_bumper_for_loop (loop, stmt))
                    {
-                     bsi_next (&bsi);
+                     gsi_next (&bsi);
                      continue;
                    }
 
-                 bsi_move_before (&bsi, &header_bsi);
+                 gsi_move_before (&bsi, &header_bsi);
                }
            }
          else
@@ -2494,16 +2534,15 @@ perfect_nestify (struct loop *loop,
              /* Note that the bsi only needs to be explicitly incremented
                 when we don't move something, since it is automatically
                 incremented when we do.  */
-             for (bsi = bsi_start (bbs[i]); !bsi_end_p (bsi);)
+             for (bsi = gsi_start_bb (bbs[i]); !gsi_end_p (bsi);)
                { 
-                 ssa_op_iter i;
-                 tree n, stmt = bsi_stmt (bsi);
+                 gimple stmt = gsi_stmt (bsi);
                  
                  if (stmt == exit_condition
                      || not_interesting_stmt (stmt)
                      || stmt_is_bumper_for_loop (loop, stmt))
                    {
-                     bsi_next (&bsi);
+                     gsi_next (&bsi);
                      continue;
                    }
                  
@@ -2511,13 +2550,13 @@ perfect_nestify (struct loop *loop,
                    (loop, stmt, oldivvar, VEC_index (int, steps, 0), ivvar,
                     VEC_index (tree, lbounds, 0), replacements, &firstbsi);
 
-                 bsi_move_before (&bsi, &tobsi);
-                 
+                 gsi_move_before (&bsi, &tobsi);
+
                  /* If the statement has any virtual operands, they may
                     need to be rewired because the original loop may
                     still reference them.  */
-                 FOR_EACH_SSA_TREE_OPERAND (n, stmt, i, SSA_OP_ALL_VIRTUALS)
-                   mark_sym_for_renaming (SSA_NAME_VAR (n));
+                 if (gimple_vuse (stmt))
+                   mark_sym_for_renaming (gimple_vop (cfun));
                }
            }
          
@@ -2554,11 +2593,16 @@ lambda_transform_legal_p (lambda_trans_matrix trans,
   gcc_assert (LTM_COLSIZE (trans) == nb_loops
              && LTM_ROWSIZE (trans) == nb_loops);
 
-  /* When there is an unknown relation in the dependence_relations, we
-     know that it is no worth looking at this loop nest: give up.  */
+  /* When there are no dependences, the transformation is correct.  */
+  if (VEC_length (ddr_p, dependence_relations) == 0)
+    return true;
+
   ddr = VEC_index (ddr_p, dependence_relations, 0);
   if (ddr == NULL)
     return true;
+
+  /* When there is an unknown relation in the dependence_relations, we
+     know that it is no worth looking at this loop nest: give up.  */
   if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
     return false;
 
@@ -2595,3 +2639,196 @@ lambda_transform_legal_p (lambda_trans_matrix trans,
     }
   return true;
 }
+
+
+/* Collects parameters from affine function ACCESS_FUNCTION, and push
+   them in PARAMETERS.  */
+
+static void
+lambda_collect_parameters_from_af (tree access_function,
+                                  struct pointer_set_t *param_set,
+                                  VEC (tree, heap) **parameters)
+{
+  if (access_function == NULL)
+    return;
+
+  if (TREE_CODE (access_function) == SSA_NAME
+      && pointer_set_contains (param_set, access_function) == 0)
+    {
+      pointer_set_insert (param_set, access_function);
+      VEC_safe_push (tree, heap, *parameters, access_function);
+    }
+  else
+    {
+      int i, num_operands = tree_operand_length (access_function);
+
+      for (i = 0; i < num_operands; i++)
+       lambda_collect_parameters_from_af (TREE_OPERAND (access_function, i),
+                                          param_set, parameters);
+    }
+}
+
+/* Collects parameters from DATAREFS, and push them in PARAMETERS.  */
+
+void
+lambda_collect_parameters (VEC (data_reference_p, heap) *datarefs,
+                          VEC (tree, heap) **parameters)
+{
+  unsigned i, j;
+  struct pointer_set_t *parameter_set = pointer_set_create ();
+  data_reference_p data_reference;
+
+  for (i = 0; VEC_iterate (data_reference_p, datarefs, i, data_reference); i++)
+    for (j = 0; j < DR_NUM_DIMENSIONS (data_reference); j++)
+      lambda_collect_parameters_from_af (DR_ACCESS_FN (data_reference, j),
+                                        parameter_set, parameters);
+  pointer_set_destroy (parameter_set);
+}
+
+/* Translates BASE_EXPR to vector CY.  AM is needed for inferring
+   indexing positions in the data access vector.  CST is the analyzed
+   integer constant.  */
+
+static bool
+av_for_af_base (tree base_expr, lambda_vector cy, struct access_matrix *am,
+               int cst)
+{
+  bool result = true;
+
+  switch (TREE_CODE (base_expr))
+    {
+    case INTEGER_CST:
+      /* Constant part.  */
+      cy[AM_CONST_COLUMN_INDEX (am)] += int_cst_value (base_expr) * cst;
+      return true;
+
+    case SSA_NAME:
+      {
+       int param_index =
+         access_matrix_get_index_for_parameter (base_expr, am);
+
+       if (param_index >= 0)
+         {
+           cy[param_index] = cst + cy[param_index];
+           return true;
+         }
+
+       return false;
+      }
+
+    case PLUS_EXPR:
+      return av_for_af_base (TREE_OPERAND (base_expr, 0), cy, am, cst)
+       && av_for_af_base (TREE_OPERAND (base_expr, 1), cy, am, cst);
+
+    case MINUS_EXPR:
+      return av_for_af_base (TREE_OPERAND (base_expr, 0), cy, am, cst)
+       && av_for_af_base (TREE_OPERAND (base_expr, 1), cy, am, -1 * cst);
+
+    case MULT_EXPR:
+      if (TREE_CODE (TREE_OPERAND (base_expr, 0)) == INTEGER_CST)
+       result = av_for_af_base (TREE_OPERAND (base_expr, 1), 
+                                cy, am, cst *
+                                int_cst_value (TREE_OPERAND (base_expr, 0)));
+      else if (TREE_CODE (TREE_OPERAND (base_expr, 1)) == INTEGER_CST)
+       result = av_for_af_base (TREE_OPERAND (base_expr, 0),
+                                cy, am, cst *
+                                int_cst_value (TREE_OPERAND (base_expr, 1)));
+      else
+       result = false;
+
+      return result;
+
+    case NEGATE_EXPR:
+      return av_for_af_base (TREE_OPERAND (base_expr, 0), cy, am, -1 * cst);
+
+    default:
+      return false;
+    }
+
+  return result;
+}
+
+/* Translates ACCESS_FUN to vector CY.  AM is needed for inferring
+   indexing positions in the data access vector.  */
+
+static bool
+av_for_af (tree access_fun, lambda_vector cy, struct access_matrix *am)
+{
+  switch (TREE_CODE (access_fun))
+    {
+    case POLYNOMIAL_CHREC:
+      {
+       tree left = CHREC_LEFT (access_fun);
+       tree right = CHREC_RIGHT (access_fun);
+       unsigned var;
+
+       if (TREE_CODE (right) != INTEGER_CST)
+         return false;
+
+       var = am_vector_index_for_loop (am, CHREC_VARIABLE (access_fun));
+       cy[var] = int_cst_value (right);
+
+       if (TREE_CODE (left) == POLYNOMIAL_CHREC)
+         return av_for_af (left, cy, am);
+       else
+         return av_for_af_base (left, cy, am, 1);
+      }
+
+    case INTEGER_CST:
+      /* Constant part.  */
+      return av_for_af_base (access_fun, cy, am, 1);
+
+    default:
+      return false;
+    }
+}
+
+/* Initializes the access matrix for DATA_REFERENCE.  */
+
+static bool
+build_access_matrix (data_reference_p data_reference,
+                    VEC (tree, heap) *parameters, VEC (loop_p, heap) *nest)
+{
+  struct access_matrix *am = GGC_NEW (struct access_matrix);
+  unsigned i, ndim = DR_NUM_DIMENSIONS (data_reference);
+  unsigned nivs = VEC_length (loop_p, nest);
+  unsigned lambda_nb_columns;
+
+  AM_LOOP_NEST (am) = nest;
+  AM_NB_INDUCTION_VARS (am) = nivs;
+  AM_PARAMETERS (am) = parameters;
+
+  lambda_nb_columns = AM_NB_COLUMNS (am);
+  AM_MATRIX (am) = VEC_alloc (lambda_vector, gc, ndim);
+
+  for (i = 0; i < ndim; i++)
+    {
+      lambda_vector access_vector = lambda_vector_new (lambda_nb_columns);
+      tree access_function = DR_ACCESS_FN (data_reference, i);
+
+      if (!av_for_af (access_function, access_vector, am))
+       return false;
+
+      VEC_quick_push (lambda_vector, AM_MATRIX (am), access_vector);
+    }
+
+  DR_ACCESS_MATRIX (data_reference) = am;
+  return true;
+}
+
+/* Returns false when one of the access matrices cannot be built.  */
+
+bool
+lambda_compute_access_matrices (VEC (data_reference_p, heap) *datarefs,
+                               VEC (tree, heap) *parameters,
+                               VEC (loop_p, heap) *nest)
+{
+  data_reference_p dataref;
+  unsigned ix;
+
+  for (ix = 0; VEC_iterate (data_reference_p, datarefs, ix, dataref); ix++)
+    if (!build_access_matrix (dataref, parameters, nest))
+      return false;
+
+  return true;
+}