config.gcc (visium-*-*): Enable --with-cpu option, accept gr5 and gr6 as possible...
[platform/upstream/gcc.git] / gcc / graphite-scop-detection.c
index 0a3680b..3ac56de 100644 (file)
@@ -1,5 +1,5 @@
 /* Detection of Static Control Parts (SCoP) for Graphite.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2009-2015 Free Software Foundation, Inc.
    Contributed by Sebastian Pop <sebastian.pop@amd.com> and
    Tobias Grosser <grosser@fim.uni-passau.de>.
 
@@ -20,28 +20,45 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
+
+#ifdef HAVE_isl
+/* Workaround for GMP 5.1.3 bug, see PR56019.  */
+#include <stddef.h>
+
+#include <isl/constraint.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/union_map.h>
+
 #include "system.h"
 #include "coretypes.h"
-#include "tree-flow.h"
+#include "backend.h"
+#include "cfghooks.h"
+#include "tree.h"
+#include "gimple.h"
+#include "ssa.h"
+#include "fold-const.h"
+#include "gimple-iterator.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
+#include "tree-ssa.h"
 #include "cfgloop.h"
-#include "tree-chrec.h"
 #include "tree-data-ref.h"
 #include "tree-scalar-evolution.h"
 #include "tree-pass.h"
-#include "sese.h"
-
-#ifdef HAVE_cloog
-#include "ppl_c.h"
-#include "graphite-ppl.h"
 #include "graphite-poly.h"
+#include "tree-ssa-propagate.h"
 #include "graphite-scop-detection.h"
+#include "gimple-pretty-print.h"
 
 /* Forward declarations.  */
 static void make_close_phi_nodes_unique (basic_block);
 
 /* The type of the analyzed basic block.  */
 
-typedef enum gbb_type {
+enum gbb_type {
   GBB_UNKNOWN,
   GBB_LOOP_SING_EXIT_HEADER,
   GBB_LOOP_MULT_EXIT_HEADER,
@@ -49,7 +66,7 @@ typedef enum gbb_type {
   GBB_COND_HEADER,
   GBB_SIMPLE,
   GBB_LAST
-} gbb_type;
+};
 
 /* Detect the type of BB.  Loop headers are only marked, if they are
    new.  This means their loop_father is different to LAST_LOOP.
@@ -59,8 +76,8 @@ typedef enum gbb_type {
 static gbb_type
 get_bb_type (basic_block bb, struct loop *last_loop)
 {
-  VEC (basic_block, heap) *dom;
-  int nb_dom, nb_suc;
+  vec<basic_block> dom;
+  int nb_dom;
   struct loop *loop = bb->loop_father;
 
   /* Check, if we entry into a new loop. */
@@ -75,15 +92,13 @@ get_bb_type (basic_block bb, struct loop *last_loop)
     }
 
   dom = get_dominated_by (CDI_DOMINATORS, bb);
-  nb_dom = VEC_length (basic_block, dom);
-  VEC_free (basic_block, heap, dom);
+  nb_dom = dom.length ();
+  dom.release ();
 
   if (nb_dom == 0)
     return GBB_LAST;
 
-  nb_suc = VEC_length (edge, bb->succs);
-
-  if (nb_dom == 1 && nb_suc == 1)
+  if (nb_dom == 1 && single_succ_p (bb))
     return GBB_SIMPLE;
 
   return GBB_COND_HEADER;
@@ -113,7 +128,7 @@ get_bb_type (basic_block bb, struct loop *last_loop)
      9 <- exit  */
 
 
-typedef struct sd_region_p
+struct sd_region
 {
   /* The entry bb dominates all bbs in the sd_region.  It is part of
      the region.  */
@@ -122,25 +137,22 @@ typedef struct sd_region_p
   /* The exit bb postdominates all bbs in the sd_region, but is not
      part of the region.  */
   basic_block exit;
-} sd_region;
+};
 
-DEF_VEC_O(sd_region);
-DEF_VEC_ALLOC_O(sd_region, heap);
 
 
 /* Moves the scops from SOURCE to TARGET and clean up SOURCE.  */
 
 static void
-move_sd_regions (VEC (sd_region, heap) **source,
-                VEC (sd_region, heap) **target)
+move_sd_regions (vec<sd_region> *source, vec<sd_region> *target)
 {
   sd_region *s;
   int i;
 
-  FOR_EACH_VEC_ELT (sd_region, *source, i, s)
-    VEC_safe_push (sd_region, heap, *target, s);
+  FOR_EACH_VEC_ELT (*source, i, s)
+    target->safe_push (*s);
 
-  VEC_free (sd_region, heap, *source);
+  source->release ();
 }
 
 /* Something like "n * m" is not allowed.  */
