OSDN Git Service

2009-01-03 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / graphite.c
index 179d875..eda09f8 100644 (file)
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-scalar-evolution.h"
 #include "tree-pass.h"
 #include "domwalk.h"
+#include "value-prof.h"
 #include "pointer-set.h"
 #include "gimple.h"
 
@@ -63,9 +64,9 @@ static VEC (scop_p, heap) *current_scops;
 /* Converts a GMP constant V to a tree and returns it.  */
 
 static tree
-gmp_cst_to_tree (Value v)
+gmp_cst_to_tree (tree type, Value v)
 {
-  return build_int_cst (integer_type_node, value_get_si (v));
+  return build_int_cst (type, value_get_si (v));
 }
 
 /* Debug the list of old induction variables for this SCOP.  */
@@ -167,13 +168,9 @@ static tree
 loop_iv_stack_get_iv (loop_iv_stack stack, int index)
 {
   iv_stack_entry_p entry = VEC_index (iv_stack_entry_p, *stack, index);
+  iv_stack_entry_data data = entry->data;
 
-  tree result = NULL;
-
-  if (entry->kind != iv_stack_entry_const)
-    result = entry->data.iv->t;
-
-  return result;
+  return iv_stack_entry_is_iv (entry) ? data.iv->t : data.constant;
 }
 
 /* Get the IV from its NAME in STACK.  */
@@ -247,6 +244,98 @@ free_loop_iv_stack (loop_iv_stack stack)
   VEC_free (iv_stack_entry_p, heap, *stack);
 }
 
+\f
+
+/* Structure containing the mapping between the CLooG's induction
+   variable and the type of the old induction variable.  */
+typedef struct ivtype_map_elt
+{
+  tree type;
+  const char *cloog_iv;
+} *ivtype_map_elt;
+
+/* Print to stderr the element ELT.  */
+
+static void
+debug_ivtype_elt (ivtype_map_elt elt)
+{
+  fprintf (stderr, "(%s, ", elt->cloog_iv);
+  print_generic_expr (stderr, elt->type, 0);
+  fprintf (stderr, ")\n");
+}
+
+/* Helper function for debug_ivtype_map.  */
+
+static int
+debug_ivtype_map_1 (void **slot, void *s ATTRIBUTE_UNUSED)
+{
+  struct ivtype_map_elt *entry = (struct ivtype_map_elt *) *slot;
+  debug_ivtype_elt (entry);
+  return 1;
+}
+
+/* Print to stderr all the elements of MAP.  */
+
+void
+debug_ivtype_map (htab_t map)
+{
+  htab_traverse (map, debug_ivtype_map_1, NULL);
+}
+
+/* Constructs a new SCEV_INFO_STR structure for VAR and INSTANTIATED_BELOW.  */
+
+static inline ivtype_map_elt
+new_ivtype_map_elt (const char *cloog_iv, tree type)
+{
+  ivtype_map_elt res;
+  
+  res = XNEW (struct ivtype_map_elt);
+  res->cloog_iv = cloog_iv;
+  res->type = type;
+
+  return res;
+}
+
+/* Computes a hash function for database element ELT.  */
+
+static hashval_t
+ivtype_map_elt_info (const void *elt)
+{
+  return htab_hash_pointer (((const struct ivtype_map_elt *) elt)->cloog_iv);
+}
+
+/* Compares database elements E1 and E2.  */
+
+static int
+eq_ivtype_map_elts (const void *e1, const void *e2)
+{
+  const struct ivtype_map_elt *elt1 = (const struct ivtype_map_elt *) e1;
+  const struct ivtype_map_elt *elt2 = (const struct ivtype_map_elt *) e2;
+
+  return (elt1->cloog_iv == elt2->cloog_iv);
+}
+
+\f
+
+/* Given a CLOOG_IV, returns the type that it should have in GCC land.
+   If the information is not available, i.e. in the case one of the
+   transforms created the loop, just return integer_type_node.  */
+
+static tree
+gcc_type_for_cloog_iv (const char *cloog_iv, graphite_bb_p gbb)
+{
+  struct ivtype_map_elt tmp;
+  PTR *slot;
+
+  tmp.cloog_iv = cloog_iv;
+  slot = htab_find_slot (GBB_CLOOG_IV_TYPES (gbb), &tmp, NO_INSERT);
+
+  if (slot && *slot)
+    return ((ivtype_map_elt) *slot)->type;
+
+  return integer_type_node;
+}
+
 /* Inserts constants derived from the USER_STMT argument list into the
    STACK.  This is needed to map old ivs to constants when loops have
    been eliminated.  */
@@ -257,16 +346,23 @@ loop_iv_stack_patch_for_consts (loop_iv_stack stack,
 {
   struct clast_stmt *t;
   int index = 0;
+  CloogStatement *cs = user_stmt->statement;
+  graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs);
+
   for (t = user_stmt->substitutions; t; t = t->next) 
     {
-      struct clast_term *term = (struct clast_term*) 
+      struct clast_expr *expr = (struct clast_expr *) 
        ((struct clast_assignment *)t)->RHS;
+      struct clast_term *term = (struct clast_term *) expr;
 
       /* FIXME: What should be done with expr_bin, expr_red?  */
-      if (((struct clast_assignment *)t)->RHS->type == expr_term
+      if (expr->type == expr_term
          && !term->var)
        {
-         tree value = gmp_cst_to_tree (term->val);
+         loop_p loop = gbb_loop_at_index (gbb, index);
+         tree oldiv = oldiv_for_loop (GBB_SCOP (gbb), loop);
+         tree type = oldiv ? TREE_TYPE (oldiv) : integer_type_node;
+         tree value = gmp_cst_to_tree (type, term->val);
          loop_iv_stack_insert_constant (stack, index, value);
        }
       index = index + 1;
@@ -293,33 +389,6 @@ loop_iv_stack_remove_constants (loop_iv_stack stack)
     }
 }
 
-/* In SCOP, get the induction variable from NAME.  OLD is the original
-   loop that contained the definition of NAME.  */
-
-static name_tree
-get_old_iv_from_ssa_name (scop_p scop, loop_p old, tree name)
-{
-  tree var = SSA_NAME_VAR (name);
-  int i;
-  name_tree oldiv;
-  
-  for (i = 0; VEC_iterate (name_tree, SCOP_OLDIVS (scop), i, oldiv); i++)
-    {
-      loop_p current = old;
-
-      while (current)
-       {
-         if (var == oldiv->t
-             && oldiv->loop == current)
-           return oldiv;
-
-         current = loop_outer (current);
-       }
-    }
-  return NULL;
-
-}
-
 /* Returns a new loop_to_cloog_loop_str structure.  */
 
 static inline struct loop_to_cloog_loop_str *
@@ -495,7 +564,7 @@ print_graphite_bb (FILE *file, graphite_bb_p gb, int indent, int verbosity)
   if (GBB_DOMAIN (gb))
     {
       fprintf (file, "       (domain: \n");
-      cloog_matrix_print (dump_file, GBB_DOMAIN (gb));
+      cloog_matrix_print (file, GBB_DOMAIN (gb));
       fprintf (file, "       )\n");
     }
 
@@ -525,7 +594,7 @@ print_graphite_bb (FILE *file, graphite_bb_p gb, int indent, int verbosity)
   if (GBB_CONDITIONS (gb))
     {
       fprintf (file, "       (conditions: \n");
-      dump_gbb_conditions (dump_file, gb);
+      dump_gbb_conditions (file, gb);
       fprintf (file, "       )\n");
     }
 
@@ -610,14 +679,6 @@ debug_scops (int verbosity)
   print_scops (stderr, verbosity);
 }
 
-/* Return true when BB is contained in SCOP.  */
-
-static inline bool
-bb_in_scop_p (basic_block bb, scop_p scop)
-{
-  return bitmap_bit_p (SCOP_BBS_B (scop), bb->index);
-}
-
 /* Pretty print to FILE the SCOP in DOT format.  */
 
 static void 
@@ -818,15 +879,6 @@ dot_all_scops (void)
 #endif
 }
 
-/* Returns true when LOOP is in SCOP.  */
-
-static inline bool 
-loop_in_scop_p (struct loop *loop, scop_p scop)
-{
-  return (bb_in_scop_p (loop->header, scop)
-         && bb_in_scop_p (loop->latch, scop));
-}
-
 /* Returns the outermost loop in SCOP that contains BB.  */
 
 static struct loop *
@@ -1025,23 +1077,87 @@ harmful_stmt_in_bb (basic_block scop_entry, basic_block bb)
   return NULL;
 }
 
+/* Returns true when BB will be represented in graphite.  Return false
+   for the basic blocks that contain code eliminated in the code
+   generation pass: i.e. induction variables and exit conditions.  */
+
+static bool
+graphite_stmt_p (scop_p scop, basic_block bb,
+                VEC (data_reference_p, heap) *drs)
+{
+  gimple_stmt_iterator gsi;
+  loop_p loop = bb->loop_father;
+
+  if (VEC_length (data_reference_p, drs) > 0)
+    return true;
+
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple stmt = gsi_stmt (gsi);
+
+      switch (gimple_code (stmt))
+        {
+          /* Control flow expressions can be ignored, as they are
+             represented in the iteration domains and will be
+             regenerated by graphite.  */
+       case GIMPLE_COND:
+       case GIMPLE_GOTO:
+       case GIMPLE_SWITCH:
+         break;
+
+       case GIMPLE_ASSIGN:
+         {
+           tree var = gimple_assign_lhs (stmt);
+           var = analyze_scalar_evolution (loop, var);
+           var = instantiate_scev (block_before_scop (scop), loop, var);
+
+           if (chrec_contains_undetermined (var))
+             return true;
+
+           break;
+         }
+
+       default:
+         return true;
+        }
+    }
+
+  return false;
+}
+
 /* Store the GRAPHITE representation of BB.  */
 
 static void
 new_graphite_bb (scop_p scop, basic_block bb)
 {
-  struct graphite_bb *gbb = XNEW (struct graphite_bb);
+  struct graphite_bb *gbb;
+  VEC (data_reference_p, heap) *drs = VEC_alloc (data_reference_p, heap, 5);
+  struct loop *nest = outermost_loop_in_scop (scop, bb);
+  gimple_stmt_iterator gsi;
+
+  bitmap_set_bit (SCOP_BBS_B (scop), bb->index);
+
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    find_data_references_in_stmt (nest, gsi_stmt (gsi), &drs);
+
+  if (!graphite_stmt_p (scop, bb, drs))
+    {
+      free_data_refs (drs);
+      return;
+    }
 
+  gbb = XNEW (struct graphite_bb);
   bb->aux = gbb;
   GBB_BB (gbb) = bb;
   GBB_SCOP (gbb) = scop;
-  GBB_DATA_REFS (gbb) = NULL; 
+  GBB_DATA_REFS (gbb) = drs;
   GBB_DOMAIN (gbb) = NULL;
   GBB_CONDITIONS (gbb) = NULL;
   GBB_CONDITION_CASES (gbb) = NULL;
   GBB_LOOPS (gbb) = NULL;
+  GBB_STATIC_SCHEDULE (gbb) = NULL;
+  GBB_CLOOG_IV_TYPES (gbb) = NULL;
   VEC_safe_push (graphite_bb_p, heap, SCOP_BBS (scop), gbb);
-  bitmap_set_bit (SCOP_BBS_B (scop), bb->index);
 }
 
 /* Frees GBB.  */
@@ -1052,15 +1168,41 @@ free_graphite_bb (struct graphite_bb *gbb)
   if (GBB_DOMAIN (gbb))
     cloog_matrix_free (GBB_DOMAIN (gbb));
 
-  free_data_refs (GBB_DATA_REFS (gbb));
+  if (GBB_CLOOG_IV_TYPES (gbb))
+    htab_delete (GBB_CLOOG_IV_TYPES (gbb));
+
+  /* FIXME: free_data_refs is disabled for the moment, but should be
+     enabled.
+
+     free_data_refs (GBB_DATA_REFS (gbb)); */
+
   VEC_free (gimple, heap, GBB_CONDITIONS (gbb));
   VEC_free (gimple, heap, GBB_CONDITION_CASES (gbb));
   VEC_free (loop_p, heap, GBB_LOOPS (gbb));
-
   GBB_BB (gbb)->aux = 0;
   XDELETE (gbb);
 }
 
+/* Register basic blocks belonging to a region in a pointer set.  */
+
+static void
+register_bb_in_sese (basic_block entry_bb, basic_block exit_bb, sese region)
+{
+  edge_iterator ei;
+  edge e;
+  basic_block bb = entry_bb;
+
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    {
+      if (!pointer_set_contains (SESE_REGION_BBS (region), e->dest) &&
+         e->dest->index != exit_bb->index)
+       {       
+         pointer_set_insert (SESE_REGION_BBS (region), e->dest);
+         register_bb_in_sese (e->dest, exit_bb, region);
+       }
+    }
+}
+
 /* Creates a new scop starting with ENTRY.  */
 
 static scop_p
