Fix testsuite/gfortran.dg/graphite/id-4.f90.
authorSebastian Pop <spop@gcc.gnu.org>
Thu, 11 Dec 2008 07:23:02 +0000 (07:23 +0000)
committerSebastian Pop <spop@gcc.gnu.org>
Thu, 11 Dec 2008 07:23:02 +0000 (07:23 +0000)
2008-12-11  Sebastian Pop  <sebastian.pop@amd.com>

Fix testsuite/gfortran.dg/graphite/id-4.f90.
* graphite.c (scan_tree_for_params): Do not compute the multiplicand
when not needed.

2008-12-11  Sebastian Pop  <sebastian.pop@amd.com>

* graphite.c (build_scops_1): Initialize open_scop.exit
and sinfo.last.

2008-12-11  Sebastian Pop  <sebastian.pop@amd.com>
    Jan Sjodin  <jan.sjodin@amd.com>
            Harsha Jagasia  <harsha.jagasia@amd.com>

PR middle-end/37852
PR middle-end/37883
PR middle-end/37928
PR middle-end/37980
PR middle-end/38038
PR middle-end/38039
PR middle-end/38073
PR middle-end/38083
PR middle-end/38125

* tree-phinodes.c (remove_phi_nodes): New, extracted from...
* tree-cfg.c (remove_phi_nodes_and_edges_for_unreachable_block): ...here.
* tree-flow.h (remove_phi_nodes, canonicalize_loop_ivs): Declared.
* Makefile.in (graphite.o): Depend on value-prof.h.
(graphite.o-warn): Removed -Wno-error.
* tree-parloops.c (canonicalize_loop_ivs): Allow reduction_list
to be a NULL pointer.  Call update_stmt.  Return the newly created
cannonical induction variable.

* graphite.h (debug_rename_map): Declared.  Fix some comments.

* graphite.c: Reimplement the code generation from graphite to gimple.
Include value-prof.h.
(loop_iv_stack_get_iv): Do not return NULL for constant substitutions.
(get_old_iv_from_ssa_name): Removed.
(graphite_stmt_p): New.
(new_graphite_bb): Test for useful statements before building a
graphite statement for the basic block.
(free_graphite_bb): Do not free GBB_DATA_REFS: this is a bug
in free_data_ref that calls BITMAP_FREE (DR_VOPS (dr)) without
reason.
(recompute_all_dominators, graphite_verify,
nb_reductions_in_loop, graphite_loop_normal_form): New.
(scop_record_loop): Call graphite_loop_normal_form.
(build_scop_loop_nests): Iterate over all the blocks of the
function instead of relying on the incomplete information from
SCOP_BBS.  Return the success of the operation.
(find_params_in_bb): Use the data from GBB_DATA_REFS.
(add_bb_domains): Removed.
(build_loop_iteration_domains): Don't call add_bb_domains.
Add the iteration domain only to the basic blocks that have been
translated to graphite.
(build_scop_conditions_1): Add constraints only if the basic
block have been translated to graphite.
(build_scop_data_accesses): Completely disabled until data
dependence is correctly implemented.
(debug_rename_elt, debug_rename_map_1, debug_rename_map): New.
(remove_all_edges_1, remove_all_edges): Removed.
(get_new_name_from_old_name): New.
(graphite_rename_variables_in_stmt): Renamed
rename_variables_in_stmt.  Call get_new_name_from_old_name.
Use replace_exp and update_stmt.
(is_old_iv): Renamed is_iv.
(expand_scalar_variables_stmt): Extra parameter for renaming map.
Use replace_exp and update_stmt.
(expand_scalar_variables_expr): Same.  Use the map to get the
new names for the renaming of induction variables and for the
renaming of variables after a basic block has been copied.
(expand_scalar_variables): Same.
(graphite_rename_variables): Renamed rename_variables.
(move_phi_nodes): Removed.
(get_false_edge_from_guard_bb): New.
(build_iv_mapping): Do not insert the induction variable of a
loop in the renaming iv map if the basic block does not belong
to that loop.
(register_old_new_names, graphite_copy_stmts_from_block,
copy_bb_and_scalar_dependences): New.
(translate_clast): Heavily reimplemented: copy basic blocks,
do not move them.  Finally, in call cleanup_tree_cfg in gloog.
At each translation step call graphite_verify ensuring the
consistency of the SSA, loops and dominators information.
(collect_virtual_phis, find_vdef_for_var_in_bb,
find_vdef_for_var_1, find_vdef_for_var,
patch_phis_for_virtual_defs): Removed huge hack.
(mark_old_loops, remove_dead_loops, skip_phi_defs,
collect_scop_exit_phi_args, patch_scop_exit_phi_args,
gbb_can_be_ignored, scop_remove_ignoreable_gbbs, ): Removed.
(remove_sese_region, ifsese, if_region_entry, if_region_exit,
if_region_get_condition_block, if_region_set_false_region,
create_if_region_on_edge, move_sese_in_condition, bb_in_sese_p,
sese_find_uses_to_rename_use, sese_find_uses_to_rename_bb,
sese_add_exit_phis_edge, sese_add_exit_phis_var,
rewrite_into_sese_closed_ssa): New.
(gloog): Remove dead code.  Early return if code cannot be
generated.  Call cleanup_tree_cfg once the scop has been code
generated.
(graphite_trans_scop_block, graphite_trans_loop_block): Do not
block loops with less than two loops.
(graphite_apply_transformations): Remove the call to
scop_remove_ignoreable_gbbs.
(limit_scops): When build_scop_loop_nests fails, continue on next scop.
Fix open_scop.entry.
(graphite_transform_loops): Call recompute_all_dominators: force the
recomputation of correct CDI_DOMINATORS and CDI_POST_DOMINATORS.
Call initialize_original_copy_tables and free_original_copy_tables
to be able to copy basic blocks during code generation.
When build_scop_loop_nests fails, continue on next scop.
(value_clast): New union.
(clast_to_gcc_expression): Fix type cast warning.

2008-12-11  Sebastian Pop  <sebastian.pop@amd.com>

* gcc.dg/graphite/pr37928.c: New.
* gcc.dg/graphite/pr37883.c: New.
* gcc.dg/graphite/pr38073.c: New.
* gcc.dg/graphite/pr38125.c: New.
* gfortran.dg/graphite/pr38083.f90: New.
* gfortran.dg/graphite/pr37852.f90: New.
* gfortran.dg/graphite/pr37980.f90: New.
* gfortran.dg/graphite/id-2.f90: New.
* gfortran.dg/graphite/id-4.f90: New.

* gcc.dg/graphite/scop-18.c: Remove reduction, test for
the number of detected scops.  Copy exact same test for loop blocking...
* gcc.dg/graphite/block-1.c: Fix the number of expected loops
to be blocked as reductions are not handled.
* gcc.dg/graphite/block-4.c: ...here.  New.

From-SVN: r142673

