/* 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>.
<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,
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.
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. */
}
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;
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. */
/* 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. */
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:
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));
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;
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))
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;
}
|| (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;
}
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;
}
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. */
};
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;
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);
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, ®ions, 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;
{
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);
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
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;
if (result.difficult)
move_sd_regions (®ions, scops);
else
- VEC_free (sd_region, heap, regions);
+ regions.release ();
}
break;
{
/* 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, ®ions, 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))
{
result.difficult = true;
result.exits = false;
move_sd_regions (®ions, 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;
/* 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. */
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))
result.exit = NULL;
}
- VEC_free (basic_block, heap, dominated);
+ dominated.release ();
result.next = NULL;
move_sd_regions (®ions, scops);
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;
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;
}
{
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;
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;
}
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;
/* 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);
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
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));
}
}
}
-/* 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);
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)
{
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);
/* 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);
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++)
{
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),
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);
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,
®ions, 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
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;
fprintf (file, "digraph all {\n");
- FOR_ALL_BB (bb)
+ FOR_ALL_BB_FN (bb, cfun)
{
int part_of_scop = false;
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)
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);
/* 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". */
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". */
#else
dot_all_scops_1 (stderr, scops);
#endif
-
- VEC_free (scop_p, heap, scops);
}
-#endif
+#endif /* HAVE_isl */