@@ -1073,11 +1215,15 @@ new_scop (edge entry, edge exit)
   SCOP_REGION (scop) = XNEW (struct sese);
   SESE_ENTRY (SCOP_REGION (scop)) = entry;
   SESE_EXIT (SCOP_REGION (scop)) = exit;
+  SESE_REGION_BBS (SCOP_REGION (scop)) = pointer_set_create ();
+  register_bb_in_sese (SCOP_ENTRY (scop), SCOP_EXIT (scop),
+                      SCOP_REGION (scop));
   SCOP_BBS (scop) = VEC_alloc (graphite_bb_p, heap, 3);
   SCOP_OLDIVS (scop) = VEC_alloc (name_tree, heap, 3);
   SCOP_BBS_B (scop) = BITMAP_ALLOC (NULL);
   SCOP_LOOPS (scop) = BITMAP_ALLOC (NULL);
   SCOP_LOOP_NEST (scop) = VEC_alloc (loop_p, heap, 3);
+  SCOP_ADD_PARAMS (scop) = true;
   SCOP_PARAMS (scop) = VEC_alloc (name_tree, heap, 3);
   SCOP_PROG (scop) = cloog_program_malloc ();
   cloog_program_set_names (SCOP_PROG (scop), cloog_names_malloc ());
@@ -1499,7 +1645,6 @@ scopdet_basic_block_info (basic_block bb, VEC (sd_region, heap) **scops,
 static struct scopdet_info 
 build_scops_1 (basic_block current, VEC (sd_region, heap) **scops, loop_p loop)
 {
-
   bool in_scop = false;
   sd_region open_scop;
   struct scopdet_info sinfo;
@@ -1511,6 +1656,8 @@ build_scops_1 (basic_block current, VEC (sd_region, heap) **scops, loop_p loop)
   result.next = NULL;
   result.last = NULL;
   open_scop.entry = NULL;
+  open_scop.exit = NULL;
+  sinfo.last = NULL;
 
   /* Loop over the dominance tree.  If we meet a difficult bb, close
      the current SCoP.  Loop and condition header start a new layer,
@@ -1799,6 +1946,29 @@ mark_exit_edges (VEC (sd_region, heap) *regions)
        e->aux = s;
 }
 
+/* Free and compute again all the dominators information.  */
+
+static inline void
+recompute_all_dominators (void)
+{
+  free_dominance_info (CDI_DOMINATORS);
+  free_dominance_info (CDI_POST_DOMINATORS);
+  calculate_dominance_info (CDI_DOMINATORS);
+  calculate_dominance_info (CDI_POST_DOMINATORS);
+}
+
+/* Verifies properties that GRAPHITE should maintain during translation.  */
+
+static inline void
+graphite_verify (void)
+{
+#ifdef ENABLE_CHECKING
+  verify_loop_structure ();
+  verify_dominators (CDI_DOMINATORS);
+  verify_dominators (CDI_POST_DOMINATORS);
+  verify_ssa (false);
+#endif
+}
 
 /* Create for all scop regions a single entry and a single exit edge.  */
 
@@ -1937,64 +2107,109 @@ build_scop_bbs (scop_p scop)
   sbitmap_free (visited);
 }
 
+/* Returns the number of reduction phi nodes in LOOP.  */
+
+static int
+nb_reductions_in_loop (loop_p loop)
+{
+  int res = 0;
+  gimple_stmt_iterator gsi;
 
-/* Record LOOP as occuring in SCOP.  */
+  for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple phi = gsi_stmt (gsi);
+      tree scev;
+      affine_iv iv;
 
-static void
-scop_record_loop (scop_p scop, struct loop *loop)
+      if (!is_gimple_reg (PHI_RESULT (phi)))
+       continue;
+
+      scev = analyze_scalar_evolution (loop, PHI_RESULT (phi));
+      scev = instantiate_parameters (loop, scev);
+      if (!simple_iv (loop, phi, PHI_RESULT (phi), &iv, true))
+       res++;
+    }
+
+  return res;
+}
+
+/* A LOOP is in normal form when it contains only one scalar phi node
+   that defines the main induction variable of the loop, only one
+   increment of the IV, and only one exit condition. */
+
+static tree
+graphite_loop_normal_form (loop_p loop)
 {
-  loop_p parent;
-  tree induction_var;
+  struct tree_niter_desc niter;
+  tree nit;
+  gimple_seq stmts;
+  edge exit = single_dom_exit (loop);
 
-  if (bitmap_bit_p (SCOP_LOOPS (scop), loop->num))
-    return;
+  if (!number_of_iterations_exit (loop, exit, &niter, false))
+    gcc_unreachable ();
 
-  parent = loop_outer (loop);
-  induction_var = find_induction_var_from_exit_cond (loop);
+  nit = force_gimple_operand (unshare_expr (niter.niter), &stmts, true,
+                             NULL_TREE);
+  if (stmts)
+    gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
 
-  if (!bb_in_scop_p (parent->latch, scop))
-    parent = NULL;
+  /* One IV per loop.  */
+  if (nb_reductions_in_loop (loop) > 0)
+    return NULL_TREE;
 
-  if (induction_var != NULL_TREE)
-    {
-      name_tree oldiv = XNEW (struct name_tree);
-      oldiv->t = SSA_NAME_VAR (induction_var);
-      if (DECL_NAME (oldiv->t))
-       oldiv->name = IDENTIFIER_POINTER (DECL_NAME (oldiv->t));
-      else
-       {
-         int len = 2 + 16;
-         char *n = XNEWVEC (char, len);
-         snprintf (n, len, "D.%u", DECL_UID (oldiv->t));
-         oldiv->name = n;
-       }
-      oldiv->loop = loop;
+  return canonicalize_loop_ivs (loop, NULL, nit);
+}
 
-      VEC_safe_push (name_tree, heap, SCOP_OLDIVS (scop), oldiv);
-    }
+/* Record LOOP as occuring in SCOP.  Returns true when the operation
+   was successful.  */
+
+static bool
+scop_record_loop (scop_p scop, loop_p loop)
+{
+  tree induction_var;
+  name_tree oldiv;
+
+  if (bitmap_bit_p (SCOP_LOOPS (scop), loop->num))
+    return true;
 
   bitmap_set_bit (SCOP_LOOPS (scop), loop->num);
   VEC_safe_push (loop_p, heap, SCOP_LOOP_NEST (scop), loop);
+
+  induction_var = graphite_loop_normal_form (loop);
+  if (!induction_var)
+    return false;
+
+  oldiv = XNEW (struct name_tree);
+  oldiv->t = induction_var;
+  oldiv->name = get_name (SSA_NAME_VAR (oldiv->t));
+  oldiv->loop = loop;
+  VEC_safe_push (name_tree, heap, SCOP_OLDIVS (scop), oldiv);
+  return true;
 }
 
-/* Build the loop nests contained in SCOP.  */
+/* Build the loop nests contained in SCOP.  Returns true when the
+   operation was successful.  */
 
-static void
+static bool
 build_scop_loop_nests (scop_p scop)
 {
   unsigned i;
-  graphite_bb_p gb;
+  basic_block bb;
   struct loop *loop0, *loop1;
 
-  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
-    {
-      struct loop *loop = gbb_loop (gb);
+  FOR_EACH_BB (bb)
+    if (bb_in_scop_p (bb, scop))
+      {
+       struct loop *loop = bb->loop_father;
 
-      /* Only add loops, if they are completely contained in the SCoP.  */
-      if (loop->header == GBB_BB (gb)
-         && bb_in_scop_p (loop->latch, scop))
-        scop_record_loop (scop, gbb_loop (gb));
-    }
+       /* Only add loops if they are completely contained in the SCoP.  */
+       if (loop->header == bb
+           && bb_in_scop_p (loop->latch, scop))
+         {
+           if (!scop_record_loop (scop, loop))
+             return false;
+         }
+      }
 
   /* Make sure that the loops in the SCOP_LOOP_NEST are ordered.  It
      can be the case that an inner loop is inserted before an outer
@@ -2011,20 +2226,37 @@ build_scop_loop_nests (scop_p scop)
          VEC_replace (loop_p, SCOP_LOOP_NEST (scop), i + 1, loop0);
        }
     }
+
+  return true;
 }
 
-/* Calculate the number of loops around GB in the current SCOP.  */
+/* Build dynamic schedules for all the BBs. */
 
-static inline int
-nb_loops_around_gb (graphite_bb_p gb)
+static void
+build_scop_dynamic_schedules (scop_p scop)
 {
-  scop_p scop = GBB_SCOP (gb);
-  struct loop *l = gbb_loop (gb);
-  int d = 0;
+  int i, dim, loop_num, row, col;
+  graphite_bb_p gb;
 
-  for (; loop_in_scop_p (l, scop); d++, l = loop_outer (l));
+  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
+    {
+      loop_num = GBB_BB (gb)->loop_father->num;
 
-  return d;
+      if (loop_num != 0)
+        {
+          dim = nb_loops_around_gb (gb);
+          GBB_DYNAMIC_SCHEDULE (gb) = cloog_matrix_alloc (dim, dim);
+
+          for (row = 0; row < GBB_DYNAMIC_SCHEDULE (gb)->NbRows; row++)
+            for (col = 0; col < GBB_DYNAMIC_SCHEDULE (gb)->NbColumns; col++)
+              if (row == col)
+                value_set_si (GBB_DYNAMIC_SCHEDULE (gb)->p[row][col], 1);
+              else
+                value_set_si (GBB_DYNAMIC_SCHEDULE (gb)->p[row][col], 0);
+        }
+      else
+        GBB_DYNAMIC_SCHEDULE (gb) = NULL;
+    }
 }
 
 /* Build for BB the static schedule.
@@ -2138,6 +2370,8 @@ param_index (tree var, scop_p scop)
     if (p->t == var)
       return i;
 
+  gcc_assert (SCOP_ADD_PARAMS (scop));
+
   nvar = XNEW (struct name_tree);
   nvar->t = var;
   nvar->name = NULL;
@@ -2217,26 +2451,28 @@ scan_tree_for_params (scop_p s, tree e, CloogMatrix *c, int r, Value k,
     case MULT_EXPR:
       if (chrec_contains_symbols (TREE_OPERAND (e, 0)))
        {
-         Value val;
-
-         gcc_assert (host_integerp (TREE_OPERAND (e, 1), 0));
-
-         value_init (val);
-         value_set_si (val, int_cst_value (TREE_OPERAND (e, 1)));
-         value_multiply (k, k, val);
-         value_clear (val);
+         if (c)
+           {
+             Value val;
+             gcc_assert (host_integerp (TREE_OPERAND (e, 1), 0));
+             value_init (val);
+             value_set_si (val, int_cst_value (TREE_OPERAND (e, 1)));
+             value_multiply (k, k, val);
+             value_clear (val);
+           }
          scan_tree_for_params (s, TREE_OPERAND (e, 0), c, r, k, subtract);
        }
       else
        {
-         Value val;
-
-         gcc_assert (host_integerp (TREE_OPERAND (e, 0), 0));
-
-         value_init (val);
-         value_set_si (val, int_cst_value (TREE_OPERAND (e, 0)));
-         value_multiply (k, k, val);
-         value_clear (val);
+         if (c)
+           {
+             Value val;
+             gcc_assert (host_integerp (TREE_OPERAND (e, 0), 0));
+             value_init (val);
+             value_set_si (val, int_cst_value (TREE_OPERAND (e, 0)));
+             value_multiply (k, k, val);
+             value_clear (val);
+           }
          scan_tree_for_params (s, TREE_OPERAND (e, 1), c, r, k, subtract);
        }
       break;
@@ -2347,58 +2583,43 @@ idx_record_params (tree base, tree *idx, void *dta)
    access functions, conditions and loop bounds.  */
 
 static void
-find_params_in_bb (scop_p scop, basic_block bb)
+find_params_in_bb (scop_p scop, graphite_bb_p gb)
 {
   int i;
   data_reference_p dr;
-  VEC (data_reference_p, heap) *drs;
-  gimple_stmt_iterator gsi;
-  struct loop *nest = outermost_loop_in_scop (scop, bb);
-
-  /* Find the parameters used in the memory access functions.  */
-  drs = VEC_alloc (data_reference_p, heap, 5);
-  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-    find_data_references_in_stmt (nest, gsi_stmt (gsi), &drs);
+  gimple stmt;
+  loop_p father = GBB_BB (gb)->loop_father;
 
-  for (i = 0; VEC_iterate (data_reference_p, drs, i, dr); i++)
+  for (i = 0; VEC_iterate (data_reference_p, GBB_DATA_REFS (gb), i, dr); i++)
     {
       struct irp_data irp;
 
-      irp.loop = bb->loop_father;
+      irp.loop = father;
       irp.scop = scop;
       for_each_index (&dr->ref, idx_record_params, &irp);
-      free_data_ref (dr);
     }
 
-  VEC_free (data_reference_p, heap, drs);
-
   /* Find parameters in conditional statements.  */ 
-  gsi = gsi_last_bb (bb);
-  if (!gsi_end_p (gsi))
+  for (i = 0; VEC_iterate (gimple, GBB_CONDITIONS (gb), i, stmt); i++)
     {
-      gimple stmt = gsi_stmt (gsi);
+      Value one;
+      loop_p loop = father;
 
-      if (gimple_code (stmt) == GIMPLE_COND)
-        {
-          Value one;
-          loop_p loop = bb->loop_father;
-
-          tree lhs, rhs;
-          
-          lhs = gimple_cond_lhs (stmt);
-          lhs = analyze_scalar_evolution (loop, lhs);
-          lhs = instantiate_scev (block_before_scop (scop), loop, lhs);
-
-          rhs = gimple_cond_rhs (stmt);
-          rhs = analyze_scalar_evolution (loop, rhs);
-          rhs = instantiate_scev (block_before_scop (scop), loop, rhs);
-
-          value_init (one);
-          scan_tree_for_params (scop, lhs, NULL, 0, one, false);
-          value_set_si (one, 1);
-          scan_tree_for_params (scop, rhs, NULL, 0, one, false);
-          value_clear (one);
-       }
+      tree lhs, rhs;
+
+      lhs = gimple_cond_lhs (stmt);
+      lhs = analyze_scalar_evolution (loop, lhs);
+      lhs = instantiate_scev (block_before_scop (scop), loop, lhs);
+
+      rhs = gimple_cond_rhs (stmt);
+      rhs = analyze_scalar_evolution (loop, rhs);
+      rhs = instantiate_scev (block_before_scop (scop), loop, rhs);
+
+      value_init (one);
+      scan_tree_for_params (scop, lhs, NULL, 0, one, false);
+      value_set_si (one, 1);
+      scan_tree_for_params (scop, rhs, NULL, 0, one, false);
+      value_clear (one);
     }
 }
 
@@ -2522,7 +2743,9 @@ find_scop_parameters (scop_p scop)
 
   /* Find the parameters used in data accesses.  */
   for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
-    find_params_in_bb (scop, GBB_BB (gb));
+    find_params_in_bb (scop, gb);
+
+  SCOP_ADD_PARAMS (scop) = false;
 }
 
 /* Build the context constraints for SCOP: constraints and relations
@@ -2554,24 +2777,6 @@ gbb_from_bb (basic_block bb)
   return (graphite_bb_p) bb->aux;
 }
 
-/* Add DOMAIN to all the basic blocks in LOOP.  */
-
-static void
-add_bb_domains (struct loop *loop, CloogMatrix *domain)
-{
-  basic_block *bbs = get_loop_body (loop);
-  unsigned i;
-
-  for (i = 0; i < loop->num_nodes; i++)
-    if (bbs[i]->loop_father == loop)
-      {
-        graphite_bb_p gbb = gbb_from_bb (bbs[i]);
-        GBB_DOMAIN (gbb) = cloog_matrix_copy (domain);
-      }
-
-  free (bbs);
-}
-
 /* Builds the constraint matrix for LOOP in SCOP.  NB_OUTER_LOOPS is the
    number of loops surrounding LOOP in SCOP.  OUTER_CSTR gives the
    constraints matrix for the surrounding loops.  */