21 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/graphite.c
gcc/graphite.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/graphite/block-1.c
gcc/testsuite/gcc.dg/graphite/block-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/graphite/pr37883.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/graphite/pr37928.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/graphite/pr38073.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/graphite/pr38125.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/graphite/scop-18.c
gcc/testsuite/gfortran.dg/graphite/id-2.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/graphite/id-4.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/graphite/pr37852.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/graphite/pr37980.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/graphite/pr38083.f90 [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-flow.h
gcc/tree-parloops.c
gcc/tree-phinodes.c

index e8ee6f2a567df1d2b63715b5e7f90e3870c49da5..f51730a1f4b4cf36a9f5c14eb744a333a324b97f 100644 (file)
@@ -1,3 +1,118 @@
+2008-12-11  Sebastian Pop  <sebastian.pop@amd.com>
+
+       Fix testsuite/gfortran.dg/graphite/id-4.f90.
+       * graphite.c (scan_tree_for_params): Do not compute the multiplicand
+       when not needed.
+
+2008-12-11  Sebastian Pop  <sebastian.pop@amd.com>
+
+       * graphite.c (build_scops_1): Initialize open_scop.exit
+       and sinfo.last.
+
+2008-12-11  Sebastian Pop  <sebastian.pop@amd.com>
+           Jan Sjodin  <jan.sjodin@amd.com>
+            Harsha Jagasia  <harsha.jagasia@amd.com>
+
+       PR middle-end/37852
+       PR middle-end/37883
+       PR middle-end/37928
+       PR middle-end/37980
+       PR middle-end/38038
+       PR middle-end/38039
+       PR middle-end/38073
+       PR middle-end/38083
+       PR middle-end/38125
+
+       * tree-phinodes.c (remove_phi_nodes): New, extracted from...
+       * tree-cfg.c (remove_phi_nodes_and_edges_for_unreachable_block): ...here.
+       * tree-flow.h (remove_phi_nodes, canonicalize_loop_ivs): Declared.
+       * Makefile.in (graphite.o): Depend on value-prof.h.
+       (graphite.o-warn): Removed -Wno-error.
+       * tree-parloops.c (canonicalize_loop_ivs): Allow reduction_list 
+       to be a NULL pointer.  Call update_stmt.  Return the newly created 
+       cannonical induction variable.
+
+       * graphite.h (debug_rename_map): Declared.  Fix some comments.
+
+       * graphite.c: Reimplement the code generation from graphite to gimple.
+       Include value-prof.h.
+       (loop_iv_stack_get_iv): Do not return NULL for constant substitutions.
+       (get_old_iv_from_ssa_name): Removed.
+       (graphite_stmt_p): New.
+       (new_graphite_bb): Test for useful statements before building a
+       graphite statement for the basic block.
+       (free_graphite_bb): Do not free GBB_DATA_REFS: this is a bug
+       in free_data_ref that calls BITMAP_FREE (DR_VOPS (dr)) without 
+       reason.
+       (recompute_all_dominators, graphite_verify,
+       nb_reductions_in_loop, graphite_loop_normal_form): New.
+       (scop_record_loop): Call graphite_loop_normal_form.
+       (build_scop_loop_nests): Iterate over all the blocks of the
+       function instead of relying on the incomplete information from
+       SCOP_BBS.  Return the success of the operation.
+       (find_params_in_bb): Use the data from GBB_DATA_REFS.
+       (add_bb_domains): Removed.
+       (build_loop_iteration_domains): Don't call add_bb_domains.
+       Add the iteration domain only to the basic blocks that have been
+       translated to graphite.
+       (build_scop_conditions_1): Add constraints only if the basic
+       block have been translated to graphite.
+       (build_scop_data_accesses): Completely disabled until data
+       dependence is correctly implemented.
+       (debug_rename_elt, debug_rename_map_1, debug_rename_map): New.
+       (remove_all_edges_1, remove_all_edges): Removed.
+       (get_new_name_from_old_name): New.
+       (graphite_rename_variables_in_stmt): Renamed 
+       rename_variables_in_stmt.  Call get_new_name_from_old_name.
+       Use replace_exp and update_stmt.
+       (is_old_iv): Renamed is_iv.
+       (expand_scalar_variables_stmt): Extra parameter for renaming map.
+       Use replace_exp and update_stmt.
+       (expand_scalar_variables_expr): Same.  Use the map to get the
+       new names for the renaming of induction variables and for the
+       renaming of variables after a basic block has been copied.
+       (expand_scalar_variables): Same.
+       (graphite_rename_variables): Renamed rename_variables.
+       (move_phi_nodes): Removed.
+       (get_false_edge_from_guard_bb): New.
+       (build_iv_mapping): Do not insert the induction variable of a
+       loop in the renaming iv map if the basic block does not belong
+       to that loop.
+       (register_old_new_names, graphite_copy_stmts_from_block,
+       copy_bb_and_scalar_dependences): New.
+       (translate_clast): Heavily reimplemented: copy basic blocks,
+       do not move them.  Finally, in call cleanup_tree_cfg in gloog.
+       At each translation step call graphite_verify ensuring the 
+       consistency of the SSA, loops and dominators information.
+       (collect_virtual_phis, find_vdef_for_var_in_bb,
+       find_vdef_for_var_1, find_vdef_for_var,
+       patch_phis_for_virtual_defs): Removed huge hack.
+       (mark_old_loops, remove_dead_loops, skip_phi_defs,
+       collect_scop_exit_phi_args, patch_scop_exit_phi_args,
+       gbb_can_be_ignored, scop_remove_ignoreable_gbbs, ): Removed.
+       (remove_sese_region, ifsese, if_region_entry, if_region_exit,
+       if_region_get_condition_block, if_region_set_false_region,
+       create_if_region_on_edge, move_sese_in_condition, bb_in_sese_p,
+       sese_find_uses_to_rename_use, sese_find_uses_to_rename_bb, 
+       sese_add_exit_phis_edge, sese_add_exit_phis_var,
+       rewrite_into_sese_closed_ssa): New.
+       (gloog): Remove dead code.  Early return if code cannot be
+       generated.  Call cleanup_tree_cfg once the scop has been code
+       generated.
+       (graphite_trans_scop_block, graphite_trans_loop_block): Do not 
+       block loops with less than two loops.
+       (graphite_apply_transformations): Remove the call to
+       scop_remove_ignoreable_gbbs.
+       (limit_scops): When build_scop_loop_nests fails, continue on next scop.
+       Fix open_scop.entry.
+       (graphite_transform_loops): Call recompute_all_dominators: force the
+       recomputation of correct CDI_DOMINATORS and CDI_POST_DOMINATORS.
+       Call initialize_original_copy_tables and free_original_copy_tables
+       to be able to copy basic blocks during code generation.
+       When build_scop_loop_nests fails, continue on next scop.
+       (value_clast): New union.
+       (clast_to_gcc_expression): Fix type cast warning.
+
 2008-12-10  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/36792
        Fix testsuite/gfortran.dg/graphite/id-3.f90.
        * graphite.c (scopdet_basic_block_info): Fix bug that found some
        regions more than once.
-       * testsuite/gfortran.dg/graphite/id-3.f90: New.
-       * gcc/testsuite/gcc.dg/graphite/pr38084.c: New.
 
 2008-12-09  Ben Elliston  <bje@au.ibm.com>
 
index 097159c6457b7e0ee0984db9d5500675d1732f84..644694b6adbf1607df98afc20b4050e7428f6be6 100644 (file)
@@ -183,8 +183,6 @@ dfp.o-warn = -Wno-error
 bitmap.o-warn = -Wno-error
 # dominance.c contains a -Wc++compat warning.
 dominance.o-warn = -Wno-error
-# graphite.c contains code calling cloog that has problems.
-graphite.o-warn = -Wno-error
 # mips-tfile.c contains -Wcast-qual warnings.
 mips-tfile.o-warn = -Wno-error
 
@@ -2368,7 +2366,8 @@ tree-data-ref.o: tree-data-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
 graphite.o: graphite.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(GGC_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TOPLEV_H) \
    $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) $(GIMPLE_H) domwalk.h \