@@ -157,10 +169,10 @@ graphite_can_represent_init (tree e)
     case MULT_EXPR:
       if (chrec_contains_symbols (TREE_OPERAND (e, 0)))
        return graphite_can_represent_init (TREE_OPERAND (e, 0))
-         && host_integerp (TREE_OPERAND (e, 1), 0);
+         && tree_fits_shwi_p (TREE_OPERAND (e, 1));
       else
        return graphite_can_represent_init (TREE_OPERAND (e, 1))
-         && host_integerp (TREE_OPERAND (e, 0), 0);
+         && tree_fits_shwi_p (TREE_OPERAND (e, 0));
 
     case PLUS_EXPR:
     case POINTER_PLUS_EXPR:
@@ -199,9 +211,24 @@ graphite_can_represent_scev (tree scev)
   if (chrec_contains_undetermined (scev))
     return false;
 
+  /* We disable the handling of pointer types, because it’s currently not
+     supported by Graphite with the ISL AST generator. SSA_NAME nodes are
+     the only nodes, which are disabled in case they are pointers to object
+     types, but this can be changed.  */
+
+  if (POINTER_TYPE_P (TREE_TYPE (scev)) && TREE_CODE (scev) == SSA_NAME)
+    return false;
+
   switch (TREE_CODE (scev))
     {
+    case NEGATE_EXPR:
+    case BIT_NOT_EXPR:
+    CASE_CONVERT:
+    case NON_LVALUE_EXPR:
+      return graphite_can_represent_scev (TREE_OPERAND (scev, 0));
+
     case PLUS_EXPR:
+    case POINTER_PLUS_EXPR:
     case MINUS_EXPR:
       return graphite_can_represent_scev (TREE_OPERAND (scev, 0))
        && graphite_can_represent_scev (TREE_OPERAND (scev, 1));
@@ -223,13 +250,15 @@ graphite_can_represent_scev (tree scev)
       if (!evolution_function_right_is_integer_cst (scev)
          || !graphite_can_represent_init (scev))
        return false;
+      return graphite_can_represent_scev (CHREC_LEFT (scev));
 
     default:
       break;
     }
 
   /* Only affine functions can be represented.  */
-  if (!scev_is_linear_expression (scev))
+  if (tree_contains_chrecs (scev, NULL)
+      || !scev_is_linear_expression (scev))
     return false;
 
   return true;
@@ -262,10 +291,9 @@ stmt_has_simple_data_refs_p (loop_p outermost_loop ATTRIBUTE_UNUSED,
                             gimple stmt)
 {
   data_reference_p dr;
-  unsigned i;
   int j;
   bool res = true;
-  VEC (data_reference_p, heap) *drs = NULL;
+  vec<data_reference_p> drs = vNULL;
   loop_p outer;
 
   for (outer = loop_containing_stmt (stmt); outer; outer = loop_outer (outer))
@@ -274,19 +302,30 @@ stmt_has_simple_data_refs_p (loop_p outermost_loop ATTRIBUTE_UNUSED,
                                             loop_containing_stmt (stmt),
                                             stmt, &drs);
 
-      FOR_EACH_VEC_ELT (data_reference_p, drs, j, dr)
-       for (i = 0; i < DR_NUM_DIMENSIONS (dr); i++)
-         if (!graphite_can_represent_scev (DR_ACCESS_FN (dr, i)))
+      FOR_EACH_VEC_ELT (drs, j, dr)
+       {
+         int nb_subscripts = DR_NUM_DIMENSIONS (dr);
+         tree ref = DR_REF (dr);
+
+         for (int i = nb_subscripts - 1; i >= 0; i--)
            {
-             res = false;
-             goto done;
+             if (!graphite_can_represent_scev (DR_ACCESS_FN (dr, i))
+                 || (TREE_CODE (ref) != ARRAY_REF
+                     && TREE_CODE (ref) != MEM_REF
+                     && TREE_CODE (ref) != COMPONENT_REF))
+               {
+                 free_data_refs (drs);
+                 return false;
+               }
+
+             ref = TREE_OPERAND (ref, 0);
            }
+       }
 
       free_data_refs (drs);
-      drs = NULL;
+      drs.create (0);
     }
 
- done:
   free_data_refs (drs);
   return res;
 }
@@ -312,42 +351,77 @@ stmt_simple_for_scop_p (basic_block scop_entry, loop_p outermost_loop,
       || (gimple_code (stmt) == GIMPLE_CALL
          && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE)))
       || (gimple_code (stmt) == GIMPLE_ASM))
-    return false;
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "[scop-detection-fail] ");
+         fprintf (dump_file, "Graphite cannot handle this stmt:\n");
+         print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
+       }
+
+      return false;
+    }
 
   if (is_gimple_debug (stmt))
     return true;
 
   if (!stmt_has_simple_data_refs_p (outermost_loop, stmt))