@@ -2582,6 +2787,7 @@ build_loop_iteration_domains (scop_p scop, struct loop *loop,
 {
   int i, j, row;
   CloogMatrix *cstr;
+  graphite_bb_p gb;
 
   int nb_rows = outer_cstr->NbRows + 1;
   int nb_cols = outer_cstr->NbColumns + 1;
@@ -2662,7 +2868,9 @@ build_loop_iteration_domains (scop_p scop, struct loop *loop,
   if (nb_outer_loops != 0 && loop->next && loop_in_scop_p (loop->next, scop))
     build_loop_iteration_domains (scop, loop->next, outer_cstr, nb_outer_loops);
 
-  add_bb_domains (loop, cstr);
+  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
+    if (gbb_loop (gb) == loop)
+      GBB_DOMAIN (gb) = cloog_matrix_copy (cstr);
 
   cloog_matrix_free (cstr);
 }
@@ -2884,10 +3092,12 @@ build_scop_conditions_1 (VEC (gimple, heap) **conditions,
 
   /* Record conditions in graphite_bb.  */
   gbb = gbb_from_bb (bb);
-  GBB_CONDITIONS (gbb) = VEC_copy (gimple, heap, *conditions);
-  GBB_CONDITION_CASES (gbb) = VEC_copy (gimple, heap, *cases);
-
-  add_conditions_to_domain (gbb);
+  if (gbb)
+    {
+      GBB_CONDITIONS (gbb) = VEC_copy (gimple, heap, *conditions);
+      GBB_CONDITION_CASES (gbb) = VEC_copy (gimple, heap, *cases);
+      add_conditions_to_domain (gbb);
+    }
 
   dom = get_dominated_by (CDI_DOMINATORS, bb);
 
@@ -3049,27 +3259,31 @@ build_scop_iteration_domain (scop_p scop)
 }
 
 /* Initializes an equation CY of the access matrix using the
-   information for a subscript from ACCESS_FUN, relatively to the loop
+   information for a subscript from AF, relatively to the loop
    indexes from LOOP_NEST and parameter indexes from PARAMS.  NDIM is
    the dimension of the array access, i.e. the number of
    subscripts.  Returns true when the operation succeeds.  */
 
 static bool
-build_access_matrix_with_af (tree access_fun, lambda_vector cy,
+build_access_matrix_with_af (tree af, lambda_vector cy,
                             scop_p scop, int ndim)
 {
-  switch (TREE_CODE (access_fun))
+  int param_col;
+
+  switch (TREE_CODE (af))
     {
     case POLYNOMIAL_CHREC:
       {
-       tree left = CHREC_LEFT (access_fun);
-       tree right = CHREC_RIGHT (access_fun);
+        struct loop *outer_loop;
+       tree left = CHREC_LEFT (af);
+       tree right = CHREC_RIGHT (af);
        int var;
 
        if (TREE_CODE (right) != INTEGER_CST)
          return false;
-        
-       var = loop_iteration_vector_dim (CHREC_VARIABLE (access_fun), scop);
+
+        outer_loop = get_loop (CHREC_VARIABLE (af));
+        var = nb_loops_around_loop_in_scop (outer_loop, scop);
        cy[var] = int_cst_value (right);
 
        switch (TREE_CODE (left))
@@ -3082,12 +3296,27 @@ build_access_matrix_with_af (tree access_fun, lambda_vector cy,
            return true;
 
          default:
-           /* FIXME: access_fn can have parameters.  */
-           return false;
+           return build_access_matrix_with_af (left, cy, scop, ndim);
          }
       }
+
+    case PLUS_EXPR:
+      build_access_matrix_with_af (TREE_OPERAND (af, 0), cy, scop, ndim);
+      build_access_matrix_with_af (TREE_OPERAND (af, 1), cy, scop, ndim);
+      return true;
+      
+    case MINUS_EXPR:
+      build_access_matrix_with_af (TREE_OPERAND (af, 0), cy, scop, ndim);
+      build_access_matrix_with_af (TREE_OPERAND (af, 1), cy, scop, ndim);
+      return true;
+
     case INTEGER_CST:
-      cy[ndim - 1] = int_cst_value (access_fun);
+      cy[ndim - 1] = int_cst_value (af);
+      return true;
+
+    case SSA_NAME:
+      param_col = param_index (af, scop);      
+      cy [ndim - scop_nb_params (scop) + param_col - 1] = 1; 
       return true;
 
     default:
@@ -3133,23 +3362,14 @@ build_scop_data_accesses (scop_p scop)
   int i;
   graphite_bb_p gb;
 
+  /* FIXME: Construction of access matrix is disabled until some
+     pass, like the data dependence analysis, is using it.  */
+  return;
+
   for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
     {
       int j;
-      gimple_stmt_iterator gsi;
       data_reference_p dr;
-      struct loop *nest = outermost_loop_in_scop (scop, GBB_BB (gb));
-
-      /* On each statement of the basic block, gather all the occurences
-        to read/write memory.  */
-      GBB_DATA_REFS (gb) = VEC_alloc (data_reference_p, heap, 5);
-      for (gsi = gsi_start_bb (GBB_BB (gb)); !gsi_end_p (gsi); gsi_next (&gsi))
-       find_data_references_in_stmt (nest, gsi_stmt (gsi),
-                                     &GBB_DATA_REFS (gb));
-
-      /* FIXME: Construction of access matrix is disabled until some
-        pass, like the data dependence analysis, is using it.  */
-      continue;
 
       /* Construct the access matrix for each data ref, with respect to
         the loop nest of the current BB in the considered SCOP.  */
@@ -3188,9 +3408,10 @@ clast_name_to_gcc (const char *name, VEC (name_tree, heap) *params,
   name_tree t;
   tree iv;
 
-  for (i = 0; VEC_iterate (name_tree, params, i, t); i++)
-    if (!strcmp (name, t->name))
-      return t->t;
+  if (params)
+    for (i = 0; VEC_iterate (name_tree, params, i, t); i++)
+      if (!strcmp (name, t->name))
+       return t->t;
 
   iv = loop_iv_stack_get_iv_from_name (ivstack, name);
   if (iv)
@@ -3199,17 +3420,24 @@ clast_name_to_gcc (const char *name, VEC (name_tree, heap) *params,
   gcc_unreachable ();
 }
 
-/* Converts a Cloog AST expression E back to a GCC expression tree.   */
+/* Returns the maximal precision type for expressions E1 and E2.  */
+
+static inline tree
+max_precision_type (tree e1, tree e2)
+{
+  tree type1 = TREE_TYPE (e1);
+  tree type2 = TREE_TYPE (e2);
+  return TYPE_PRECISION (type1) > TYPE_PRECISION (type2) ? type1 : type2;
+}
+
+/* Converts a Cloog AST expression E back to a GCC expression tree
+   of type TYPE.  */
 
 static tree
-clast_to_gcc_expression (struct clast_expr *e,
+clast_to_gcc_expression (tree type, struct clast_expr *e,
                         VEC (name_tree, heap) *params,
                         loop_iv_stack ivstack)
 {
-  tree type = integer_type_node;
-
-  gcc_assert (e);
-
   switch (e->type)
     {
     case expr_term:
@@ -3219,53 +3447,62 @@ clast_to_gcc_expression (struct clast_expr *e,
        if (t->var)
          {
            if (value_one_p (t->val))
-             return clast_name_to_gcc (t->var, params, ivstack);
+             {
+               tree name = clast_name_to_gcc (t->var, params, ivstack);
+               return fold_convert (type, name);
+             }
 
            else if (value_mone_p (t->val))
-             return fold_build1 (NEGATE_EXPR, type,
-                                 clast_name_to_gcc (t->var, params, ivstack));
+             {
+               tree name = clast_name_to_gcc (t->var, params, ivstack);
+               name = fold_convert (type, name);
+               return fold_build1 (NEGATE_EXPR, type, name);
+             }
            else
-             return fold_build2 (MULT_EXPR, type,
-                                 gmp_cst_to_tree (t->val),
-                                 clast_name_to_gcc (t->var, params, ivstack));
+             {
+               tree name = clast_name_to_gcc (t->var, params, ivstack);
+               tree cst = gmp_cst_to_tree (type, t->val);
+               name = fold_convert (type, name);
+               return fold_build2 (MULT_EXPR, type, cst, name);
+             }
          }
        else
-         return gmp_cst_to_tree (t->val);
+         return gmp_cst_to_tree (type, t->val);
       }
 
     case expr_red:
       {
         struct clast_reduction *r = (struct clast_reduction *) e;
-        tree left, right;
 
         switch (r->type)
           {
          case clast_red_sum:
            if (r->n == 1)
-             return clast_to_gcc_expression (r->elts[0], params, ivstack);
+             return clast_to_gcc_expression (type, r->elts[0], params, ivstack);
 
            else 
              {
+               tree tl = clast_to_gcc_expression (type, r->elts[0], params, ivstack);
+               tree tr = clast_to_gcc_expression (type, r->elts[1], params, ivstack);
+
                gcc_assert (r->n >= 1
                            && r->elts[0]->type == expr_term
                            && r->elts[1]->type == expr_term);
 
-               left = clast_to_gcc_expression (r->elts[0], params, ivstack);
-               right = clast_to_gcc_expression (r->elts[1], params, ivstack);
-               return fold_build2 (PLUS_EXPR, type, left, right);
+               return fold_build2 (PLUS_EXPR, type, tl, tr);
              }
 
            break;
 
          case clast_red_min:
            if (r->n == 1)
-             return clast_to_gcc_expression (r->elts[0], params, ivstack);
+             return clast_to_gcc_expression (type, r->elts[0], params, ivstack);
 
            else if (r->n == 2)
              {
-               left = clast_to_gcc_expression (r->elts[0], params, ivstack);
-               right = clast_to_gcc_expression (r->elts[1], params, ivstack);
-               return fold_build2 (MIN_EXPR, type, left, right);
+               tree tl = clast_to_gcc_expression (type, r->elts[0], params, ivstack);
+               tree tr = clast_to_gcc_expression (type, r->elts[1], params, ivstack);
+               return fold_build2 (MIN_EXPR, type, tl, tr);
              }
 
            else
@@ -3275,13 +3512,13 @@ clast_to_gcc_expression (struct clast_expr *e,
 
          case clast_red_max:
            if (r->n == 1)
-             return clast_to_gcc_expression (r->elts[0], params, ivstack);
+             return clast_to_gcc_expression (type, r->elts[0], params, ivstack);
 
            else if (r->n == 2)
              {
-               left = clast_to_gcc_expression (r->elts[0], params, ivstack);
-               right = clast_to_gcc_expression (r->elts[1], params, ivstack);
-               return fold_build2 (MAX_EXPR, type, left, right);
+               tree tl = clast_to_gcc_expression (type, r->elts[0], params, ivstack);
+               tree tr = clast_to_gcc_expression (type, r->elts[1], params, ivstack);
+               return fold_build2 (MAX_EXPR, type, tl, tr);
              }
 
            else
@@ -3299,15 +3536,8 @@ clast_to_gcc_expression (struct clast_expr *e,
       {
        struct clast_binary *b = (struct clast_binary *) e;
        struct clast_expr *lhs = (struct clast_expr *) b->LHS;
-       struct clast_expr *rhs = (struct clast_expr *) b->RHS;
-       tree tl = clast_to_gcc_expression (lhs, params, ivstack);
-
-       /* FIXME: The next statement produces a warning: Cloog assumes
-          that the RHS is a constant, but this is a "void *" pointer
-          that should be casted into a Value, but this cast cannot be
-          done as Value is a GMP type, that is an array.  Cloog must
-          be fixed for removing this warning.  */
-       tree tr = gmp_cst_to_tree (rhs);
+       tree tl = clast_to_gcc_expression (type, lhs, params, ivstack);
+       tree tr = gmp_cst_to_tree (type, b->RHS);
 
        switch (b->type)
          {
@@ -3335,6 +3565,72 @@ clast_to_gcc_expression (struct clast_expr *e,
   return NULL_TREE;
 }
 
+/* Returns the type for the expression E.  */
+
+static tree
+gcc_type_for_clast_expr (struct clast_expr *e,
+                        VEC (name_tree, heap) *params,
+                        loop_iv_stack ivstack)
+{
+  switch (e->type)
+    {
+    case expr_term:
+      {
+       struct clast_term *t = (struct clast_term *) e;
+
+       if (t->var)
+         return TREE_TYPE (clast_name_to_gcc (t->var, params, ivstack));
+       else
+         return NULL_TREE;
+      }
+
+    case expr_red:
+      {
+        struct clast_reduction *r = (struct clast_reduction *) e;
+
+       if (r->n == 1)
+         return gcc_type_for_clast_expr (r->elts[0], params, ivstack);
+       else 
+         {
+           int i;
+           for (i = 0; i < r->n; i++)
+             {
+               tree type = gcc_type_for_clast_expr (r->elts[i], params, ivstack);
+               if (type)
+                 return type;
+             }
+           return NULL_TREE;
+         }
+      }
+
+    case expr_bin:
+      {
+       struct clast_binary *b = (struct clast_binary *) e;
+       struct clast_expr *lhs = (struct clast_expr *) b->LHS;
+       return gcc_type_for_clast_expr (lhs, params, ivstack);
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return NULL_TREE;
+}
+
+/* Returns the type for the equation CLEQ.  */
+
+static tree
+gcc_type_for_clast_eq (struct clast_equation *cleq,
+                      VEC (name_tree, heap) *params,
+                      loop_iv_stack ivstack)
+{
+  tree type = gcc_type_for_clast_expr (cleq->LHS, params, ivstack);
+  if (type)
+    return type;
+
+  return gcc_type_for_clast_expr (cleq->RHS, params, ivstack);
+}
+
 /* Translates a clast equation CLEQ to a tree.  */
 
 static tree
@@ -3343,8 +3639,9 @@ graphite_translate_clast_equation (scop_p scop,
                                   loop_iv_stack ivstack)
 {
   enum tree_code comp;
-  tree lhs = clast_to_gcc_expression (cleq->LHS, SCOP_PARAMS (scop), ivstack);
-  tree rhs = clast_to_gcc_expression (cleq->RHS, SCOP_PARAMS (scop), ivstack);
+  tree type = gcc_type_for_clast_eq (cleq, SCOP_PARAMS (scop), ivstack);
+  tree lhs = clast_to_gcc_expression (type, cleq->LHS, SCOP_PARAMS (scop), ivstack);
+  tree rhs = clast_to_gcc_expression (type, cleq->RHS, SCOP_PARAMS (scop), ivstack);
 
   if (cleq->sign == 0)
     comp = EQ_EXPR;
@@ -3355,7 +3652,7 @@ graphite_translate_clast_equation (scop_p scop,
   else
     comp = LE_EXPR;
 
-  return fold_build2 (comp, integer_type_node, lhs, rhs);
+  return fold_build2 (comp, type, lhs, rhs);
 }
 
 /* Creates the test for the condition in STMT.  */
@@ -3372,7 +3669,7 @@ graphite_create_guard_cond_expr (scop_p scop, struct clast_guard *stmt,
       tree eq = graphite_translate_clast_equation (scop, &stmt->eq[i], ivstack);
 
       if (cond)
-       cond = fold_build2 (TRUTH_AND_EXPR, integer_type_node, cond, eq);
+       cond = fold_build2 (TRUTH_AND_EXPR, TREE_TYPE (eq), cond, eq);
       else
        cond = eq;
     }
@@ -3392,6 +3689,41 @@ graphite_create_new_guard (scop_p scop, edge entry_edge,
   return exit_edge;
 }
 
+/* Walks a CLAST and returns the first statement in the body of a
+   loop.  */
+
+static struct clast_user_stmt *
+clast_get_body_of_loop (struct clast_stmt *stmt)
+{
+  if (!stmt
+      || CLAST_STMT_IS_A (stmt, stmt_user))
+    return (struct clast_user_stmt *) stmt;
+
+  if (CLAST_STMT_IS_A (stmt, stmt_for))
+    return clast_get_body_of_loop (((struct clast_for *) stmt)->body);
+
+  if (CLAST_STMT_IS_A (stmt, stmt_guard))
+    return clast_get_body_of_loop (((struct clast_guard *) stmt)->then);
+
+  if (CLAST_STMT_IS_A (stmt, stmt_block))
+    return clast_get_body_of_loop (((struct clast_block *) stmt)->body);
+
+  gcc_unreachable ();
+}
+
+/* Returns the induction variable for the loop that gets translated to
+   STMT.  */
+
+static tree
+gcc_type_for_iv_of_clast_loop (struct clast_for *stmt_for)
+{
+  struct clast_user_stmt *stmt = clast_get_body_of_loop ((struct clast_stmt *) stmt_for);
+  const char *cloog_iv = stmt_for->iterator;
+  CloogStatement *cs = stmt->statement;
+  graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs);
+
+  return gcc_type_for_cloog_iv (cloog_iv, gbb);
+}
 
 /* Creates a new LOOP corresponding to Cloog's STMT.  Inserts an induction 
    variable for the new LOOP.  New LOOP is attached to CFG starting at
@@ -3403,63 +3735,114 @@ graphite_create_new_loop (scop_p scop, edge entry_edge,
                          struct clast_for *stmt, loop_iv_stack ivstack,
                          loop_p outer)
 {
-  struct loop *loop;
-  tree ivvar;
-  tree stride, lowb, upb;
+  tree type = gcc_type_for_iv_of_clast_loop (stmt);
+  VEC (name_tree, heap) *params = SCOP_PARAMS (scop);
+  tree lb = clast_to_gcc_expression (type, stmt->LB, params, ivstack);
+  tree ub = clast_to_gcc_expression (type, stmt->UB, params, ivstack);
+  tree stride = gmp_cst_to_tree (type, stmt->stride);
+  tree ivvar = create_tmp_var (type, "graphiteIV");
   tree iv_before;
+  loop_p loop = create_empty_loop_on_edge
+    (entry_edge, lb, stride, ub, ivvar, &iv_before,
+     outer ? outer : entry_edge->src->loop_father);
 
-  gcc_assert (stmt->LB
-             && stmt->UB);
-
-  stride = gmp_cst_to_tree (stmt->stride);
-  lowb = clast_to_gcc_expression (stmt->LB, SCOP_PARAMS (scop), ivstack);
-  ivvar = create_tmp_var (integer_type_node, "graphiteIV");
   add_referenced_var (ivvar);
-
-  upb = clast_to_gcc_expression (stmt->UB, SCOP_PARAMS (scop), ivstack);
-  loop = create_empty_loop_on_edge (entry_edge, lowb, stride, upb, ivvar,
-                                   &iv_before, outer ? outer
-                                   : entry_edge->src->loop_father);
-
   loop_iv_stack_push_iv (ivstack, iv_before, stmt->iterator);
-
   return loop;
 }
 
-/* Remove all the edges from EDGES except the edge KEEP.  */
+/* Structure containing the mapping between the old names and the new
+   names used after block copy in the new loop context.  */
+typedef struct rename_map_elt
+{
+  tree old_name, new_name;
+} *rename_map_elt;
+
+
+/* Print to stderr the element ELT.  */
 
 static void
-remove_all_edges_1 (VEC (edge, gc) *edges, edge keep)
+debug_rename_elt (rename_map_elt elt)
 {
-  edge e;
-  edge_iterator ei;
+  fprintf (stderr, "(");
+  print_generic_expr (stderr, elt->old_name, 0);
+  fprintf (stderr, ", ");
+  print_generic_expr (stderr, elt->new_name, 0);
+  fprintf (stderr, ")\n");
+}
 
-  for (ei = ei_start (edges); (e = ei_safe_edge (ei)); )
-    {
-      if (e != keep)
-       {
-         remove_edge (e);
-         e = ei_safe_edge (ei);
-       }
-      else
-       ei_next (&ei);
-    }
+/* Helper function for debug_rename_map.  */
+
+static int
+debug_rename_map_1 (void **slot, void *s ATTRIBUTE_UNUSED)
+{
+  struct rename_map_elt *entry = (struct rename_map_elt *) *slot;
+  debug_rename_elt (entry);
+  return 1;
 }
 
-/* Remove all the edges from BB except the edge KEEP.  */
+/* Print to stderr all the elements of MAP.  */
 
-static void
-remove_all_edges (basic_block bb, edge keep)
+void
+debug_rename_map (htab_t map)
+{
+  htab_traverse (map, debug_rename_map_1, NULL);
+}
+
+/* Constructs a new SCEV_INFO_STR structure for VAR and INSTANTIATED_BELOW.  */
+
+static inline rename_map_elt
+new_rename_map_elt (tree old_name, tree new_name)
+{
+  rename_map_elt res;
+  
+  res = XNEW (struct rename_map_elt);
+  res->old_name = old_name;
+  res->new_name = new_name;
+
+  return res;
+}
+
+/* Computes a hash function for database element ELT.  */
+
+static hashval_t
+rename_map_elt_info (const void *elt)
+{
+  return htab_hash_pointer (((const struct rename_map_elt *) elt)->old_name);
+}
+
+/* Compares database elements E1 and E2.  */
+
+static int
+eq_rename_map_elts (const void *e1, const void *e2)
+{
+  const struct rename_map_elt *elt1 = (const struct rename_map_elt *) e1;
+  const struct rename_map_elt *elt2 = (const struct rename_map_elt *) e2;
+
+  return (elt1->old_name == elt2->old_name);
+}
+
+/* Returns the new name associated to OLD_NAME in MAP.  */
+
+static tree
+get_new_name_from_old_name (htab_t map, tree old_name)
 {
-  remove_all_edges_1 (bb->succs, keep);
-  remove_all_edges_1 (bb->preds, keep);
+  struct rename_map_elt tmp;
+  PTR *slot;
+
+  tmp.old_name = old_name;
+  slot = htab_find_slot (map, &tmp, NO_INSERT);
+
+  if (slot && *slot)
+    return ((rename_map_elt) *slot)->new_name;
+
+  return old_name;
 }
 
 /* Rename the SSA_NAMEs used in STMT and that appear in IVSTACK.  */
 
 static void 
-graphite_rename_ivs_stmt (gimple stmt, graphite_bb_p gbb, scop_p scop,
-                         loop_p old, loop_iv_stack ivstack)
+rename_variables_in_stmt (gimple stmt, htab_t map)
 {
   ssa_op_iter iter;
   use_operand_p use_p;
@@ -3467,16 +3850,12 @@ graphite_rename_ivs_stmt (gimple stmt, graphite_bb_p gbb, scop_p scop,
   FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
     {
       tree use = USE_FROM_PTR (use_p);
-      tree new_iv = NULL;
-      name_tree old_iv = get_old_iv_from_ssa_name (scop, old, use);
-      
-      if (old_iv)
-       new_iv = loop_iv_stack_get_iv (ivstack,
-                                      gbb_loop_index (gbb, old_iv->loop));
+      tree new_name = get_new_name_from_old_name (map, use);
 
-      if (new_iv)
-       SET_USE (use_p, new_iv);
+      replace_exp (use_p, new_name);
     }
+
+  update_stmt (stmt);
 }
 
 /* Returns true if SSA_NAME is a parameter of SCOP.  */
@@ -3495,28 +3874,26 @@ is_parameter (scop_p scop, tree ssa_name)
   return false;
 }
 
-/* Returns true if NAME is an old induction variable in SCOP.  OLD is
-   the original loop that contained the definition of NAME.  */
+/* Returns true if NAME is an induction variable.  */
 
 static bool
-is_old_iv (scop_p scop, loop_p old, tree name)
+is_iv (tree name)
 {
-  return get_old_iv_from_ssa_name (scop, old, name) != NULL;
-
+  return gimple_code (SSA_NAME_DEF_STMT (name)) == GIMPLE_PHI;
 }
 
-static void expand_scalar_variables_stmt (gimple, graphite_bb_p, scop_p, loop_p,
-                                         loop_iv_stack);
+static void expand_scalar_variables_stmt (gimple, basic_block, scop_p,
+                                         loop_p, htab_t);
 
 /* Constructs a tree which only contains old_ivs and parameters.  Any
-   other variables that are defined outside GBB will be eliminated by
+   other variables that are defined outside BB will be eliminated by
    using their definitions in the constructed tree.  OLD_LOOP_FATHER
-   is the original loop that contained GBB.  */
+   is the original loop that contained BB.  */
 
 static tree
 expand_scalar_variables_expr (tree type, tree op0, enum tree_code code, 
-                             tree op1, graphite_bb_p gbb, scop_p scop, 
-                             loop_p old_loop_father, loop_iv_stack ivstack)
+                             tree op1, basic_block bb, scop_p scop, 
+                             loop_p old_loop_father, htab_t map)
 {
   if ((TREE_CODE_CLASS (code) == tcc_constant
        && code == INTEGER_CST)
@@ -3529,8 +3906,7 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code,
       enum tree_code op0_code = TREE_CODE (op0);
       tree op0_expr = 
        expand_scalar_variables_expr (op0_type, op0, op0_code,
-                                     NULL, gbb, scop, old_loop_father,
-                                     ivstack);
+                                     NULL, bb, scop, old_loop_father, map);
 
       return fold_build1 (code, type, op0_expr);
     }
@@ -3541,14 +3917,12 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code,
       enum tree_code op0_code = TREE_CODE (op0);
       tree op0_expr = 
        expand_scalar_variables_expr (op0_type, op0, op0_code,
-                                     NULL, gbb, scop, old_loop_father,
-                                     ivstack);
+                                     NULL, bb, scop, old_loop_father, map);
       tree op1_type = TREE_TYPE (op1);
       enum tree_code op1_code = TREE_CODE (op1);
       tree op1_expr = 
        expand_scalar_variables_expr (op1_type, op1, op1_code,
-                                     NULL, gbb, scop, old_loop_father,
-                                     ivstack);
+                                     NULL, bb, scop, old_loop_father, map);
 
       return fold_build2 (code, type, op0_expr, op1_expr);
     }
@@ -3559,34 +3933,34 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code,
       gimple def_stmt;
       enum tree_code subcode;
       
-      if(is_parameter (scop, op0) ||
-        is_old_iv (scop, old_loop_father, op0))
-       return op0;
+      if (is_parameter (scop, op0)
+         || is_iv (op0))
+       return get_new_name_from_old_name (map, op0);
       
       def_stmt = SSA_NAME_DEF_STMT (op0);
       
-      if (gimple_bb (def_stmt) == GBB_BB (gbb))
+      if (gimple_bb (def_stmt) == bb)
        {
          /* If the defining statement is in the basic block already
             we do not need to create a new expression for it, we
             only need to ensure its operands are expanded.  */
-         expand_scalar_variables_stmt (def_stmt, gbb, scop,
-                                       old_loop_father, ivstack);
-         return op0;
+         expand_scalar_variables_stmt (def_stmt, bb, scop,
+                                       old_loop_father, map);
+         return get_new_name_from_old_name (map, op0);
          
        }
       else
        {
-         if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
-           return op0;
+         if (gimple_code (def_stmt) != GIMPLE_ASSIGN
+             || !bb_in_scop_p (gimple_bb (def_stmt), scop))
+           return get_new_name_from_old_name (map, op0);
          
          var0 = gimple_assign_rhs1 (def_stmt);
          subcode = gimple_assign_rhs_code (def_stmt);
          var1 = gimple_assign_rhs2 (def_stmt);
          
-         return expand_scalar_variables_expr (type, var0, subcode, var1, 
-                                              gbb, scop, old_loop_father, 
-                                              ivstack);
+         return expand_scalar_variables_expr (type, var0, subcode, var1,
+                                              bb, scop, old_loop_father, map);
        }
     }
 
@@ -3595,106 +3969,96 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code,
 }
 
 /* Replicates any uses of non-parameters and non-old-ivs variablesthat
-   are defind outside GBB with code that is inserted in GBB.
+   are defind outside BB with code that is inserted in BB.
    OLD_LOOP_FATHER is the original loop that contained STMT.  */
  
 static void
-expand_scalar_variables_stmt (gimple stmt, graphite_bb_p gbb, scop_p scop,
-                             loop_p old_loop_father, loop_iv_stack ivstack)
+expand_scalar_variables_stmt (gimple stmt, basic_block bb, scop_p scop,
+                             loop_p old_loop_father, htab_t map)
 {
   ssa_op_iter iter;
   use_operand_p use_p;
-  basic_block bb = GBB_BB (gbb);
 
   FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
     {
       tree use = USE_FROM_PTR (use_p);
       tree type = TREE_TYPE (use);
       enum tree_code code  = TREE_CODE (use);
-      tree use_expr = expand_scalar_variables_expr (type, use, code, NULL,
-                                                   gbb, scop, old_loop_father, 
-                                                   ivstack);
+      tree use_expr = expand_scalar_variables_expr (type, use, code, NULL, bb,
+                                                   scop, old_loop_father, map);
       if (use_expr != use)
        {
          gimple_stmt_iterator gsi = gsi_after_labels (bb);
          tree new_use =
            force_gimple_operand_gsi (&gsi, use_expr, true, NULL,
                                      true, GSI_NEW_STMT);
-         SET_USE (use_p, new_use);
+         replace_exp (use_p, new_use);
        }
     }
+
+  update_stmt (stmt);
 }
 
-/* Copies the definitions outside of GBB of variables that are not
-   induction variables nor parameters. GBB must only contain
+/* Copies the definitions outside of BB of variables that are not
+   induction variables nor parameters.  BB must only contain
    "external" references to these types of variables.  OLD_LOOP_FATHER
-   is the original loop that contained GBB.  */
+   is the original loop that contained BB.  */
 
 static void 
-expand_scalar_variables (graphite_bb_p gbb, scop_p scop, 
-                        loop_p old_loop_father, loop_iv_stack ivstack)
+expand_scalar_variables (basic_block bb, scop_p scop, 
+                        loop_p old_loop_father, htab_t map)
 {
-  basic_block bb = GBB_BB (gbb);
   gimple_stmt_iterator gsi;
   
   for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi);)
     {
       gimple stmt = gsi_stmt (gsi);
-      expand_scalar_variables_stmt (stmt, gbb, scop, old_loop_father, 
-                                   ivstack); 
+      expand_scalar_variables_stmt (stmt, bb, scop, old_loop_father, map);
       gsi_next (&gsi);
     }
 }
 
-/* Rename all the SSA_NAMEs from block GBB that appear in IVSTACK in
-   terms of new induction variables.  OLD_LOOP_FATHER is the original
-   loop that contained GBB.  */
+/* Rename all the SSA_NAMEs from block BB according to the MAP.  */
 
 static void 
-graphite_rename_ivs (graphite_bb_p gbb, scop_p scop, loop_p old_loop_father,
-                    loop_iv_stack ivstack)
+rename_variables (basic_block bb, htab_t map)
 {
-  basic_block bb = GBB_BB (gbb);
   gimple_stmt_iterator gsi;
   
-  for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi);)
-    {
-      gimple stmt = gsi_stmt (gsi);
+  for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    rename_variables_in_stmt (gsi_stmt (gsi), map);
+}
 
-      if (gimple_get_lhs (stmt)
-         && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME
-         && get_old_iv_from_ssa_name (scop, old_loop_father,
-                                      gimple_get_lhs (stmt)))
-       gsi_remove (&gsi, false);
-      else
-       {
-         graphite_rename_ivs_stmt (stmt, gbb, scop, old_loop_father, ivstack); 
-         gsi_next (&gsi);
-       }
-    }
+/* Rename following the information from MAP the PHI node argument
+   corresponding to the edge E.  In order to allow several renames of
+   that argument, we match the original SSA_NAME on the argument
+   coming from the edge different than E.  */
+
+static void
+rename_variables_from_edge (edge e, gimple phi, htab_t map)
+{
+  int n = e->dest_idx == 0 ? 1 : 0;
+  tree old_name = gimple_phi_arg_def (phi, n);
+  tree new_name = get_new_name_from_old_name (map, old_name);
+
+  gcc_assert (gimple_phi_num_args (phi) == 2
+             && gimple_phi_arg_edge (phi, e->dest_idx) == e);
+
+  SET_PHI_ARG_DEF (phi, n, new_name);
 }
 
-/* Move all the PHI nodes from block FROM to block TO.
-   OLD_LOOP_FATHER is the original loop that contained FROM.  */
+/* Rename all the phi arguments for the edges comming from the scop
+   according to the MAP.  */
 
 static void
-move_phi_nodes (scop_p scop, loop_p old_loop_father, basic_block from,
-               basic_block to)
+rename_phis_end_scop (scop_p scop, htab_t map)
 {
+  basic_block after_scop = SCOP_EXIT (scop);
+  edge e = SESE_EXIT (SCOP_REGION (scop));
   gimple_stmt_iterator gsi;
 
-  for (gsi = gsi_start_phis (from); !gsi_end_p (gsi);)
-    {
-      gimple phi = gsi_stmt (gsi);
-      tree op = gimple_phi_result (phi);
-
-      if (get_old_iv_from_ssa_name (scop, old_loop_father, op) == NULL)
-       {
-         gimple new_phi = make_phi_node (op, 0);
-         add_phi_node_to_bb (new_phi, to);
-       }
-      remove_phi_node (&gsi, false);
-    }
+  for (gsi = gsi_start_phis (after_scop); !gsi_end_p (gsi); gsi_next (&gsi))
+    rename_variables_from_edge (e, gsi_stmt (gsi), map);
 }
 
 /* Remove condition from BB.  */
@@ -3727,6 +4091,132 @@ get_true_edge_from_guard_bb (basic_block bb)
   return NULL;
 }
 
+/* Returns the first successor edge of BB with EDGE_TRUE_VALUE flag cleared.  */
+
+static edge
+get_false_edge_from_guard_bb (basic_block bb)
+{
+  edge e;
+  edge_iterator ei;
+
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    if (!(e->flags & EDGE_TRUE_VALUE)) 
+      return e;
+
+  gcc_unreachable ();
+  return NULL;
+}
+
+/* Inserts in MAP a tuple (OLD_NAME, NEW_NAME) for the induction
+   variables of the loops around GBB in SCOP, i.e. GBB_LOOPS.
+   NEW_NAME is obtained from IVSTACK.  IVSTACK has the same stack
+   ordering as GBB_LOOPS.  */
+
+static void
+build_iv_mapping (loop_iv_stack ivstack, htab_t map, gbb_p gbb, scop_p scop)
+{
+  int i;
+  name_tree iv;
+  PTR *slot;
+
+  for (i = 0; VEC_iterate (name_tree, SCOP_OLDIVS (scop), i, iv); i++)
+    {
+      struct rename_map_elt tmp;
+
+      if (!flow_bb_inside_loop_p (iv->loop, GBB_BB (gbb)))
+       continue;
+
+      tmp.old_name = iv->t;
+      slot = htab_find_slot (map, &tmp, INSERT);
+
+      if (!*slot)
+       {
+         tree new_name = loop_iv_stack_get_iv (ivstack, 
+                                               gbb_loop_index (gbb, iv->loop));
+         *slot = new_rename_map_elt (iv->t, new_name);
+       }
+    }
+}
+
+/* Register in MAP the tuple (old_name, new_name).  */
+
+static void
+register_old_new_names (htab_t map, tree old_name, tree new_name)
+{
+  struct rename_map_elt tmp;
+  PTR *slot;
+
+  tmp.old_name = old_name;
+  slot = htab_find_slot (map, &tmp, INSERT);
+
+  if (!*slot)
+    *slot = new_rename_map_elt (old_name, new_name);
+}
+
+/* Create a duplicate of the basic block BB.  NOTE: This does not
+   preserve SSA form.  */
+
+static void
+graphite_copy_stmts_from_block (basic_block bb, basic_block new_bb, htab_t map)
+{
+  gimple_stmt_iterator gsi, gsi_tgt;
+
+  gsi_tgt = gsi_start_bb (new_bb);
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      def_operand_p def_p;
+      ssa_op_iter op_iter;
+      int region;
+      gimple stmt = gsi_stmt (gsi);
+      gimple copy;
+
+      if (gimple_code (stmt) == GIMPLE_LABEL)
+       continue;
+
+      /* Create a new copy of STMT and duplicate STMT's virtual
+        operands.  */
+      copy = gimple_copy (stmt);
+      gsi_insert_after (&gsi_tgt, copy, GSI_NEW_STMT);
+      mark_symbols_for_renaming (copy);
+
+      region = lookup_stmt_eh_region (stmt);
+      if (region >= 0)
+       add_stmt_to_eh_region (copy, region);
+      gimple_duplicate_stmt_histograms (cfun, copy, cfun, stmt);
+
+      /* Create new names for all the definitions created by COPY and
+        add replacement mappings for each new name.  */
+      FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_DEF)
+       {
+         tree old_name = DEF_FROM_PTR (def_p);
+         tree new_name = create_new_def_for (old_name, copy, def_p);
+         register_old_new_names (map, old_name, new_name);
+       }
+    }
+}
+
+/* Copies BB and includes in the copied BB all the statements that can
+   be reached following the use-def chains from the memory accesses,
+   and returns the next edge following this new block.  */
+static edge
+copy_bb_and_scalar_dependences (basic_block bb, scop_p scop,
+                               loop_p context_loop,
+                               edge next_e, htab_t map)
+{
+  basic_block new_bb = split_edge (next_e);
+
+  next_e = single_succ_edge (new_bb);
+  graphite_copy_stmts_from_block (bb, new_bb, map);
+  remove_condition (new_bb);
+  rename_variables (new_bb, map);
+  remove_phi_nodes (new_bb);
+  expand_scalar_variables (new_bb, scop, context_loop, map);
+  rename_phis_end_scop (scop, map);
+
+  return next_e;
+}
+
 /* Translates a CLAST statement STMT to GCC representation.  NEXT_E is
    the edge where new generated code should be attached.  BB_EXIT is the last
    basic block that defines the scope of code generation.  CONTEXT_LOOP is the
@@ -3744,35 +4234,23 @@ translate_clast (scop_p scop, struct loop *context_loop,
 
   if (CLAST_STMT_IS_A (stmt, stmt_user))
     {
+      htab_t map;
       CloogStatement *cs = ((struct clast_user_stmt *) stmt)->statement;
       graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs);
-      basic_block bb = gbb->bb;
-      loop_p old_loop_father = bb->loop_father;
 
-      if (bb == ENTRY_BLOCK_PTR)
+      if (GBB_BB (gbb) == ENTRY_BLOCK_PTR)
        return next_e;
 
-      remove_condition (bb);
-      expand_scalar_variables (gbb, scop, old_loop_father, ivstack);
-      remove_all_edges (bb, next_e);
-      move_phi_nodes (scop, old_loop_father, bb, next_e->src); 
-      redirect_edge_succ_nodup (next_e, bb);
-
-      if (context_loop)
-       {
-         remove_bb_from_loops (bb);
-         add_bb_to_loop (bb, context_loop);
-       }
-
-      set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src); 
-      mark_virtual_ops_in_bb (bb);
-      next_e = make_edge (bb,
-                         context_loop ? context_loop->latch : EXIT_BLOCK_PTR,
-                         EDGE_FALLTHRU);
-      loop_iv_stack_patch_for_consts (ivstack,
-                                     (struct clast_user_stmt *) stmt);
-      graphite_rename_ivs (gbb, scop, old_loop_father, ivstack);
+      map = htab_create (10, rename_map_elt_info, eq_rename_map_elts, free);
+      loop_iv_stack_patch_for_consts (ivstack, (struct clast_user_stmt *) stmt);
+      build_iv_mapping (ivstack, map, gbb, scop);
+      next_e = copy_bb_and_scalar_dependences (GBB_BB (gbb), scop,
+                                              context_loop, next_e, map);
+      htab_delete (map);
       loop_iv_stack_remove_constants (ivstack);
+      update_ssa (TODO_update_ssa);
+      recompute_all_dominators ();
+      graphite_verify ();
       return translate_clast (scop, context_loop, stmt->next, next_e, ivstack);
     }
 
@@ -3790,7 +4268,9 @@ translate_clast (scop_p scop, struct loop *context_loop,
        
       set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src);
       loop_iv_stack_pop (ivstack);
-
+      last_e = single_succ_edge (split_edge (last_e));
+      recompute_all_dominators ();
+      graphite_verify ();
       return translate_clast (scop, context_loop, stmt->next, last_e, ivstack);
     }
 
@@ -3803,7 +4283,7 @@ translate_clast (scop_p scop, struct loop *context_loop,
       next_e = translate_clast (scop, context_loop, 
                                ((struct clast_guard *) stmt)->then,
                                true_e, ivstack);
-      redirect_edge_succ_nodup (next_e, last_e->src);
+      graphite_verify ();
       return translate_clast (scop, context_loop, stmt->next, last_e, ivstack);
     }
 
@@ -3812,6 +4292,7 @@ translate_clast (scop_p scop, struct loop *context_loop,
       next_e = translate_clast (scop, context_loop,
                                ((struct clast_block *) stmt)->body,
                                next_e, ivstack);
+      graphite_verify ();
       return translate_clast (scop, context_loop, stmt->next, next_e, ivstack);
     }
 
@@ -3989,218 +4470,41 @@ debug_clast_stmt (struct clast_stmt *stmt)
 {
   CloogOptions *options = set_cloog_options ();
 
-  pprint (stderr, stmt, 0, options);
-}
-
-/* Find the right transform for the SCOP, and return a Cloog AST
-   representing the new form of the program.  */
-
-static struct clast_stmt *
-find_transform (scop_p scop)
-{
-  struct clast_stmt *stmt;
-  CloogOptions *options = set_cloog_options ();
-
-  /* Connect new cloog prog generation to graphite.  */
-  build_cloog_prog (scop);
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      fprintf (dump_file, "Cloog Input [\n");
-      cloog_program_print (dump_file, SCOP_PROG(scop));
-      fprintf (dump_file, "]\n");
-    }
-
-  SCOP_PROG (scop) = cloog_program_generate (SCOP_PROG (scop), options);
-  stmt = cloog_clast_create (SCOP_PROG (scop), options);
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      fprintf (dump_file, "Cloog Output[\n");
-      pprint (dump_file, stmt, 0, options);
-      cloog_program_dump_cloog (dump_file, SCOP_PROG (scop));
-      fprintf (dump_file, "]\n");
-    }
-
-  cloog_options_free (options);
-  return stmt;
-}
-
-/* Return a vector of all the virtual phi nodes in the current
-   function.  */
-static VEC (gimple, heap) *
-collect_virtual_phis (void)     
-{
-  gimple_stmt_iterator si;
-  gimple_vec phis = VEC_alloc (gimple, heap, 3);
-  basic_block bb;
-
-  FOR_EACH_BB (bb) 
-    for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
-      /* The phis we moved will have 0 arguments because the
-        original edges were removed.  */
-      if (gimple_phi_num_args (gsi_stmt (si)) == 0)
-       VEC_safe_push (gimple, heap, phis, gsi_stmt (si));
-
-  /* Deallocate if we did not find any.  */
-  if (VEC_length (gimple, phis) == 0)
-    {
-      VEC_free (gimple, heap, phis);
-      phis = NULL;
-    }
-
-  return phis;
-}
-
-/* Find a virtual definition for variable VAR in BB.  */
-
-static tree
-find_vdef_for_var_in_bb (basic_block bb, tree var)
-{
-  gimple_stmt_iterator gsi;
-  gimple phi;
-  def_operand_p def_var;
-  vuse_vec_p vv;
-  ssa_op_iter op_iter;
-
-  for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
-    FOR_EACH_SSA_VDEF_OPERAND (def_var, vv, gsi_stmt (gsi), op_iter)
-      if (SSA_NAME_VAR (*def_var) == var)
-       return *def_var;
-
-  for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
-    FOR_EACH_SSA_DEF_OPERAND (def_var, gsi_stmt (gsi), op_iter, SSA_OP_DEF)
-      if (SSA_NAME_VAR (*def_var) == var)
-       return *def_var;
-
-  for (gsi = gsi_start_phis (bb); !gsi_end_p(gsi); gsi_next (&gsi))
-    {
-      phi = gsi_stmt (gsi);
-      if (SSA_NAME_VAR (PHI_RESULT (phi)) == var)
-       return PHI_RESULT (phi);
-    }
-
-  return NULL;
-}
-
-/* Recursive helper.  */
-
-static tree
-find_vdef_for_var_1 (basic_block bb, struct pointer_set_t *visited, tree var)
-{
-  tree result = NULL;
-  edge_iterator ei;
-  edge pred_edge;
-
-  if (pointer_set_contains (visited, bb))
-    return NULL;
-
-  pointer_set_insert (visited, bb);
-  result = find_vdef_for_var_in_bb (bb, var);
-
-  if (!result)
-    FOR_EACH_EDGE (pred_edge, ei, bb->preds)
-      if (!result)
-       result = find_vdef_for_var_1 (pred_edge->src, visited, var);
-
-  return result;
-}
-
-/* Finds a virtual definition for variable VAR.  */
-
-static tree
-find_vdef_for_var (basic_block bb, tree var)
-{
-  struct pointer_set_t *visited = pointer_set_create ();
-  tree def = find_vdef_for_var_1 (bb, visited, var);
-
-  pointer_set_destroy (visited);
-  return def;
-}
-
-/* Update the virtual phis after loop bodies are moved to new
-   loops.  */
-
-static void
-patch_phis_for_virtual_defs (void)
-{
-  int i;
-  gimple phi;
-  VEC (gimple, heap) *virtual_phis = collect_virtual_phis ();
-  
-  for (i = 0; VEC_iterate (gimple, virtual_phis, i, phi); i++)
-    {
-      basic_block bb = gimple_bb (phi);
-      edge_iterator ei;
-      edge pred_edge;
-      gimple_stmt_iterator gsi;
-      gimple new_phi;
-      tree phi_result = PHI_RESULT (phi);
-      tree var = SSA_NAME_VAR (phi_result);
-
-      new_phi = create_phi_node (phi_result, bb);
-      SSA_NAME_DEF_STMT (phi_result) = new_phi;
-
-      FOR_EACH_EDGE (pred_edge, ei, bb->preds)
-       {
-         tree def = find_vdef_for_var (pred_edge->src, var);
-
-         if (def)
-           add_phi_arg (new_phi, def, pred_edge);
-         else
-           add_phi_arg (new_phi, gimple_default_def (cfun, var), pred_edge);
-       }
-
-      gsi = gsi_for_stmt (phi);
-      remove_phi_node (&gsi, false);
-    }
-
-  VEC_free (gimple, heap, virtual_phis);
+  pprint (stderr, stmt, 0, options);
 }
 
-/* Mark the original loops of SCOP for removal, replacing their header
-   field with NULL.  */
+/* Find the right transform for the SCOP, and return a Cloog AST
+   representing the new form of the program.  */
 
-static void
-mark_old_loops (scop_p scop)
+static struct clast_stmt *
+find_transform (scop_p scop)
 {
-  int i;
-  struct loop *loop;
+  struct clast_stmt *stmt;
+  CloogOptions *options = set_cloog_options ();
 
-  for (i = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), i, loop); i++)
+  /* Connect new cloog prog generation to graphite.  */
+  build_cloog_prog (scop);
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      loop->header = NULL;
-      loop->latch = NULL;
+      fprintf (dump_file, "Cloog Input [\n");
+      cloog_program_print (dump_file, SCOP_PROG(scop));
+      fprintf (dump_file, "]\n");
     }
-}
-
-/* Scan the loops and remove the ones that have been marked for
-   removal.  */
 