-   $(TREE_DATA_REF_H) $(SCEV_H) tree-pass.h tree-chrec.h graphite.h pointer-set.h
+   $(TREE_DATA_REF_H) $(SCEV_H) tree-pass.h tree-chrec.h graphite.h pointer-set.h \
+   value-prof.h
 tree-vect-analyze.o: tree-vect-analyze.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TM_H) $(GGC_H) $(OPTABS_H) $(TREE_H) $(RECOG_H) $(BASIC_BLOCK_H) \
    $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
index 78485a2c8335e76e9f20aac0f6ed47c1cb5b89d8..7c2b8da90b97187451154177322a4373d8d85bb7 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"
 
@@ -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.  */
@@ -293,33 +290,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 *
@@ -610,14 +580,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 +780,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 +978,85 @@ 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;
   VEC_safe_push (graphite_bb_p, heap, SCOP_BBS (scop), gbb);
-  bitmap_set_bit (SCOP_BBS_B (scop), bb->index);
 }
 
 /* Frees GBB.  */
@@ -1052,11 +1067,9 @@ free_graphite_bb (struct graphite_bb *gbb)
   if (GBB_DOMAIN (gbb))
     cloog_matrix_free (GBB_DOMAIN (gbb));
 
-  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);
 }
@@ -1078,6 +1091,7 @@ new_scop (edge entry, edge exit)
   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 ());
@@ -1511,6 +1525,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 +1815,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 +1976,108 @@ 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;
 
-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 (chrec_contains_undetermined (scev))
+       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 +2094,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 +2238,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 +2319,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 +2451,44 @@ 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 +2612,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 +2646,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 +2656,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 +2737,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 +2961,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 +3128,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 +3165,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 +3231,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.  */
@@ -3199,6 +3288,13 @@ clast_name_to_gcc (const char *name, VEC (name_tree, heap) *params,
   gcc_unreachable ();
 }
 
+/* A union needed to convert from CLAST expressions to GMP values.  */
+
+typedef union {
+  struct clast_expr *c;
+  Value v;
+} value_clast;
+
 /* Converts a Cloog AST expression E back to a GCC expression tree.   */
 
 static tree
@@ -3299,15 +3395,12 @@ 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);
+       value_clast r;
+       tree tr;
 
-       /* 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);
+       r.c = (struct clast_expr *) b->RHS;
+       tr = gmp_cst_to_tree (r.v);
 
        switch (b->type)
          {
@@ -3426,97 +3519,149 @@ graphite_create_new_loop (scop_p scop, edge entry_edge,
   return loop;
 }
 
-/* Remove all the edges from EDGES except the edge KEEP.  */
-
-static void
-remove_all_edges_1 (VEC (edge, gc) *edges, 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
 {
-  edge e;
-  edge_iterator ei;
+  tree old_name, new_name;
+} *rename_map_elt;
 
-  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);
-    }
-}
 
-/* Remove all the edges from BB except the edge KEEP.  */
+/* Print to stderr the element ELT.  */
 
 static void
-remove_all_edges (basic_block bb, edge keep)
+debug_rename_elt (rename_map_elt elt)
 {
-  remove_all_edges_1 (bb->succs, keep);
-  remove_all_edges_1 (bb->preds, keep);
+  fprintf (stderr, "(");
+  print_generic_expr (stderr, elt->old_name, 0);
+  fprintf (stderr, ", ");
+  print_generic_expr (stderr, elt->new_name, 0);
+  fprintf (stderr, ")\n");
 }
 
-/* Rename the SSA_NAMEs used in STMT and that appear in IVSTACK.  */
+/* Helper function for debug_rename_map.  */
 
-static void 
-graphite_rename_ivs_stmt (gimple stmt, graphite_bb_p gbb, scop_p scop,
-                         loop_p old, loop_iv_stack ivstack)
+static int
+debug_rename_map_1 (void **slot, void *s ATTRIBUTE_UNUSED)
 {
-  ssa_op_iter iter;
-  use_operand_p use_p;
+  struct rename_map_elt *entry = (struct rename_map_elt *) *slot;
+  debug_rename_elt (entry);
+  return 1;
+}
 
-  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));
+/* Print to stderr all the elements of MAP.  */
 
-      if (new_iv)
-       SET_USE (use_p, new_iv);
-    }
+void
+debug_rename_map (htab_t map)
+{
+  htab_traverse (map, debug_rename_map_1, NULL);
 }
 
-/* Returns true if SSA_NAME is a parameter of SCOP.  */
+/* Constructs a new SCEV_INFO_STR structure for VAR and INSTANTIATED_BELOW.  */
 
-static bool
-is_parameter (scop_p scop, tree ssa_name)
+static inline rename_map_elt
+new_rename_map_elt (tree old_name, tree new_name)
 {
-  int i;
-  VEC (name_tree, heap) *params = SCOP_PARAMS (scop);
-  name_tree param;
+  rename_map_elt res;
+  
+  res = XNEW (struct rename_map_elt);
+  res->old_name = old_name;
+  res->new_name = new_name;
 
-  for (i = 0; VEC_iterate (name_tree, params, i, param); i++)
-    if (param->t == ssa_name)
-      return true;
+  return res;
+}
 
-  return false;
+/* 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);
 }
 
-/* Returns true if NAME is an old induction variable in SCOP.  OLD is
-   the original loop that contained the definition of NAME.  */
+/* Compares database elements E1 and E2.  */
 
-static bool
-is_old_iv (scop_p scop, loop_p old, tree name)
+static int
+eq_rename_map_elts (const void *e1, const void *e2)
 {
-  return get_old_iv_from_ssa_name (scop, old, name) != NULL;
+  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);
 }
 
-static void expand_scalar_variables_stmt (gimple, graphite_bb_p, scop_p, loop_p,
-                                         loop_iv_stack);
+/* Returns the new name associated to OLD_NAME in MAP.  */
 