-    return false;
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "[scop-detection-fail] ");
+         fprintf (dump_file, "Graphite cannot handle data-refs in stmt:\n");
+         print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
+       }
+
+      return false;
+    }
 
   switch (gimple_code (stmt))
     {
-    case GIMPLE_RETURN:
     case GIMPLE_LABEL:
       return true;
 
     case GIMPLE_COND:
       {
-       tree op;
-       ssa_op_iter op_iter;
-        enum tree_code code = gimple_cond_code (stmt);
-
        /* We can handle all binary comparisons.  Inequalities are
           also supported as they can be represented with union of
           polyhedra.  */
+        enum tree_code code = gimple_cond_code (stmt);
         if (!(code == LT_EXPR
              || code == GT_EXPR
              || code == LE_EXPR
              || code == GE_EXPR
              || code == EQ_EXPR
              || code == NE_EXPR))
-          return false;
+          {
+           if (dump_file && (dump_flags & TDF_DETAILS))
+             {
+               fprintf (dump_file, "[scop-detection-fail] ");
+               fprintf (dump_file, "Graphite cannot handle cond stmt:\n");
+               print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
+             }
 
-       FOR_EACH_SSA_TREE_OPERAND (op, stmt, op_iter, SSA_OP_ALL_USES)
-         if (!graphite_can_represent_expr (scop_entry, loop, op)
-             /* We can not handle REAL_TYPE. Failed for pr39260.  */
-             || TREE_CODE (TREE_TYPE (op)) == REAL_TYPE)
            return false;
+         }
+
+       for (unsigned i = 0; i < 2; ++i)
+         {
+           tree op = gimple_op (stmt, i);
+           if (!graphite_can_represent_expr (scop_entry, loop, op)
+               /* We can only constrain on integer type.  */
+               || (TREE_CODE (TREE_TYPE (op)) != INTEGER_TYPE))
+             {
+               if (dump_file && (dump_flags & TDF_DETAILS))
+                 {
+                   fprintf (dump_file, "[scop-detection-fail] ");
+                   fprintf (dump_file, "Graphite cannot represent stmt:\n");
+                   print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
+                 }
+
+               return false;
+             }
+         }
 
        return true;
       }
@@ -358,6 +432,12 @@ stmt_simple_for_scop_p (basic_block scop_entry, loop_p outermost_loop,
 
     default:
       /* These nodes cut a new scope.  */
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "[scop-detection-fail] ");
+         fprintf (dump_file, "Gimple stmt not handled in Graphite:\n");
+         print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
+       }
       return false;
     }
 
@@ -392,6 +472,17 @@ graphite_can_represent_loop (basic_block scop_entry, loop_p loop)
   tree niter;
   struct tree_niter_desc niter_desc;
 
+  if (!loop_nest_has_data_refs (loop))
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "[scop-detection-fail] ");
+         fprintf (dump_file, "Loop %d does not have any data reference.\n",
+                  loop->num);
+       }
+      return false;
+    }
+
   /* FIXME: For the moment, graphite cannot be used on loops that
      iterate using induction variables that wrap.  */
 
@@ -421,21 +512,21 @@ struct scopdet_info
 };
 
 static struct scopdet_info build_scops_1 (basic_block, loop_p,
-                                         VEC (sd_region, heap) **, loop_p);
+                                         vec<sd_region> *, loop_p);
 
 /* Calculates BB infos. If bb is difficult we add valid SCoPs dominated by BB
    to SCOPS.  TYPE is the gbb_type of BB.  */
 
 static struct scopdet_info
 scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
-                         VEC (sd_region, heap) **scops, gbb_type type)
+                         vec<sd_region> *scops, gbb_type type)
 {
   loop_p loop = bb->loop_father;
   struct scopdet_info result;
   gimple stmt;
 
   /* XXX: ENTRY_BLOCK_PTR could be optimized in later steps.  */
-  basic_block entry_block = ENTRY_BLOCK_PTR;
+  basic_block entry_block = ENTRY_BLOCK_PTR_FOR_FN (cfun);
   stmt = harmful_stmt_in_bb (entry_block, outermost_loop, bb);
   result.difficult = (stmt != NULL);
   result.exit = NULL;
@@ -447,9 +538,20 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
       result.exits = false;
 
       /* Mark bbs terminating a SESE region difficult, if they start
-        a condition.  */
-      if (!single_succ_p (bb))
-       result.difficult = true;
+        a condition or if the block it exits to cannot be split
+        with make_forwarder_block.  */
+      if (!single_succ_p (bb)
+         || bb_has_abnormal_pred (single_succ (bb)))
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "[scop-detection-fail] ");
+             fprintf (dump_file, "BB %d cannot be part of a scop.\n",
+                      bb->index);
+           }
+
+         result.difficult = true;
+       }
       else
        result.exit = single_succ (bb);
 