-static void
-remove_dead_loops (void)
-{
-  struct loop *loop, *ploop;
-  loop_iterator li;
+  SCOP_PROG (scop) = cloog_program_generate (SCOP_PROG (scop), options);
+  stmt = cloog_clast_create (SCOP_PROG (scop), options);
 
-  FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      /* Remove only those loops that we marked to be removed with
-        mark_old_loops.  */
-      if (loop->header)
-       continue;
-
-      while (loop->inner)
-       {
-         ploop = loop->inner;
-         flow_loop_tree_node_remove (ploop);
-         flow_loop_tree_node_add (loop_outer (loop), ploop);
-       }
-
-      /* Remove the loop and free its data.  */
-      delete_loop (loop);
+      fprintf (dump_file, "Cloog Output[\n");
+      pprint (dump_file, stmt, 0, options);
+      cloog_program_dump_cloog (dump_file, SCOP_PROG (scop));
+      fprintf (dump_file, "]\n");
     }
+
+  cloog_options_free (options);
+  return stmt;
 }
 
 /* Returns true when it is possible to generate code for this STMT.
@@ -4261,230 +4565,443 @@ can_generate_code (struct clast_stmt *stmt)
   return result;
 }
 
-/* Skip any definition that is a phi node with a single phi def.  */
+/* Remove from the CFG the REGION.  */
 