-/* Constructs a tree which only contains old_ivs and parameters.  Any
-   other variables that are defined outside GBB will be eliminated by
-   using their definitions in the constructed tree.  OLD_LOOP_FATHER
-   is the original loop that contained GBB.  */
+static tree
+get_new_name_from_old_name (htab_t map, tree old_name)
+{
+  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 
+rename_variables_in_stmt (gimple stmt, htab_t map)
+{
+  ssa_op_iter iter;
+  use_operand_p use_p;
+
+  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+    {
+      tree use = USE_FROM_PTR (use_p);
+      tree new_name = get_new_name_from_old_name (map, use);
+
+      replace_exp (use_p, new_name);
+    }
+
+  update_stmt (stmt);
+}
+
+/* Returns true if SSA_NAME is a parameter of SCOP.  */
+
+static bool
+is_parameter (scop_p scop, tree ssa_name)
+{
+  int i;
+  VEC (name_tree, heap) *params = SCOP_PARAMS (scop);
+  name_tree param;
+
+  for (i = 0; VEC_iterate (name_tree, params, i, param); i++)
+    if (param->t == ssa_name)
+      return true;
+
+  return false;
+}
+
+/* Returns true if NAME is an induction variable.  */
+
+static bool
+is_iv (tree name)
+{
+  return gimple_code (SSA_NAME_DEF_STMT (name)) == GIMPLE_PHI;
+}
+
+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 BB will be eliminated by
+   using their definitions in the constructed tree.  OLD_LOOP_FATHER
+   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 +3674,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 +3685,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 +3701,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 +3737,66 @@ 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 that appear in IVSTACK in
+   terms of new induction variables.  OLD is the original loop that
+   contained BB.  */
 
 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);
-
-      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);
-       }
-    }
-}
-
-/* Move all the PHI nodes from block FROM to block TO.
-   OLD_LOOP_FATHER is the original loop that contained FROM.  */
-
-static void
-move_phi_nodes (scop_p scop, loop_p old_loop_father, basic_block from,
-               basic_block to)
-{
-  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_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    rename_variables_in_stmt (gsi_stmt (gsi), map);
 }
 
 /* Remove condition from BB.  */
@@ -3727,6 +3829,131 @@ 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);
+
+  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 +3971,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 +4005,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 +4020,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 +4029,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);
     }
 
@@ -4026,183 +4244,6 @@ find_transform (scop_p scop)
   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);
-}
-
-/* Mark the original loops of SCOP for removal, replacing their header
-   field with NULL.  */
-
-static void
-mark_old_loops (scop_p scop)
-{
-  int i;
-  struct loop *loop;
-
-  for (i = 0; VEC_iterate (loop_p, SCOP_LOOP_NEST (scop), i, loop); i++)
-    {
-      loop->header = NULL;
-      loop->latch = NULL;
-    }
-}
-
-/* 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;
-
-  FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
-    {
-      /* 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);
-    }
-}
-
 /* Returns true when it is possible to generate code for this STMT.
    For the moment we cannot generate code when Cloog decides to
    duplicate a statement, as we do not do a copy, but a move.
@@ -4261,230 +4302,326 @@ 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;
-
-  for (gsi = gsi_start_phis (scop_exit->dest); !gsi_end_p (gsi); gsi_next (&gsi))
-    {
-      gimple phi = gsi_stmt (gsi);
-      tree phi_arg = skip_phi_defs(PHI_ARG_DEF_FROM_EDGE (phi, scop_exit));
-
-      VEC_safe_push (tree, heap, phi_args, phi_arg);
-    }
+  return SESE_ENTRY (if_region->region);
+}
 
-  return phi_args;
+static inline edge
+if_region_exit (ifsese if_region)
+{
+  return SESE_EXIT (if_region->region);
 }
 
-/* Patches (adds) PHI_ARGS to the phi nodes in SCOP_EXIT destination.  */
+static inline basic_block
+if_region_get_condition_block (ifsese if_region)
+{
+  return if_region_entry (if_region)->dest;
+}
 
-static void
-patch_scop_exit_phi_args (edge scop_exit,
-                         VEC (tree, heap) *phi_args)
+static inline void
+if_region_set_false_region (ifsese if_region, sese region)
 {
-  int i = 0;
-  gimple_stmt_iterator gsi;
+  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;
+
+  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 ();
 
-  for (gsi = gsi_start_phis (scop_exit->dest); !gsi_end_p (gsi);
-       gsi_next (&gsi), i++)
+  SESE_EXIT (region) = single_succ_edge (false_edge->dest);
+  if_region->false_region = region;
+
+  if (slot)
     {
-      tree def = VEC_index (tree, phi_args, i);
-      gimple phi = gsi_stmt (gsi);
+      struct loop_exit *loop_exit = GGC_CNEW (struct loop_exit);
 
-      gcc_assert (PHI_ARG_DEF_FROM_EDGE (phi, scop_exit) == NULL);
+      memcpy (loop_exit, *((struct loop_exit **) slot), sizeof (struct loop_exit));
+      htab_clear_slot (current_loops->exits, slot);
 
-      add_phi_arg (phi, def, scop_exit);
+      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;
     }
 }
 
-/* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for
-   the given SCOP.  */
-
-static void
-gloog (scop_p scop, struct clast_stmt *stmt)
+static ifsese
+create_if_region_on_edge (edge entry, tree condition)
 {
-  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);
+  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);
 
-  if (!can_generate_code (stmt))
+  if_region->region = sese_region;
+  if_region->region->entry = entry;
+  if_region->region->exit = exit;
+
+  FOR_EACH_EDGE (e, ei, entry->dest->succs)
     {
-      cloog_clast_free (stmt);
-      return;
+      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;
+       }
     }
 
-  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);
+  return if_region;
+}
 
-  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);
+/* Moves REGION in a condition expression:
+   | if (1)
+   |   ;
+   | else
+   |   REGION;
+*/
 
-  cloog_clast_free (stmt);
+static ifsese
+move_sese_in_condition (sese region)
+{
+  basic_block pred_block = split_edge (SESE_ENTRY (region));
+  ifsese if_region = NULL;
 
-  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); 
+  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);
 
-#ifdef ENABLE_CHECKING
-  verify_loop_structure ();
-  verify_dominators (CDI_DOMINATORS);
-  verify_ssa (false);
-#endif
+  return if_region;
 }
 
-/* Returns the number of data references in SCOP.  */
+/* Returns true when BB is in REGION.  */
 
-static int
-nb_data_refs_in_scop (scop_p scop)
+static bool
+bb_in_sese_p (basic_block bb, sese region)
 {
-  int i;
-  graphite_bb_p gbb;
-  int res = 0;
+  return (dominated_by_p (CDI_DOMINATORS, bb, SESE_ENTRY (region)->src)
+         && dominated_by_p (CDI_POST_DOMINATORS, bb, SESE_EXIT (region)->dest));
+}
 
-  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gbb); i++)
-    res += VEC_length (data_reference_p, GBB_DATA_REFS (gbb));
+/* 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.  */
 
-  return res;
+static void
+sese_find_uses_to_rename_use (sese region, basic_block bb, tree use,
+                             bitmap *use_blocks, bitmap need_phis)
+{
+  unsigned ver;
+  basic_block def_bb;
+
+  if (TREE_CODE (use) != SSA_NAME)
+    return;
+
+  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 (!use_blocks[ver])
+    use_blocks[ver] = BITMAP_ALLOC (NULL);
+  bitmap_set_bit (use_blocks[ver], bb->index);
+
+  bitmap_set_bit (need_phis, ver);
 }
 
-/* Check if a graphite bb can be ignored in graphite.  We ignore all
-   bbs, that only contain code, that will be eliminated later.
+/* 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.  */
+
+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);
 
-   TODO: - Move PHI nodes and scalar variables out of these bbs, that only
-           remain conditions and induction variables.  */
+  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);
+}
 