@@ -463,14 +565,22 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
 
     case GBB_LOOP_SING_EXIT_HEADER:
       {
-       VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
+       auto_vec<sd_region, 3> regions;
        struct scopdet_info sinfo;
        edge exit_e = single_exit (loop);
 
        sinfo = build_scops_1 (bb, outermost_loop, &regions, loop);
 
        if (!graphite_can_represent_loop (entry_block, loop))
-         result.difficult = true;
+         {
+           if (dump_file && (dump_flags & TDF_DETAILS))
+             {
+               fprintf (dump_file, "[scop-detection-fail] ");
+               fprintf (dump_file, "Graphite cannot represent loop %d.\n",
+                        loop->num);
+             }
+           result.difficult = true;
+         }
 
        result.difficult |= sinfo.difficult;
 
@@ -480,8 +590,8 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
          {
            outermost_loop = loop;
 
-           VEC_free (sd_region, heap, regions);
-           regions = VEC_alloc (sd_region, heap, 3);
+           regions.release ();
+           regions.create (3);
 
            sinfo = scopdet_basic_block_info (bb, outermost_loop, scops, type);
 
@@ -495,8 +605,8 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
                sd_region open_scop;
                open_scop.entry = bb;
                open_scop.exit = exit_e->dest;
-               VEC_safe_push (sd_region, heap, *scops, &open_scop);
-               VEC_free (sd_region, heap, regions);
+               scops->safe_push (open_scop);
+               regions.release ();
              }
          }
        else
@@ -505,7 +615,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
            result.next = exit_e->dest;
 
            /* If we do not dominate result.next, remove it.  It's either
-              the EXIT_BLOCK_PTR, or another bb dominates it and will
+              the exit block, or another bb dominates it and will
               call the scop detection for this bb.  */
            if (!dominated_by_p (CDI_DOMINATORS, result.next, bb))
              result.next = NULL;
@@ -518,7 +628,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
            if (result.difficult)
              move_sd_regions (&regions, scops);
            else
-             VEC_free (sd_region, heap, regions);
+             regions.release ();
          }
 
        break;