-static tree 
-skip_phi_defs (tree ssa_name)
+static inline void
+remove_sese_region (sese region)
 {
-  tree result = ssa_name;
-  gimple def_stmt = SSA_NAME_DEF_STMT (ssa_name);
+  VEC (basic_block, heap) *bbs = NULL;
+  basic_block entry_bb = SESE_ENTRY (region)->dest;
+  basic_block exit_bb = SESE_EXIT (region)->dest;
+  basic_block bb;
+  int i;
 
-  if (gimple_code (def_stmt) == GIMPLE_PHI 
-      && gimple_phi_num_args (def_stmt) == 1)
-    result = skip_phi_defs (gimple_phi_arg(def_stmt,0)->def);
+  VEC_safe_push (basic_block, heap, bbs, entry_bb);
+  gather_blocks_in_sese_region (entry_bb, exit_bb, &bbs);
 
-  return result;
+  for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
+    delete_basic_block (bb);
+
+  VEC_free (basic_block, heap, bbs);
 }
 
-/* Returns a VEC containing the phi-arg defs coming from SCOP_EXIT in
-   the destination block of SCOP_EXIT.  */
+typedef struct ifsese {
+  sese region;
+  sese true_region;
+  sese false_region;
+} *ifsese;
 
-static VEC (tree, heap) *
-collect_scop_exit_phi_args (edge scop_exit)
+static inline edge
+if_region_entry (ifsese if_region)
 {
-  VEC (tree, heap) *phi_args = VEC_alloc (tree, heap, 1);
-  gimple_stmt_iterator gsi;
+  return SESE_ENTRY (if_region->region);
+}
+
+static inline edge
+if_region_exit (ifsese if_region)
+{
+  return SESE_EXIT (if_region->region);
+}
+
+static inline basic_block
+if_region_get_condition_block (ifsese if_region)
+{
+  return if_region_entry (if_region)->dest;
+}
+
+static inline void
+if_region_set_false_region (ifsese if_region, sese region)
+{
+  basic_block condition = if_region_get_condition_block (if_region);
+  edge false_edge = get_false_edge_from_guard_bb (condition);
+  edge entry_region = SESE_ENTRY (region);
+  edge exit_region = SESE_EXIT (region);
+  basic_block before_region = entry_region->src;
+  basic_block last_in_region = exit_region->src;
+  void **slot = htab_find_slot_with_hash (current_loops->exits, exit_region,
+                                         htab_hash_pointer (exit_region),
+                                         NO_INSERT);
+
+  entry_region->flags = false_edge->flags;
+  false_edge->flags = exit_region->flags;
 
-  for (gsi = gsi_start_phis (scop_exit->dest); !gsi_end_p (gsi); gsi_next (&gsi))
+  redirect_edge_pred (entry_region, condition);
+  redirect_edge_pred (exit_region, before_region);
+  redirect_edge_pred (false_edge, last_in_region);
+
+  exit_region->flags = EDGE_FALLTHRU;
+  recompute_all_dominators ();
+
+  SESE_EXIT (region) = single_succ_edge (false_edge->dest);
+  if_region->false_region = region;
+
+  if (slot)
     {
-      gimple phi = gsi_stmt (gsi);
-      tree phi_arg = skip_phi_defs(PHI_ARG_DEF_FROM_EDGE (phi, scop_exit));
+      struct loop_exit *loop_exit = GGC_CNEW (struct loop_exit);
+
+      memcpy (loop_exit, *((struct loop_exit **) slot), sizeof (struct loop_exit));
+      htab_clear_slot (current_loops->exits, slot);
+
+      slot = htab_find_slot_with_hash (current_loops->exits, false_edge,
+                                      htab_hash_pointer (false_edge),
+                                      INSERT);
+      loop_exit->e = false_edge;
+      *slot = loop_exit;
+      false_edge->src->loop_father->exits->next = loop_exit;
+    }
+}
+
+static ifsese
+create_if_region_on_edge (edge entry, tree condition)
+{
+  edge e;
+  edge_iterator ei;
+  sese sese_region = GGC_NEW (struct sese);
+  sese true_region = GGC_NEW (struct sese);
+  sese false_region = GGC_NEW (struct sese);
+  ifsese if_region = GGC_NEW (struct ifsese);
+  edge exit = create_empty_if_region_on_edge (entry, condition);
 
-      VEC_safe_push (tree, heap, phi_args, phi_arg);
+  if_region->region = sese_region;
+  if_region->region->entry = entry;
+  if_region->region->exit = exit;
+
+  FOR_EACH_EDGE (e, ei, entry->dest->succs)
+    {
+      if (e->flags & EDGE_TRUE_VALUE)
+       {
+         true_region->entry = e;
+         true_region->exit = single_succ_edge (e->dest);
+         if_region->true_region = true_region;
+       }
+      else if (e->flags & EDGE_FALSE_VALUE)
+       {
+         false_region->entry = e;
+         false_region->exit = single_succ_edge (e->dest);
+         if_region->false_region = false_region;
+       }
     }
 
-  return phi_args;
+  return if_region;
 }
 