-static bool
-gbb_can_be_ignored (graphite_bb_p gb)
+/* Add exit phis for the USE on EXIT.  */
+
+static void
+sese_add_exit_phis_edge (basic_block exit, tree use, edge false_e, edge true_e)
 {
-  gimple_stmt_iterator gsi;
-  scop_p scop = GBB_SCOP (gb);
-  loop_p loop = GBB_BB (gb)->loop_father;
+  gimple phi = create_phi_node (use, exit);
 
-  if (VEC_length (data_reference_p, GBB_DATA_REFS(gb)))
-    return false;
+  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, integer_zero_node, true_e);
+}
 
-  /* 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;
+/* Add phi nodes for VAR that is used in LIVEIN.  Phi nodes are
+   inserted in block WHERE.  */
 
-          /* 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);
+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 (TREE_CODE (var) == SCEV_NOT_KNOWN)
-               return false;
+  if (is_gimple_reg (var))
+    bitmap_clear_bit (livein, def_bb->index);
+  else
+    bitmap_set_bit (livein, def_bb->index);
 
-             break;
-           }
-          /* Otherwise not ignoreable.  */
-          default:
-            return false;
-        }
-    }
+  def = BITMAP_ALLOC (NULL);
+  bitmap_set_bit (def, def_bb->index);
+  compute_global_livein (livein, def);
+  BITMAP_FREE (def);
 
-  return true;
+  sese_add_exit_phis_edge (where, var, false_e, true_e);
 }
 
-/* Remove all ignoreable gbbs from SCOP.  */
+/* Insert in the block WHERE phi nodes for variables defined in REGION
+   and used outside the REGION.  */
 
 static void
-scop_remove_ignoreable_gbbs (scop_p scop)
+rewrite_into_sese_closed_ssa (sese region, basic_block where,
+                             edge false_e, edge true_e)
 {
-  graphite_bb_p gb;
-  int i;
+  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);
 
-  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);
+  update_ssa (TODO_update_ssa);
 
-  /* Update schedules.  */
-  for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++)
-    {
-      int nb_loops = gbb_nb_loops (gb);
+  FOR_EACH_BB (bb)
+    sese_find_uses_to_rename_bb (region, bb, use_blocks, names_to_rename);
 
-      if (GBB_STATIC_SCHEDULE (gb) [nb_loops] == 0)
-        last_schedule [nb_loops] = 0;
+  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);
 
-      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);
+  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);
+}
+
+/* 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;
     }
 
-  /* 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--;
-      }  
+  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;
+  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);
+}
 
-  graphite_sort_gbbs (scop);
+/* 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 +5099,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 +5181,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 +5240,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 +5288,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 +5323,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 +5340,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 +5361,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))
        {
@@ -5249,6 +5384,7 @@ graphite_transform_loops (void)
   /* Cleanup.  */
   free_scops (current_scops);
   cloog_finalize ();
+  free_original_copy_tables ();
 }
 
 #else /* If Cloog is not available: #ifndef HAVE_cloog.  */
index 2e2904a6abf9c9976dc56402299eef28e7efd2a1..faae00950d66d3cdde94eacc359a9f2875137c35 100644 (file)
@@ -18,6 +18,9 @@ You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+#ifndef GCC_GRAPHITE_H
+#define GCC_GRAPHITE_H
+
 #include "tree-data-ref.h"
 
 typedef struct graphite_bb *graphite_bb_p;
@@ -31,7 +34,7 @@ static inline int scop_nb_loops (scop_p scop);
 static inline unsigned scop_nb_params (scop_p scop);
 static inline bool scop_contains_loop (scop_p scop, struct loop *loop);
 
-struct graphite_bb
+typedef struct graphite_bb
 {
   basic_block bb;
   scop_p scop;
@@ -116,7 +119,7 @@ struct graphite_bb
    CloogMatrix *domain;
 
   /* Lists containing the restrictions of the conditional statements
-     dominating this bb. This bb can only be executed, if all conditions
+     dominating this bb.  This bb can only be executed, if all conditions
      are true.
  
      Example:
@@ -129,13 +132,13 @@ struct graphite_bb
          B
      }
  
-     So for B there is a additional condition (2i <= 8).
+     So for B there is an additional condition (2i <= 8).
  
-     TODO: Add this restrictions to the domain matrix.
+     TODO: Add these restrictions to the domain matrix.
       
-     List of COND_EXPR and SWITCH_EXPR. A COND_EXPR is true only if the 
-     corresponding element in CONDITION_CASES is not NULL_TREE. For a 
-     SWITCH_EXPR the corresponding element in CONDITION_CASES is a 
+     List of COND_EXPR and SWITCH_EXPR.  A COND_EXPR is true only if the
+     corresponding element in CONDITION_CASES is not NULL_TREE.  For a
+     SWITCH_EXPR the corresponding element in CONDITION_CASES is a
      CASE_LABEL_EXPR.  */
   VEC (gimple, heap) *conditions;
   VEC (gimple, heap) *condition_cases;
@@ -190,7 +193,7 @@ struct graphite_bb
   lambda_vector compressed_alpha_matrix;
   CloogMatrix *dynamic_schedule;
   VEC (data_reference_p, heap) *data_refs;
-};
+} *gbb_p;
 
 #define GBB_BB(GBB) GBB->bb
 #define GBB_SCOP(GBB) GBB->scop
@@ -234,7 +237,7 @@ gbb_loop_at_index (graphite_bb_p gb, int index)
   return VEC_index (loop_p, GBB_LOOPS (gb), index);
 }
 
-/* Returns the corresponding loop iterator index for a gimple loop.  */
+/* Returns the index of LOOP in the loop nest around GB.  */
 
 static inline int
 gbb_loop_index (graphite_bb_p gb, loop_p loop)
@@ -305,8 +308,13 @@ struct scop
   /* ???  It looks like a global mapping loop_id -> cloog_loop would work.  */
   htab_t loop2cloog_loop;
 
-  /* CLooG representation of this SCOP.  */
+  /* Cloog representation of this scop.  */
   CloogProgram *program;
+
+  /* Are we allowed to add more params?  This is for debugging purpose.  We
+     can only add new params before generating the bb domains, otherwise they
+     become invalid.  */
+  bool add_params;
 };
 
 #define SCOP_BBS(S) S->bbs
@@ -322,6 +330,7 @@ struct scop
 #define SCOP_STATIC_SCHEDULE(S) S->static_schedule
 #define SCOP_LOOPS(S) S->loops
 #define SCOP_LOOP_NEST(S) S->loop_nest
+#define SCOP_ADD_PARAMS(S) S->add_params
 #define SCOP_PARAMS(S) S->params
 #define SCOP_OLDIVS(S) S->old_ivs
 #define SCOP_PROG(S) S->program
@@ -335,8 +344,7 @@ extern void debug_gbb (graphite_bb_p, int);
 extern void dot_scop (scop_p);
 extern void dot_all_scops (void);
 extern void debug_clast_stmt (struct clast_stmt *);
-
-
+extern void debug_rename_map (htab_t);
 extern void debug_loop_vec (graphite_bb_p gb);
 extern void debug_oldivs (scop_p);
 
@@ -369,7 +377,6 @@ DEF_VEC_ALLOC_P(iv_stack_entry_p,heap);
 typedef VEC(iv_stack_entry_p, heap) **loop_iv_stack;
 extern void debug_loop_iv_stack (loop_iv_stack);
 