@@ -528,8 +638,8 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
       {
         /* XXX: For now we just do not join loops with multiple exits.  If the
            exits lead to the same bb it may be possible to join the loop.  */
-        VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
-        VEC (edge, heap) *exits = get_loop_exit_edges (loop);
+        auto_vec<sd_region, 3> regions;
+        vec<edge> exits = get_loop_exit_edges (loop);
         edge e;
         int i;
        build_scops_1 (bb, loop, &regions, loop);
@@ -544,7 +654,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
                  - The exit destinations are dominated by another bb inside
                    the loop.
                  - The loop dominates bbs, that are not exit destinations.  */
-        FOR_EACH_VEC_ELT (edge, exits, i, e)
+        FOR_EACH_VEC_ELT (exits, i, e)
           if (e->src->loop_father == loop
              && dominated_by_p (CDI_DOMINATORS, e->dest, e->src))
            {
@@ -566,14 +676,14 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
         result.difficult = true;
         result.exits = false;
         move_sd_regions (&regions, scops);
-        VEC_free (edge, heap, exits);
+        exits.release ();
         break;
       }
     case GBB_COND_HEADER:
       {
-       VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
+       auto_vec<sd_region, 3> regions;
        struct scopdet_info sinfo;
-       VEC (basic_block, heap) *dominated;
+       vec<basic_block> dominated;
        int i;
        basic_block dom_bb;
        basic_block last_exit = NULL;
@@ -582,7 +692,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
 
        /* First check the successors of BB, and check if it is
           possible to join the different branches.  */
-       FOR_EACH_VEC_ELT (edge, bb->succs, i, e)
+       FOR_EACH_VEC_SAFE_ELT (bb->succs, i, e)
          {
            /* Ignore loop exits.  They will be handled after the loop
               body.  */
@@ -661,14 +771,14 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
 
            result.exit = last_exit;
 
-           VEC_free (sd_region, heap, regions);
+           regions.release ();
            break;
          }
 
        /* Scan remaining bbs dominated by BB.  */
        dominated = get_dominated_by (CDI_DOMINATORS, bb);
 
-       FOR_EACH_VEC_ELT (basic_block, dominated, i, dom_bb)
+       FOR_EACH_VEC_ELT (dominated, i, dom_bb)
          {
            /* Ignore loop exits: they will be handled after the loop body.  */
            if (loop_depth (find_common_loop (loop, dom_bb->loop_father))
@@ -693,7 +803,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
            result.exit = NULL;
          }
 
-       VEC_free (basic_block, heap, dominated);
+       dominated.release ();
 
        result.next = NULL;
        move_sd_regions (&regions, scops);
@@ -718,7 +828,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
 
 static struct scopdet_info
 build_scops_1 (basic_block current, loop_p outermost_loop,
-              VEC (sd_region, heap) **scops, loop_p loop)
+              vec<sd_region> *scops, loop_p loop)
 {
   bool in_scop = false;
   sd_region open_scop;
@@ -751,7 +861,7 @@ build_scops_1 (basic_block current, loop_p outermost_loop,
       else if (in_scop && (sinfo.exits || sinfo.difficult))
         {
          open_scop.exit = current;
-          VEC_safe_push (sd_region, heap, *scops, &open_scop);
+          scops->safe_push (open_scop);
           in_scop = false;
         }
 
@@ -766,7 +876,14 @@ build_scops_1 (basic_block current, loop_p outermost_loop,
     {
       open_scop.exit = sinfo.exit;
       gcc_assert (open_scop.exit);
-      VEC_safe_push (sd_region, heap, *scops, &open_scop);
+      if (open_scop.entry != open_scop.exit)
+       scops->safe_push (open_scop);
+      else
+       {
+         sinfo.difficult = true;
+         sinfo.exits = false;
+         sinfo.exit = NULL;
+       }
     }
 
   result.exit = sinfo.exit;
@@ -971,14 +1088,14 @@ create_single_exit_edge (sd_region *region)
    See comment in "create_single_exit_edge". */
 
 static void
-unmark_exit_edges (VEC (sd_region, heap) *regions)
+unmark_exit_edges (vec<sd_region> regions)
 {
   int i;
   sd_region *s;
   edge e;
   edge_iterator ei;
 
-  FOR_EACH_VEC_ELT (sd_region, regions, i, s)
+  FOR_EACH_VEC_ELT (regions, i, s)
     FOR_EACH_EDGE (e, ei, s->exit->preds)
       e->aux = NULL;
 }
@@ -988,14 +1105,14 @@ unmark_exit_edges (VEC (sd_region, heap) *regions)
    See comment in "create_single_exit_edge". */
 
 static void
-mark_exit_edges (VEC (sd_region, heap) *regions)
+mark_exit_edges (vec<sd_region> regions)
 {
   int i;
   sd_region *s;
   edge e;
   edge_iterator ei;
 
-  FOR_EACH_VEC_ELT (sd_region, regions, i, s)
+  FOR_EACH_VEC_ELT (regions, i, s)
     FOR_EACH_EDGE (e, ei, s->exit->preds)
       if (bb_in_sd_region (e->src, s))
        e->aux = s;
@@ -1004,43 +1121,43 @@ mark_exit_edges (VEC (sd_region, heap) *regions)
 /* Create for all scop regions a single entry and a single exit edge.  */
 
 static void
-create_sese_edges (VEC (sd_region, heap) *regions)
+create_sese_edges (vec<sd_region> regions)
 {
   int i;
   sd_region *s;
 
-  FOR_EACH_VEC_ELT (sd_region, regions, i, s)
+  FOR_EACH_VEC_ELT (regions, i, s)
     create_single_entry_edge (s);
 
   mark_exit_edges (regions);
 
-  FOR_EACH_VEC_ELT (sd_region, regions, i, s)
+  FOR_EACH_VEC_ELT (regions, i, s)
     /* Don't handle multiple edges exiting the function.  */
     if (!find_single_exit_edge (s)
-       && s->exit != EXIT_BLOCK_PTR)
+       && s->exit != EXIT_BLOCK_PTR_FOR_FN (cfun))
       create_single_exit_edge (s);
 
   unmark_exit_edges (regions);
 
+  calculate_dominance_info (CDI_DOMINATORS);
   fix_loop_structure (NULL);
 
 #ifdef ENABLE_CHECKING
   verify_loop_structure ();
-  verify_dominators (CDI_DOMINATORS);
-  verify_ssa (false);
+  verify_ssa (false, true);
 #endif
 }
 
 /* Create graphite SCoPs from an array of scop detection REGIONS.  */
 
 static void
-build_graphite_scops (VEC (sd_region, heap) *regions,
-                     VEC (scop_p, heap) **scops)
+build_graphite_scops (vec<sd_region> regions,
+                     vec<scop_p> *scops)
 {
   int i;
   sd_region *s;
 
-  FOR_EACH_VEC_ELT (sd_region, regions, i, s)
+  FOR_EACH_VEC_ELT (regions, i, s)
     {
       edge entry = find_single_entry_edge (s);
       edge exit = find_single_exit_edge (s);
@@ -1049,8 +1166,17 @@ build_graphite_scops (VEC (sd_region, heap) *regions,
       if (!exit)
        continue;
 
-      scop = new_scop (new_sese (entry, exit));
-      VEC_safe_push (scop_p, heap, *scops, scop);
+      sese sese_reg = new_sese (entry, exit);
+      scop = new_scop (sese_reg);
+
+      build_sese_loop_nests (sese_reg);
+
+      /* Scops with one or no loops are not interesting.  */
+      if (SESE_LOOP_NEST (sese_reg).length () > 1)
+       scops->safe_push (scop);
+      else if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Discarded scop: %d loops\n",
+                SESE_LOOP_NEST (sese_reg).length ());
 
       /* Are there overlapping SCoPs?  */
 #ifdef ENABLE_CHECKING
@@ -1058,7 +1184,7 @@ build_graphite_scops (VEC (sd_region, heap) *regions,
          int j;
          sd_region *s2;
 
-         FOR_EACH_VEC_ELT (sd_region, regions, j, s2)
+         FOR_EACH_VEC_ELT (regions, j, s2)
            if (s != s2)
              gcc_assert (!bb_in_sd_region (s->entry, s2));
        }
@@ -1066,157 +1192,11 @@ build_graphite_scops (VEC (sd_region, heap) *regions,
     }
 }
 
-/* Returns true when BB contains only close phi nodes.  */
-
-static bool
-contains_only_close_phi_nodes (basic_block bb)
-{
-  gimple_stmt_iterator gsi;
-
-  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-    if (gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
-      return false;
-
-  return true;
-}
-
-/* Print statistics for SCOP to FILE.  */
-
-static void
-print_graphite_scop_statistics (FILE* file, scop_p scop)
-{
-  long n_bbs = 0;
-  long n_loops = 0;
-  long n_stmts = 0;
-  long n_conditions = 0;
-  long n_p_bbs = 0;
-  long n_p_loops = 0;
-  long n_p_stmts = 0;
-  long n_p_conditions = 0;
-
-  basic_block bb;
-
-  FOR_ALL_BB (bb)
-    {
-      gimple_stmt_iterator psi;
-      loop_p loop = bb->loop_father;
-
-      if (!bb_in_sese_p (bb, SCOP_REGION (scop)))
-       continue;
-
-      n_bbs++;
-      n_p_bbs += bb->count;
-
-      if (VEC_length (edge, bb->succs) > 1)
-       {
-         n_conditions++;
-         n_p_conditions += bb->count;
-       }
-
-      for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
-       {
-         n_stmts++;
-         n_p_stmts += bb->count;
-       }
-
-      if (loop->header == bb && loop_in_sese_p (loop, SCOP_REGION (scop)))
-       {
-         n_loops++;
-         n_p_loops += bb->count;
-       }
-
-    }
-
-  fprintf (file, "\nBefore limit_scops SCoP statistics (");
-  fprintf (file, "BBS:%ld, ", n_bbs);
-  fprintf (file, "LOOPS:%ld, ", n_loops);
-  fprintf (file, "CONDITIONS:%ld, ", n_conditions);
-  fprintf (file, "STMTS:%ld)\n", n_stmts);
-  fprintf (file, "\nBefore limit_scops SCoP profiling statistics (");
-  fprintf (file, "BBS:%ld, ", n_p_bbs);
-  fprintf (file, "LOOPS:%ld, ", n_p_loops);
-  fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
-  fprintf (file, "STMTS:%ld)\n", n_p_stmts);
-}
-
-/* Print statistics for SCOPS to FILE.  */
-
-static void
-print_graphite_statistics (FILE* file, VEC (scop_p, heap) *scops)
-{
-  int i;
-  scop_p scop;
-
-  FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
-    print_graphite_scop_statistics (file, scop);
-}
-
-/* We limit all SCoPs to SCoPs, that are completely surrounded by a loop.
-
-   Example:
-
-   for (i      |
-     {         |
-       for (j  |  SCoP 1
-       for (k  |
-     }         |
-
-   * SCoP frontier, as this line is not surrounded by any loop. *
-
-   for (l      |  SCoP 2
-
-   This is necessary as scalar evolution and parameter detection need a
-   outermost loop to initialize parameters correctly.
-
-   TODO: FIX scalar evolution and parameter detection to allow more flexible
-         SCoP frontiers.  */
-
-static void
-limit_scops (VEC (scop_p, heap) **scops)
-{
-  VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
-
-  int i;
-  scop_p scop;
-
-  FOR_EACH_VEC_ELT (scop_p, *scops, i, scop)
-    {
-      int j;
-      loop_p loop;
-      sese region = SCOP_REGION (scop);
-      build_sese_loop_nests (region);
-
-      FOR_EACH_VEC_ELT (loop_p, SESE_LOOP_NEST (region), j, loop)
-        if (!loop_in_sese_p (loop_outer (loop), region)
-           && single_exit (loop))
-          {
-           sd_region open_scop;
-           open_scop.entry = loop->header;
-           open_scop.exit = single_exit (loop)->dest;
-
-           /* This is a hack on top of the limit_scops hack.  The
-              limit_scops hack should disappear all together.  */
-           if (single_succ_p (open_scop.exit)
-               && contains_only_close_phi_nodes (open_scop.exit))
-             open_scop.exit = single_succ_edge (open_scop.exit)->dest;
-
-           VEC_safe_push (sd_region, heap, regions, &open_scop);
-         }
-    }
-
-  free_scops (*scops);
-  *scops = VEC_alloc (scop_p, heap, 3);
-
-  create_sese_edges (regions);
-  build_graphite_scops (regions, scops);
-  VEC_free (sd_region, heap, regions);
-}
-
 /* Returns true when P1 and P2 are close phis with the same
    argument.  */
 
 static inline bool
-same_close_phi_node (gimple p1, gimple p2)
+same_close_phi_node (gphi *p1, gphi *p2)
 {
   return operand_equal_p (gimple_phi_arg_def (p1, 0),
                          gimple_phi_arg_def (p2, 0), 0);
@@ -1226,15 +1206,15 @@ same_close_phi_node (gimple p1, gimple p2)
    of PHI.  */
 
 static void
-remove_duplicate_close_phi (gimple phi, gimple_stmt_iterator *gsi)
+remove_duplicate_close_phi (gphi *phi, gphi_iterator *gsi)
 {
   gimple use_stmt;
   use_operand_p use_p;
   imm_use_iterator imm_iter;
   tree res = gimple_phi_result (phi);
-  tree def = gimple_phi_result (gsi_stmt (*gsi));
+  tree def = gimple_phi_result (gsi->phi ());
 
-  gcc_assert (same_close_phi_node (phi, gsi_stmt (*gsi)));
+  gcc_assert (same_close_phi_node (phi, gsi->phi ()));
 
   FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def)
     {
@@ -1259,12 +1239,12 @@ remove_duplicate_close_phi (gimple phi, gimple_stmt_iterator *gsi)
 static void
 make_close_phi_nodes_unique (basic_block bb)
 {
-  gimple_stmt_iterator psi;
+  gphi_iterator psi;
 
   for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
     {
-      gimple_stmt_iterator gsi = psi;
-      gimple phi = gsi_stmt (psi);
+      gphi_iterator gsi = psi;
+      gphi *phi = psi.phi ();
 
       /* At this point, PHI should be a close phi in normal form.  */
       gcc_assert (gimple_phi_num_args (phi) == 1);
@@ -1272,7 +1252,7 @@ make_close_phi_nodes_unique (basic_block bb)
       /* Iterate over the next phis and remove duplicates.  */
       gsi_next (&gsi);
       while (!gsi_end_p (gsi))
-       if (same_close_phi_node (phi, gsi_stmt (gsi)))
+       if (same_close_phi_node (phi, gsi.phi ()))
          remove_duplicate_close_phi (phi, &gsi);
        else
          gsi_next (&gsi);
@@ -1292,21 +1272,21 @@ canonicalize_loop_closed_ssa (loop_p loop)
 
   bb = e->dest;
 
-  if (VEC_length (edge, bb->preds) == 1)
+  if (single_pred_p (bb))
     {
       e = split_block_after_labels (bb);
       make_close_phi_nodes_unique (e->src);
     }
   else
     {
-      gimple_stmt_iterator psi;
+      gphi_iterator psi;
       basic_block close = split_edge (e);
 
       e = single_succ_edge (close);
 
       for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
        {
-         gimple phi = gsi_stmt (psi);
+         gphi *phi = psi.phi ();
          unsigned i;
 
          for (i = 0; i < gimple_phi_num_args (phi); i++)
@@ -1314,14 +1294,13 @@ canonicalize_loop_closed_ssa (loop_p loop)
              {
                tree res, arg = gimple_phi_arg_def (phi, i);
                use_operand_p use_p;
-               gimple close_phi;
+               gphi *close_phi;
 
                if (TREE_CODE (arg) != SSA_NAME)
                  continue;
 
-               close_phi = create_phi_node (arg, close);
-               res = create_new_def_for (gimple_phi_result (close_phi),
-                                         close_phi,
+               close_phi = create_phi_node (NULL_TREE, close);
+               res = create_new_def_for (arg, close_phi,
                                          gimple_phi_result_ptr (close_phi));
                add_phi_arg (close_phi, arg,
                             gimple_phi_arg_edge (close_phi, 0),
@@ -1364,14 +1343,13 @@ canonicalize_loop_closed_ssa (loop_p loop)
 static void
 canonicalize_loop_closed_ssa_form (void)
 {
-  loop_iterator li;
   loop_p loop;
 
 #ifdef ENABLE_CHECKING
   verify_loop_closed_ssa (true);
 #endif
 
-  FOR_EACH_LOOP (li, loop, 0)
+  FOR_EACH_LOOP (loop, 0)
     canonicalize_loop_closed_ssa (loop);
 
   rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
@@ -1386,26 +1364,23 @@ canonicalize_loop_closed_ssa_form (void)
    them to SCOPS.  */
 
 void
-build_scops (VEC (scop_p, heap) **scops)
+build_scops (vec<scop_p> *scops)
 {
   struct loop *loop = current_loops->tree_root;
-  VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
+  auto_vec<sd_region, 3> regions;
 
   canonicalize_loop_closed_ssa_form ();
-  build_scops_1 (single_succ (ENTRY_BLOCK_PTR), ENTRY_BLOCK_PTR->loop_father,
+  build_scops_1 (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
+                ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father,
                 &regions, loop);
   create_sese_edges (regions);
   build_graphite_scops (regions, scops);
 
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    print_graphite_statistics (dump_file, *scops);
-
-  limit_scops (scops);
-  VEC_free (sd_region, heap, regions);
+  regions.release ();
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "\nnumber of SCoPs: %d\n",
-            VEC_length (scop_p, *scops));
+            scops ? scops->length () : 0);
 }
 
 /* Pretty print to FILE all the SCoPs in DOT format and mark them with
@@ -1419,7 +1394,7 @@ build_scops (VEC (scop_p, heap) **scops)
      exit nodes of the SCOP.  These are not part of SCoP.  */
 
 static void
-dot_all_scops_1 (FILE *file, VEC (scop_p, heap) *scops)
+dot_all_scops_1 (FILE *file, vec<scop_p> scops)
 {
   basic_block bb;
   edge e;
@@ -1434,7 +1409,7 @@ dot_all_scops_1 (FILE *file, VEC (scop_p, heap) *scops)
 
   fprintf (file, "digraph all {\n");
 
-  FOR_ALL_BB (bb)
+  FOR_ALL_BB_FN (bb, cfun)
     {
       int part_of_scop = false;
 
@@ -1446,7 +1421,7 @@ dot_all_scops_1 (FILE *file, VEC (scop_p, heap) *scops)
       fprintf (file, "CELLSPACING=\"0\">\n");
 
       /* Select color for SCoP.  */
-      FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
+      FOR_EACH_VEC_ELT (scops, i, scop)
        {
          sese region = SCOP_REGION (scop);
          if (bb_in_sese_p (bb, region)
@@ -1541,7 +1516,7 @@ dot_all_scops_1 (FILE *file, VEC (scop_p, heap) *scops)
       fprintf (file, "  </TABLE>>, shape=box, style=\"setlinewidth(0)\"]\n");
     }
 
-  FOR_ALL_BB (bb)
+  FOR_ALL_BB_FN (bb, cfun)
     {
       FOR_EACH_EDGE (e, ei, bb->succs)
              fprintf (file, "%d -> %d;\n", bb->index, e->dest->index);
@@ -1556,7 +1531,7 @@ dot_all_scops_1 (FILE *file, VEC (scop_p, heap) *scops)
 /* Display all SCoPs using dotty.  */
 
 DEBUG_FUNCTION void
-dot_all_scops (VEC (scop_p, heap) *scops)
+dot_all_scops (vec<scop_p> scops)
 {
   /* When debugging, enable the following code.  This cannot be used
      in production compilers because it calls "system".  */
@@ -1579,10 +1554,10 @@ dot_all_scops (VEC (scop_p, heap) *scops)
 DEBUG_FUNCTION void
 dot_scop (scop_p scop)
 {
-  VEC (scop_p, heap) *scops = NULL;
+  auto_vec<scop_p, 1> scops;
 
   if (scop)
-    VEC_safe_push (scop_p, heap, scops, scop);
+    scops.safe_push (scop);
 
   /* When debugging, enable the following code.  This cannot be used
      in production compilers because it calls "system".  */
@@ -1599,8 +1574,6 @@ dot_scop (scop_p scop)
 #else
   dot_all_scops_1 (stderr, scops);
 #endif
-
-  VEC_free (scop_p, heap, scops);
 }
 
-#endif
+#endif  /* HAVE_isl */