-/* Patches (adds) PHI_ARGS to the phi nodes in SCOP_EXIT destination.  */
+/* Moves REGION in a condition expression:
+   | if (1)
+   |   ;
+   | else
+   |   REGION;
+*/
 
-static void
-patch_scop_exit_phi_args (edge scop_exit,
-                         VEC (tree, heap) *phi_args)
+static ifsese
+move_sese_in_condition (sese region)
 {
-  int i = 0;
-  gimple_stmt_iterator gsi;
+  basic_block pred_block = split_edge (SESE_ENTRY (region));
+  ifsese if_region = NULL;
 
-  for (gsi = gsi_start_phis (scop_exit->dest); !gsi_end_p (gsi);
-       gsi_next (&gsi), i++)
-    {
-      tree def = VEC_index (tree, phi_args, i);
-      gimple phi = gsi_stmt (gsi);
+  SESE_ENTRY (region) = single_succ_edge (pred_block);
+  if_region = create_if_region_on_edge (single_pred_edge (pred_block), integer_one_node);
+  if_region_set_false_region (if_region, region);
+
+  return if_region;
+}
 
-      gcc_assert (PHI_ARG_DEF_FROM_EDGE (phi, scop_exit) == NULL);
+/* Returns true when BB is in REGION.  */
 
-      add_phi_arg (phi, def, scop_exit);
-    }
+static bool
+bb_in_sese_p (basic_block bb, sese region)
+{
+  return pointer_set_contains (SESE_REGION_BBS (region), bb);
 }
 