-
 /* Return the number of gimple loops contained in SCOP.  */
 
 static inline int
@@ -422,15 +429,6 @@ loop_domain_dim (unsigned int loop_num, scop_p scop)
   return cloog_domain_dim (cloog_loop_domain (slot->cloog_loop)) + 2;
 }
 
-/* Returns the dimensionality of an enclosing loop iteration domain
-   with respect to enclosing SCoP for a given data reference REF.  */
-
-static inline int
-ref_nb_loops (data_reference_p ref)
-{
-  return loop_domain_dim (loop_containing_stmt (DR_STMT (ref))->num, DR_SCOP (ref));
-}
-
 /* Returns the dimensionality of a loop iteration vector in a loop
    iteration domain for a given loop (identified by LOOP_NUM) with
    respect to SCOP.  */
@@ -521,22 +519,59 @@ scop_gimple_loop_depth (scop_p scop, loop_p loop)
   return depth;
 }
 
-/* Associate a POLYHEDRON dependence description to two data
-   references A and B.  */
-struct data_dependence_polyhedron
+/* Static inline function prototypes.  */
+
+static inline unsigned scop_nb_params (scop_p scop);
+
+/* Returns true when BB is in SCOP.  */
+
+static inline bool
+bb_in_scop_p (basic_block bb, scop_p scop)
 {
-  struct data_reference *a;
-  struct data_reference *b;
-  bool reversed_p;
-  bool loop_carried; /*TODO:konrad get rid of this, make level signed */
-  signed level;
-  CloogDomain *polyhedron;  
-};
+  return bitmap_bit_p (SCOP_BBS_B (scop), bb->index);
+}
 
-#define RDGE_DDP(E)   ((struct data_dependence_polyhedron*) ((E)->data))
+/* Returns true when LOOP is in SCOP.  */
 
-typedef struct data_dependence_polyhedron *ddp_p;
+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));
+}
+
+/* Calculate the number of loops around LOOP in the SCOP.  */
+
+static inline int
+nb_loops_around_loop_in_scop (struct loop *l, scop_p scop)
+{
+  int d = 0;
+
+  for (; loop_in_scop_p (l, scop); d++, l = loop_outer (l));
+
+  return d;
+}
+
+/* Calculate the number of loops around GB in the current SCOP.  */
+
+static inline int
+nb_loops_around_gb (graphite_bb_p gb)
+{
+  return nb_loops_around_loop_in_scop (gbb_loop (gb), GBB_SCOP (gb));
+}
+
+/* Returns the dimensionality of an enclosing loop iteration domain
+   with respect to enclosing SCoP for a given data reference REF.  The
+   returned dimensionality is homogeneous (depth of loop nest + number
+   of SCoP parameters + const).  */
 
-DEF_VEC_P(ddp_p);
-DEF_VEC_ALLOC_P(ddp_p,heap);
+static inline int
+ref_nb_loops (data_reference_p ref)
+{
+  loop_p loop = loop_containing_stmt (DR_STMT (ref));
+  scop_p scop = DR_SCOP (ref);
+
+  return nb_loops_around_loop_in_scop (loop, scop) + scop_nb_params (scop) + 2;
+}
 
+#endif  /* GCC_GRAPHITE_H  */
index 20881212bd5192262f8463c40617161b0c6bf203..207da42eda583cb42cf5820c2a0e6d2b65f6a09c 100644 (file)
@@ -1,3 +1,30 @@
+2008-12-11  Sebastian Pop  <sebastian.pop@amd.com>
+
+       PR middle-end/37852
+       PR middle-end/37883
+       PR middle-end/37928
+       PR middle-end/37980
+       PR middle-end/38038
+       PR middle-end/38039
+       PR middle-end/38073
+       PR middle-end/38083
+       PR middle-end/38125
+       * gcc.dg/graphite/pr37928.c: New.
+       * gcc.dg/graphite/pr37883.c: New.
+       * gcc.dg/graphite/pr38073.c: New.
+       * gcc.dg/graphite/pr38125.c: New.
+       * gfortran.dg/graphite/pr38083.f90: New.
+       * gfortran.dg/graphite/pr37852.f90: New.
+       * gfortran.dg/graphite/pr37980.f90: New.
+       * gfortran.dg/graphite/id-2.f90: New.
+       * gfortran.dg/graphite/id-4.f90: New.
+
+       * gcc.dg/graphite/scop-18.c: Remove reduction, test for
+       the number of detected scops.  Copy exact same test for loop blocking...
+       * gcc.dg/graphite/block-1.c: Fix the number of expected loops
+       to be blocked as reductions are not handled.
+       * gcc.dg/graphite/block-4.c: ...here.  New.
+
 2008-12-11  Ira Rosen  <irar@il.ibm.com>
 
        PR tree-optimization/38464
        PR c++/38410
        * gcc.dg/ctor1.c: New test.
 
+2008-12-09 Tobias Grosser  <grosser@fim.uni-passau.de>
+
+       PR middle-end/38084
+       * gfortran.dg/graphite/id-3.f90: New.
+       * gcc.dg/graphite/pr38084.c: New.
+
 2008-12-08  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.target/mips/fix-r10000-6.c: Add dg-message to look for
index 039b974fdae355285a29ea9b6e229bdbcf181d33..857f8d54e8e36b33a6a6f02d40f7f2707b651700 100644 (file)
@@ -2,6 +2,8 @@
 
 #define MAX 8192
 
+void bar (void);
+
 int main()
 {
   int i, j;
@@ -9,6 +11,8 @@ int main()
   int A[MAX * MAX];
   int B[MAX * MAX];
 
+  bar ();
+
   for (i = 0; i < MAX; i++)
     for (j = 0; j < MAX; j++)
       {
@@ -20,6 +24,11 @@ int main()
     for (j = 0; j < MAX; j++)
       A[i*MAX + j] += B[j*MAX + i];
 
+  bar ();
+
+  /* FIXME: For now, reductions are not handled by the code generation
+     of graphite.  We have to bound the scop to the above loops.  */
+
   for(i = 0; i < MAX; i++)
     for(j = 0; j < MAX; j++)
       sum += A[i*MAX + j];
@@ -27,5 +36,5 @@ int main()
   return sum;
 }
 
-/* { dg-final { scan-tree-dump-times "Loop blocked" 3 "graphite"} } */ 
+/* { dg-final { scan-tree-dump-times "Loop blocked" 2 "graphite"} } */ 
 /* { dg-final { cleanup-tree-dump "graphite" } } */
diff --git a/gcc/testsuite/gcc.dg/graphite/block-4.c b/gcc/testsuite/gcc.dg/graphite/block-4.c
new file mode 100644 (file)
index 0000000..4b550b4
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */
+
+#define N 24
+#define M 1000
+
+float A[1000][1000], B[1000][1000], C[1000][1000];
+
+void test (void)
+{
+  int i, j, k;
+
+  /* These loops contain too few iterations for being strip-mined by 64.  */
+  for (i = 0; i < 24; i++)
+    for (j = 0; j < 24; j++)
+      for (k = 0; k < 24; k++)
+        A[i][j] = B[i][k] * C[k][j];
+
+  /* These loops should still be strip mined.  */
+  for (i = 0; i < 1000; i++)
+    for (j = 0; j < 1000; j++)
+      for (k = 0; k < 1000; k++)
+        A[i][j] = B[i][k] * C[k][j];
+}
+
+/* { dg-final { scan-tree-dump-times "Strip Mining is not profitable" 2 "graphite" } } */
+/* { dg-final { cleanup-tree-dump "graphite" } } */
diff --git a/gcc/testsuite/gcc.dg/graphite/pr37883.c b/gcc/testsuite/gcc.dg/graphite/pr37883.c
new file mode 100644 (file)
index 0000000..2ab043a
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-options "-O3 -floop-block" } */
+
+void test_sort()
+{
+  char *base;
+  register char c, *i, *hi;
+
+  for (i = base; i < hi; i++)
+    *i++ = c;
+}
+
diff --git a/gcc/testsuite/gcc.dg/graphite/pr37928.c b/gcc/testsuite/gcc.dg/graphite/pr37928.c
new file mode 100644 (file)
index 0000000..47ad5bc
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-options "-O3 -floop-block" } */
+
+int get_state(int size, int *node, int *hash)
+{
+  int i=0;
+  while(hash[i])
+    {
+     if(node[hash[i]] == 0)
+           return hash[i]-1;
+      i++;
+     if(i==5)
+       i=0;
+    }
+  return -1;
+}
+
+void foo (int);
+
+int gate1(int size, int *node, int *hash)
+{
+  int i, j ;
+  int add_size=0;
+  for(i=0; i<size; i++)
+  {
+     j = get_state(size,node, hash);
+     if(j == -1)
+     {
+       add_size++;
+     }
+  }
+
+  foo (size+add_size);
+}
diff --git a/gcc/testsuite/gcc.dg/graphite/pr38073.c b/gcc/testsuite/gcc.dg/graphite/pr38073.c
new file mode 100644 (file)
index 0000000..9c48d8d
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-options "-O3 -fgraphite-identity" } */
+
+test_seg(int a, int b)
+{
+  int i,r=1;
+  for(i=0; i<b ;i++)
+    r*=a;
+  return r;
+}
diff --git a/gcc/testsuite/gcc.dg/graphite/pr38125.c b/gcc/testsuite/gcc.dg/graphite/pr38125.c
new file mode 100644 (file)
index 0000000..780e6f6
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-options "-O3 -fgraphite-identity" } */
+
+typedef struct sv TEST_SV;
+typedef struct av TEST_AV;
+typedef struct magic TEST_MAGIC;
+typedef struct xpvav TEST_XPVAV;
+struct sv 
+{
+    void* sv_any;
+};
+struct av 
+{
+    TEST_XPVAV* sv_any;
+};
+struct xpvav 
+{
+    char* xav_array;
+    long int xav_fill;
+    long int xav_max;
+};
+struct magic {
+    TEST_SV* mg_obj;
+};
+extern TEST_SV PL_sv_undef;
+Perl_av_fill( register TEST_AV *av, int fill)
+{
+    TEST_MAGIC *mg;
+    int key = ((TEST_XPVAV*) (av)->sv_any)->xav_fill;
+    TEST_SV** ary = ((TEST_SV**)((TEST_XPVAV*) (av)->sv_any)->xav_array);
+    while (key < fill)
+          ary[++key] = &PL_sv_undef;
+}
index fe2d5f4a4121ac4a3b0174d4fe3a03b77f7e08aa..6264116e114178f916a1480937a4f78843c3eb9f 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */
+/* { dg-options "-O2 -fgraphite -fdump-tree-graphite-all" } */
 
 #define N 24
 #define M 1000
@@ -13,14 +13,14 @@ void test (void)
   for (i = 0; i < 24; i++)
     for (j = 0; j < 24; j++)
       for (k = 0; k < 24; k++)
-        A[i][j] += B[i][k] * C[k][j];
+        A[i][j] = B[i][k] * C[k][j];
 
   /* These loops should still be strip mined.  */
   for (i = 0; i < 1000; i++)
     for (j = 0; j < 1000; j++)
       for (k = 0; k < 1000; k++)
-        A[i][j] += B[i][k] * C[k][j];
+        A[i][j] = B[i][k] * C[k][j];
 }
 
-/* { dg-final { scan-tree-dump-times "Strip Mining is not profitable" 3 "graphite" } } */
+/* { dg-final { scan-tree-dump-times "number of SCoPs: 2" 1 "graphite"} } */ 
 /* { dg-final { cleanup-tree-dump "graphite" } } */