-/* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for
-   the given SCOP.  */
+/* For USE in BB, if it is used outside of the REGION it is defined in,
+   mark it for rewrite.  Record basic block BB where it is used
+   to USE_BLOCKS.  Record the ssa name index to NEED_PHIS bitmap.  */
 
 static void
-gloog (scop_p scop, struct clast_stmt *stmt)
+sese_find_uses_to_rename_use (sese region, basic_block bb, tree use,
+                             bitmap *use_blocks, bitmap need_phis)
 {
-  edge new_scop_exit_edge = NULL;
-  basic_block scop_exit = SCOP_EXIT (scop);
-  VEC (tree, heap) *phi_args =
-    collect_scop_exit_phi_args (SESE_EXIT (SCOP_REGION (scop)));
-  VEC (iv_stack_entry_p, heap) *ivstack = 
-    VEC_alloc (iv_stack_entry_p, heap, 10);
-  edge construction_edge = SESE_ENTRY (SCOP_REGION (scop));
-  basic_block old_scop_exit_idom = get_immediate_dominator (CDI_DOMINATORS,
-                                                           scop_exit);
+  unsigned ver;
+  basic_block def_bb;
 
-  if (!can_generate_code (stmt))
-    {
-      cloog_clast_free (stmt);
-      return;
-    }
+  if (TREE_CODE (use) != SSA_NAME)
+    return;
 
-  redirect_edge_succ_nodup (construction_edge, EXIT_BLOCK_PTR);
-  new_scop_exit_edge = translate_clast (scop, 
-                                       construction_edge->src->loop_father,
-                                       stmt, construction_edge, &ivstack);
-  free_loop_iv_stack (&ivstack);
-  redirect_edge_succ (new_scop_exit_edge, scop_exit);
+  ver = SSA_NAME_VERSION (use);
+  def_bb = gimple_bb (SSA_NAME_DEF_STMT (use));
+  if (!def_bb
+      || !bb_in_sese_p (def_bb, region)
+      || bb_in_sese_p (bb, region))
+    return;
 
-  if (!old_scop_exit_idom
-      || !dominated_by_p (CDI_DOMINATORS, SCOP_ENTRY (scop),
-                         old_scop_exit_idom)
-      || SCOP_ENTRY (scop) == old_scop_exit_idom)
-    set_immediate_dominator (CDI_DOMINATORS,
-                            new_scop_exit_edge->dest,
-                            new_scop_exit_edge->src);
+  if (!use_blocks[ver])
+    use_blocks[ver] = BITMAP_ALLOC (NULL);
+  bitmap_set_bit (use_blocks[ver], bb->index);
 
-  cloog_clast_free (stmt);
+  bitmap_set_bit (need_phis, ver);
+}
 
-  if (new_scop_exit_edge->dest == EXIT_BLOCK_PTR)
-    new_scop_exit_edge->flags = 0;
-  delete_unreachable_blocks ();
-  patch_phis_for_virtual_defs ();
-  patch_scop_exit_phi_args (new_scop_exit_edge, phi_args);
-  VEC_free (tree, heap, phi_args);
-  mark_old_loops (scop);
-  remove_dead_loops ();
-  rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); 
+/* Marks names that are used in BB and outside of the loop they are
+   defined in for rewrite.  Records the set of blocks in that the ssa
+   names are defined to USE_BLOCKS.  Record the SSA names that will
+   need exit PHIs in NEED_PHIS.  */
 
-#ifdef ENABLE_CHECKING
-  verify_loop_structure ();
-  verify_dominators (CDI_DOMINATORS);
-  verify_ssa (false);
-#endif
+static void
+sese_find_uses_to_rename_bb (sese region, basic_block bb,
+                            bitmap *use_blocks, bitmap need_phis)
+{
+  gimple_stmt_iterator bsi;
+  edge e;
+  edge_iterator ei;
+  ssa_op_iter iter;
+  tree var;
+
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    for (bsi = gsi_start_phis (e->dest); !gsi_end_p (bsi); gsi_next (&bsi))
+      sese_find_uses_to_rename_use (region, bb,
+                                   PHI_ARG_DEF_FROM_EDGE (gsi_stmt (bsi), e),
+                                   use_blocks, need_phis);
+
+  for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+    FOR_EACH_SSA_TREE_OPERAND (var, gsi_stmt (bsi), iter, SSA_OP_ALL_USES)
+      sese_find_uses_to_rename_use (region, bb, var, use_blocks, need_phis);
 }
 
-/* Returns the number of data references in SCOP.  */
+/* Add exit phis for USE on EXIT.  */
 
-static int
-nb_data_refs_in_scop (scop_p scop)
+static void
+sese_add_exit_phis_edge (basic_block exit, tree use, edge false_e, edge true_e)
 {
-  int i;
-  graphite_bb_p gbb;
-  int res = 0;
+  gimple phi = create_phi_node (use, exit);
 
-  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gbb); i++)
-    res += VEC_length (data_reference_p, GBB_DATA_REFS (gbb));
+  create_new_def_for (gimple_phi_result (phi), phi,
+                     gimple_phi_result_ptr (phi));
+  add_phi_arg (phi, use, false_e);
+  add_phi_arg (phi, use, true_e);
+}
 
-  return res;
+/* Add phi nodes for VAR that is used in LIVEIN.  Phi nodes are
+   inserted in block WHERE.  */
+
+static void
+sese_add_exit_phis_var (basic_block where, tree var, bitmap livein,
+                       edge false_e, edge true_e)
+{
+  bitmap def;
+  basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (var));
+
+  if (is_gimple_reg (var))
+    bitmap_clear_bit (livein, def_bb->index);
+  else
+    bitmap_set_bit (livein, def_bb->index);
+
+  def = BITMAP_ALLOC (NULL);
+  bitmap_set_bit (def, def_bb->index);
+  compute_global_livein (livein, def);
+  BITMAP_FREE (def);
+
+  sese_add_exit_phis_edge (where, var, false_e, true_e);
 }
 
-/* Check if a graphite bb can be ignored in graphite.  We ignore all
-   bbs, that only contain code, that will be eliminated later.
+/* Insert in the block WHERE phi nodes for variables defined in REGION
+   and used outside the REGION.  */
+
+static void
+rewrite_into_sese_closed_ssa (sese region, basic_block where,
+                             edge false_e, edge true_e)
+{
+  unsigned i;
+  basic_block bb;
+  bitmap_iterator bi;
+  bitmap names_to_rename = BITMAP_ALLOC (NULL);
+  unsigned old_num_ssa_names = num_ssa_names;
+  bitmap *use_blocks = XCNEWVEC (bitmap, old_num_ssa_names);
+
+  update_ssa (TODO_update_ssa);
 
-   TODO: - Move PHI nodes and scalar variables out of these bbs, that only
-           remain conditions and induction variables.  */
+  FOR_EACH_BB (bb)
+    sese_find_uses_to_rename_bb (region, bb, use_blocks, names_to_rename);
 
-static bool
-gbb_can_be_ignored (graphite_bb_p gb)
+  EXECUTE_IF_SET_IN_BITMAP (names_to_rename, 0, i, bi)
+    sese_add_exit_phis_var (where, ssa_name (i), use_blocks[i],
+                           false_e, true_e);
+
+  update_ssa (TODO_update_ssa);
+
+  for (i = 0; i < old_num_ssa_names; i++)
+    BITMAP_FREE (use_blocks[i]);
+
+  free (use_blocks);
+  BITMAP_FREE (names_to_rename);
+}
+
+/* Returns the first cloog name used in EXPR.  */
+
+static const char *
+find_cloog_iv_in_expr (struct clast_expr *expr)
 {
-  gimple_stmt_iterator gsi;
-  scop_p scop = GBB_SCOP (gb);
-  loop_p loop = GBB_BB (gb)->loop_father;
+  struct clast_term *term = (struct clast_term *) expr;
 
-  if (VEC_length (data_reference_p, GBB_DATA_REFS(gb)))
-    return false;
+  if (expr->type == expr_term
+      && !term->var)
+    return NULL;
 
-  /* Check statements.  */
-  for (gsi = gsi_start_bb (GBB_BB (gb)); !gsi_end_p (gsi); gsi_next (&gsi))
-    {
-      gimple stmt = gsi_stmt (gsi);
-      switch (gimple_code (stmt))
-        {
-          /* Control flow expressions can be ignored, as they are
-             represented in the iteration domains and will be
-             regenerated by graphite.  */
-          case GIMPLE_COND:
-         case GIMPLE_GOTO:
-         case GIMPLE_SWITCH:
-            break;
+  if (expr->type == expr_term)
+    return term->var;
 
-          /* Scalar variables can be ignored, if we can regenerate
-             them later using their scalar evolution function.
-             XXX: Just a heuristic, that needs further investigation.  */
-          case GIMPLE_ASSIGN:
-           {
-             tree var = gimple_assign_lhs (stmt);
-             var = analyze_scalar_evolution (loop, var);
-             var = instantiate_scev (block_before_scop (scop), loop, var);
+  if (expr->type == expr_red)
+    {
+      int i;
+      struct clast_reduction *red = (struct clast_reduction *) expr;
 
-             if (TREE_CODE (var) == SCEV_NOT_KNOWN)
-               return false;
+      for (i = 0; i < red->n; i++)
+       {
+         const char *res = find_cloog_iv_in_expr ((red)->elts[i]);
 
-             break;
-           }
-          /* Otherwise not ignoreable.  */
-          default:
-            return false;
-        }
+         if (res)
+           return res;
+       }
     }
 
-  return true;
+  return NULL;
 }
 
-/* Remove all ignoreable gbbs from SCOP.  */
+/* Build for a clast_user_stmt USER_STMT a map between the CLAST
+   induction variables and the corresponding GCC old induction
+   variables.  This information is stored on each GRAPHITE_BB.  */
 
 static void
-scop_remove_ignoreable_gbbs (scop_p scop)
+compute_cloog_iv_types_1 (graphite_bb_p gbb,
+                         struct clast_user_stmt *user_stmt)
 {
-  graphite_bb_p gb;
-  int i;
+  struct clast_stmt *t;
+  int index = 0;
 
-  int max_schedule = scop_max_loop_depth (scop) + 1;
-  lambda_vector last_schedule = lambda_vector_new (max_schedule);
-  lambda_vector_clear (last_schedule, max_schedule);
+  for (t = user_stmt->substitutions; t; t = t->next, index++)
+    {
+      PTR *slot;
+      struct ivtype_map_elt tmp;
+      struct clast_expr *expr = (struct clast_expr *) 
+       ((struct clast_assignment *)t)->RHS;
 
-  /* Update schedules.  */
-  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
+      /* Create an entry (clast_var, type).  */
+      tmp.cloog_iv = find_cloog_iv_in_expr (expr);
+      if (!tmp.cloog_iv)
+       continue;
+
+      slot = htab_find_slot (GBB_CLOOG_IV_TYPES (gbb), &tmp, INSERT);
+
+      if (!*slot)
+       {
+         loop_p loop = gbb_loop_at_index (gbb, index);
+         tree oldiv = oldiv_for_loop (GBB_SCOP (gbb), loop);
+         tree type = oldiv ? TREE_TYPE (oldiv) : integer_type_node;
+         *slot = new_ivtype_map_elt (tmp.cloog_iv, type);
+       }
+    }
+}
+
+/* Walk the CLAST tree starting from STMT and build for each
+   clast_user_stmt a map between the CLAST induction variables and the
+   corresponding GCC old induction variables.  This information is
+   stored on each GRAPHITE_BB.  */
+
+static void
+compute_cloog_iv_types (struct clast_stmt *stmt)
+{
+  if (!stmt)
+    return;
+
+  if (CLAST_STMT_IS_A (stmt, stmt_root))
+    goto next;
+
+  if (CLAST_STMT_IS_A (stmt, stmt_user))
+    {
+      CloogStatement *cs = ((struct clast_user_stmt *) stmt)->statement;
+      graphite_bb_p gbb = (graphite_bb_p) cloog_statement_usr (cs);
+      GBB_CLOOG_IV_TYPES (gbb) = htab_create (10, ivtype_map_elt_info,
+                                             eq_ivtype_map_elts, free);
+      compute_cloog_iv_types_1 (gbb, (struct clast_user_stmt *) stmt);
+      goto next;
+    }
+
+  if (CLAST_STMT_IS_A (stmt, stmt_for))
     {
-      int nb_loops = gbb_nb_loops (gb);
+      struct clast_stmt *s = ((struct clast_for *) stmt)->body;
+      compute_cloog_iv_types (s);
+      goto next;
+    }
 
-      if (GBB_STATIC_SCHEDULE (gb) [nb_loops] == 0)
-        last_schedule [nb_loops] = 0;
+  if (CLAST_STMT_IS_A (stmt, stmt_guard))
+    {
+      struct clast_stmt *s = ((struct clast_guard *) stmt)->then;
+      compute_cloog_iv_types (s);
+      goto next;
+    }
 
-      if (gbb_can_be_ignored (gb))
-        {
-          /* Mark gbb for remove.  */
-          bitmap_clear_bit (SCOP_BBS_B (scop), gb->bb->index);
-          GBB_SCOP (gb) = NULL;
-          last_schedule [nb_loops]--;
-        }
-      else
-        lambda_vector_add (GBB_STATIC_SCHEDULE (gb), last_schedule,
-                           GBB_STATIC_SCHEDULE (gb), nb_loops + 1);
+  if (CLAST_STMT_IS_A (stmt, stmt_block))
+    {
+      struct clast_stmt *s = ((struct clast_block *) stmt)->body;
+      compute_cloog_iv_types (s);
+      goto next;
     }
 
-  /* Remove gbbs.  */
-  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
-    if (GBB_SCOP (gb) == NULL)
-      {
-        VEC_unordered_remove (graphite_bb_p, SCOP_BBS (scop), i);
-        free_graphite_bb (gb);
-        /* XXX: Hackish? But working.  */
-        i--;
-      }  
+  gcc_unreachable ();
 
-  graphite_sort_gbbs (scop);
+ next:
+  compute_cloog_iv_types (stmt->next);
+}
+
+/* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for
+   the given SCOP.  */
+
+static void
+gloog (scop_p scop, struct clast_stmt *stmt)
+{
+  edge new_scop_exit_edge = NULL;
+  VEC (iv_stack_entry_p, heap) *ivstack = VEC_alloc (iv_stack_entry_p, heap,
+                                                    10);
+  loop_p context_loop;
+  ifsese if_region = NULL;
+
+  if (!can_generate_code (stmt))
+    {
+      cloog_clast_free (stmt);
+      return;
+    }
+
+  if_region = move_sese_in_condition (SCOP_REGION (scop));
+  rewrite_into_sese_closed_ssa (SCOP_REGION (scop),
+                               if_region->region->exit->src,
+                               if_region->false_region->exit,
+                               if_region->true_region->exit);
+  graphite_verify ();
+  context_loop = SESE_ENTRY (SCOP_REGION (scop))->src->loop_father;
+  compute_cloog_iv_types (stmt);
+  new_scop_exit_edge = translate_clast (scop, context_loop,
+                                       stmt, if_region->true_region->entry,
+                                       &ivstack);
+  graphite_verify ();
+  cleanup_tree_cfg ();
+  recompute_all_dominators ();
+  graphite_verify ();
+  free_loop_iv_stack (&ivstack);
+  cloog_clast_free (stmt);
+}
+
+/* Returns the number of data references in SCOP.  */
+
+static int
+nb_data_refs_in_scop (scop_p scop)
+{
+  int i;
+  graphite_bb_p gbb;
+  int res = 0;
+
+  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gbb); i++)
+    res += VEC_length (data_reference_p, GBB_DATA_REFS (gbb));
+
+  return res;
 }
 
 /* Move the loop at index LOOP and insert it before index NEW_LOOP_POS.
@@ -4962,11 +5479,6 @@ graphite_trans_loop_block (VEC (graphite_bb_p, heap) *bbs, int loops)
   /* TODO: - Calculate the stride size automatically.  */
   int stride_size = 64;
 
-  /* It makes no sense to block a single loop.  */
-  for (i = 0; VEC_iterate (graphite_bb_p, bbs, i, gb); i++)
-    if (gbb_nb_loops (gb) < 2)
-      return false;
-
   for (i = 0; VEC_iterate (graphite_bb_p, bbs, i, gb); i++)
     transform_done |= graphite_trans_bb_block (gb, stride_size, loops);
 
@@ -5049,7 +5561,7 @@ graphite_trans_scop_block (scop_p scop)
       j++;
 
       /* Found perfect loop nest.  */
-      if (perfect && last_nb_loops - j > 0)
+      if (perfect && last_nb_loops - j >= 2)
         transform_done |= graphite_trans_loop_block (bbs, last_nb_loops - j);
  
       /* Check if we start with a new loop.
@@ -5108,7 +5620,6 @@ graphite_apply_transformations (scop_p scop)
 
   /* Sort the list of bbs.  Keep them always sorted.  */
   graphite_sort_gbbs (scop);
-  scop_remove_ignoreable_gbbs (scop);
 
   if (flag_loop_block)
     transform_done = graphite_trans_scop_block (scop);
@@ -5157,13 +5668,15 @@ limit_scops (void)
       int j;
       loop_p loop;
       build_scop_bbs (scop);
-      build_scop_loop_nests (scop);
+
+      if (!build_scop_loop_nests (scop))
+       continue;
 
       for (j = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), j, loop); j++) 
         if (!loop_in_scop_p (loop_outer (loop), scop))
           {
            sd_region open_scop;
-           open_scop.entry = loop_preheader_edge (loop)->dest;
+           open_scop.entry = loop->header;
            open_scop.exit = single_exit (loop)->dest;
            VEC_safe_push (sd_region, heap, tmp_scops, &open_scop);
          }
@@ -5190,13 +5703,12 @@ graphite_transform_loops (void)
     return;
 
   current_scops = VEC_alloc (scop_p, heap, 3);
-
-  calculate_dominance_info (CDI_DOMINATORS);
-  calculate_dominance_info (CDI_POST_DOMINATORS);
+  recompute_all_dominators ();
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Graphite loop transformations \n");
 
+  initialize_original_copy_tables ();
   cloog_initialize ();
   build_scops ();
   limit_scops ();
@@ -5208,9 +5720,12 @@ graphite_transform_loops (void)
   for (i = 0; VEC_iterate (scop_p, current_scops, i, scop); i++)
     {
       build_scop_bbs (scop);
-      build_scop_loop_nests (scop);
+      if (!build_scop_loop_nests (scop))
+       continue;
+
       build_scop_canonical_schedules (scop);
       build_bb_loops (scop);
+      build_scop_conditions (scop);
       find_scop_parameters (scop);
       build_scop_context (scop);
 
@@ -5226,8 +5741,8 @@ graphite_transform_loops (void)
       if (!build_scop_iteration_domain (scop))
        continue;
 
-      build_scop_conditions (scop);
       build_scop_data_accesses (scop);
+      build_scop_dynamic_schedules (scop);
 
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
@@ -5237,11 +5752,19 @@ graphite_transform_loops (void)
 
       if (graphite_apply_transformations (scop))
         gloog (scop, find_transform (scop));
+#ifdef ENABLE_CHECKING
+      else
+       {
+         struct clast_stmt *stmt = find_transform (scop);
+         cloog_clast_free (stmt);
+       }
+#endif
     }
 
   /* Cleanup.  */
   free_scops (current_scops);
   cloog_finalize ();
+  free_original_copy_tables ();
 }
 
 #else /* If Cloog is not available: #ifndef HAVE_cloog.  */