diff --git a/gcc/testsuite/gfortran.dg/graphite/id-2.f90 b/gcc/testsuite/gfortran.dg/graphite/id-2.f90
new file mode 100644 (file)
index 0000000..0c9f54b
--- /dev/null
@@ -0,0 +1,15 @@
+! { dg-options "-O2 -fgraphite-identity" }
+
+module solv_cap
+  integer, parameter, public :: dp = selected_real_kind(5)
+contains
+  subroutine prod0( G, X )
+    real(kind=dp), intent(in out), dimension(:,:)    :: X
+    real(kind=dp), dimension(size(X,1),size(X,2)) :: Y
+    X = Y
+  end subroutine prod0
+  function Ginteg(xq1,yq1, xq2,yq2, xp,yp)  result(G)
+  end function Ginteg
+  subroutine fourir(A,ntot,kconjg, E,useold)
+  end subroutine fourir
+end module solv_cap
diff --git a/gcc/testsuite/gfortran.dg/graphite/id-4.f90 b/gcc/testsuite/gfortran.dg/graphite/id-4.f90
new file mode 100644 (file)
index 0000000..896d608
--- /dev/null
@@ -0,0 +1,34 @@
+! { dg-options "-O2 -fgraphite-identity" }
+
+MODULE Vcimage
+  CHARACTER (LEN=80), SAVE :: CARD, FIELD
+END MODULE Vcimage
+MODULE Vimage
+  LOGICAL, SAVE ::  EOFF
+END MODULE Vimage
+SUBROUTINE READIN(PROB, TITLE, CSTOP, FCYCLE, DCYCLE, DHIST, VHIST&
+     &    , IMAX, PHIST, DEBUG, NSTAT, STATS, MAXSTA, NCORE, PPLOT,     &
+     &    DPLOT, VPLOT, TPLOT, SLIST, D0, E0, NODES, SHEAT, GAMMA, COLD &
+     &    , THIST, NVISC, SCREEN, WEIGHT, TSTOP, STABF)
+  USE Vcimage
+  USE Vimage
+  INTEGER, DIMENSION(MAXSTA) :: STATS
+  IF (.NOT.EOFF) THEN
+     IF (FIELD=='PROB' .OR. FIELD=='PROBLEM_NUMBER') THEN
+        CALL QSORT (STATS(1:NSTAT))
+        WRITE (16,                                                 &
+             &'(//'' YOU HAVE REQUESTED A PRINTOUT OF THE STATION'',            &
+             &    '' ABORT''//)')
+     ENDIF
+  ENDIF
+CONTAINS
+  RECURSIVE SUBROUTINE QSORT (LIST)
+    INTEGER, DIMENSION(:), INTENT(INOUT) :: LIST
+    INTEGER, DIMENSION(SIZE(LIST)) :: SMALLER,LARGER
+    IF (SIZE(LIST) > 1) THEN
+       LIST(NUMBER_SMALLER+1:NUMBER_SMALLER+NUMBER_EQUAL) = CHOSEN
+       CALL QSORT (LARGER(1:NUMBER_LARGER))
+       LIST(NUMBER_SMALLER+NUMBER_EQUAL+1:) = LARGER(1:NUMBER_LARGER)
+    END IF
+  END SUBROUTINE QSORT
+END SUBROUTINE READIN
diff --git a/gcc/testsuite/gfortran.dg/graphite/pr37852.f90 b/gcc/testsuite/gfortran.dg/graphite/pr37852.f90
new file mode 100644 (file)
index 0000000..50e2342
--- /dev/null
@@ -0,0 +1,13 @@
+! { dg-options "-O2 -floop-block" }
+
+PROGRAM TEST_FPU
+CHARACTER (LEN=36) :: invert_id(1) = &
+                      (/ 'Test1 - Gauss 2000 (101x101) inverts'/)
+END PROGRAM TEST_FPU
+
+SUBROUTINE Gauss (a,n)
+INTEGER, PARAMETER :: RK8 = SELECTED_REAL_KIND(15, 300)
+REAL(RK8) :: a(n,n)
+INTEGER ::  ipvt(n)
+a(:,ipvt) = b
+END SUBROUTINE Gauss
diff --git a/gcc/testsuite/gfortran.dg/graphite/pr37980.f90 b/gcc/testsuite/gfortran.dg/graphite/pr37980.f90
new file mode 100644 (file)
index 0000000..5306aa8
--- /dev/null
@@ -0,0 +1,11 @@
+! { dg-options "-O2 -floop-block" }
+
+module INT_MODULE
+contains
+  pure function spher_cartesians(in1) result(out1)
+    integer(kind=kind(1)) :: in1 
+    intent(in) :: in1 
+    real(kind=kind(1.0d0)), dimension(0:in1,0:in1,0:in1) :: mat0
+    mat0 = 0.0d0
+  end function spher_cartesians
+end module INT_MODULE
diff --git a/gcc/testsuite/gfortran.dg/graphite/pr38083.f90 b/gcc/testsuite/gfortran.dg/graphite/pr38083.f90
new file mode 100644 (file)
index 0000000..834d33a
--- /dev/null
@@ -0,0 +1,16 @@
+! { dg-options "-O3 -floop-block" }
+
+SUBROUTINE IVSORT (IL,IH,NSEGS,IOUNIT)
+  INTEGER IOUNIT  
+
+  INTEGER, PARAMETER :: MAXGS = 32
+
+10 IF (IL .GE. IH) GO TO 80
+20 NSEGS = (IH + IL) / 2
+  IF (NSEGS .GT. MAXSGS) THEN
+     WRITE (IOUNIT),MAXSGS
+  ENDIF
+80 NSEGS = NSEGS - 1
+90 IF (IH - IL .GE. 11) GO TO 20
+110 IF (IL .EQ. IH) GO TO 80
+END SUBROUTINE IVSORT
index 28ee8ef40c4ff5a37fc94df621f2ff54b3c7d99e..89621f0a80ac849d2839077cca62860dd6c5be1e 100644 (file)
@@ -2072,14 +2072,9 @@ struct gimple_opt_pass pass_remove_useless_stmts =
 static void
 remove_phi_nodes_and_edges_for_unreachable_block (basic_block bb)
 {
-  gimple_stmt_iterator gsi;
-
   /* Since this block is no longer reachable, we can just delete all
      of its PHI nodes.  */
-  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
-    remove_phi_node (&gsi, true);
-
-  set_phi_nodes (bb, NULL);
+  remove_phi_nodes (bb);
 
   /* Remove edges to BB's successors.  */
   while (EDGE_COUNT (bb->succs) > 0)
index 6004978416b6c9e2e2316f694a7a74c322b850b2..d4e0004d834df4dcd8bae752ed9d7fcabf953106 100644 (file)
@@ -787,6 +787,7 @@ extern gimple create_phi_node (tree, basic_block);
 extern void add_phi_arg (gimple, tree, edge);
 extern void remove_phi_args (edge);
 extern void remove_phi_node (gimple_stmt_iterator *, bool);
+extern void remove_phi_nodes (basic_block);
 extern void init_phinodes (void);
 extern void fini_phinodes (void);
 extern void release_phi_node (gimple);
@@ -988,6 +989,7 @@ unsigned int tree_ssa_prefetch_arrays (void);
 unsigned int remove_empty_loops (void);
 void tree_ssa_iv_optimize (void);
 unsigned tree_predictive_commoning (void);
+tree canonicalize_loop_ivs (struct loop *, htab_t, tree);
 bool parallelize_loops (void);
 
 bool loop_only_exit_p (const struct loop *, const_edge);
index d6e94b3c6a5e768fd922f3dd8d4795d1eecc1e0d..91ce890755fd619970e57cdbffbae07b85d715ec 100644 (file)
@@ -1325,9 +1325,10 @@ create_loop_fn (void)
 /* Bases all the induction variables in LOOP on a single induction variable
    (unsigned with base 0 and step 1), whose final value is compared with
    NIT.  The induction variable is incremented in the loop latch.  
-   REDUCTION_LIST describes the reductions in LOOP.  */
+   REDUCTION_LIST describes the reductions in LOOP.  Return the induction 
+   variable that was created.  */
 
-static void
+tree
 canonicalize_loop_ivs (struct loop *loop, htab_t reduction_list, tree nit)
 {
   unsigned precision = TYPE_PRECISION (TREE_TYPE (nit));
@@ -1368,7 +1369,12 @@ canonicalize_loop_ivs (struct loop *loop, htab_t reduction_list, tree nit)
        }
 
       ok = simple_iv (loop, phi, res, &iv, true);
-      red = reduction_phi (reduction_list, phi);
+
+      if (reduction_list)
+       red = reduction_phi (reduction_list, phi);
+      else
+       red = NULL;
+
       /* We preserve the reduction phi nodes.  */
       if (!ok && red)
        {
@@ -1406,6 +1412,9 @@ canonicalize_loop_ivs (struct loop *loop, htab_t reduction_list, tree nit)
   gimple_cond_set_code (stmt, LT_EXPR);
   gimple_cond_set_lhs (stmt, var_before);
   gimple_cond_set_rhs (stmt, nit);
+  update_stmt (stmt);
+
+  return var_before;
 }
 
 /* Moves the exit condition of LOOP to the beginning of its header, and
index 7fd5a8f30cc4092b992ef3fae5ac17c08ed403be..fd6ac3a511bcb48b6091efdd98080a4a4a4effd1 100644 (file)
@@ -474,4 +474,17 @@ remove_phi_node (gimple_stmt_iterator *gsi, bool release_lhs_p)
     release_ssa_name (gimple_phi_result (phi));
 }
 
+/* Remove all the phi nodes from BB.  */
+
+void
+remove_phi_nodes (basic_block bb)
+{
+  gimple_stmt_iterator gsi;
+
+  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
+    remove_phi_node (&gsi, true);
+
+  set_phi_nodes (bb, NULL);
+}
+
 #include "gt-tree-phinodes.h"