/* Gimple Represented as Polyhedra.
- Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2006-2015 Free Software Foundation, Inc.
Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
This file is part of GCC.
the functions that are used for transforming the code. */
#include "config.h"
+
+#ifdef HAVE_isl
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/options.h>
+#include <isl/union_map.h>
+#endif
+
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "ggc.h"
+#include "diagnostic-core.h"
+#include "alias.h"
+#include "symtab.h"
+#include "options.h"
#include "tree.h"
-#include "rtl.h"
+#include "fold-const.h"
+#include "predict.h"
+#include "tm.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
#include "basic-block.h"
-#include "diagnostic.h"
-#include "tree-flow.h"
-#include "toplev.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "tree-cfg.h"
+#include "tree-ssa-loop.h"
#include "tree-dump.h"
-#include "timevar.h"
#include "cfgloop.h"
#include "tree-chrec.h"
#include "tree-data-ref.h"
#include "tree-scalar-evolution.h"
-#include "tree-pass.h"
-#include "value-prof.h"
-#include "pointer-set.h"
-#include "gimple.h"
#include "sese.h"
-#include "predict.h"
+#include "dbgcnt.h"
+#include "tree-parloops.h"
+#include "tree-pass.h"
+#include "tree-cfgcleanup.h"
-#ifdef HAVE_cloog
+#ifdef HAVE_isl
-#include "cloog/cloog.h"
-#include "ppl_c.h"
-#include "graphite-ppl.h"
-#include "graphite.h"
#include "graphite-poly.h"
#include "graphite-scop-detection.h"
-#include "graphite-clast-to-gimple.h"
+#include "graphite-isl-ast-to-gimple.h"
#include "graphite-sese-to-poly.h"
/* Print global statistics to FILE. */
basic_block bb;
- FOR_ALL_BB (bb)
+ FOR_ALL_BB_FN (bb, cfun)
{
gimple_stmt_iterator psi;
n_p_loops += bb->count;
}
- if (VEC_length (edge, bb->succs) > 1)
+ if (EDGE_COUNT (bb->succs) > 1)
{
n_conditions++;
n_p_conditions += bb->count;
basic_block bb;
- FOR_ALL_BB (bb)
+ FOR_ALL_BB_FN (bb, cfun)
{
gimple_stmt_iterator psi;
loop_p loop = bb->loop_father;
n_bbs++;
n_p_bbs += bb->count;
- if (VEC_length (edge, bb->succs) > 1)
+ if (EDGE_COUNT (bb->succs) > 1)
{
n_conditions++;
n_p_conditions += bb->count;
/* Print statistics for SCOPS to FILE. */
static void
-print_graphite_statistics (FILE* file, VEC (scop_p, heap) *scops)
+print_graphite_statistics (FILE* file, vec<scop_p> scops)
{
int i;
scop_p scop;
- for (i = 0; VEC_iterate (scop_p, scops, i, scop); i++)
+ FOR_EACH_VEC_ELT (scops, i, scop)
print_graphite_scop_statistics (file, scop);
}
/* Initialize graphite: when there are no loops returns false. */
static bool
-graphite_initialize (void)
+graphite_initialize (isl_ctx *ctx)
{
- if (number_of_loops () <= 1
+ if (number_of_loops (cfun) <= 1
/* FIXME: This limit on the number of basic blocks of a function
should be removed when the SCOP detection is faster. */
- || n_basic_blocks > 100)
+ || (n_basic_blocks_for_fn (cfun) >
+ PARAM_VALUE (PARAM_GRAPHITE_MAX_BBS_PER_FUNCTION)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
print_global_statistics (dump_file);
+ isl_ctx_free (ctx);
return false;
}
+ scev_reset ();
recompute_all_dominators ();
initialize_original_copy_tables ();
- cloog_initialize ();
if (dump_file && dump_flags)
dump_function_to_file (current_function_decl, dump_file, dump_flags);
{
scev_reset ();
cleanup_tree_cfg ();
- profile_status = PROFILE_ABSENT;
+ profile_status_for_fn (cfun) = PROFILE_ABSENT;
release_recorded_exits ();
tree_estimate_probability ();
}
- cloog_finalize ();
free_original_copy_tables ();
if (dump_file && dump_flags)
print_loops (dump_file, 3);
}
+isl_ctx *the_isl_ctx;
+
/* Perform a set of linear transforms on the loops of the current
function. */
int i;
scop_p scop;
bool need_cfg_cleanup_p = false;
- VEC (scop_p, heap) *scops = NULL;
- htab_t bb_pbb_mapping;
+ vec<scop_p> scops = vNULL;
+ isl_ctx *ctx;
+
+ /* If a function is parallel it was most probably already run through graphite
+ once. No need to run again. */
+ if (parallelized_function_p (cfun->decl))
+ return;
- if (!graphite_initialize ())
+ ctx = isl_ctx_alloc ();
+ isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
+ if (!graphite_initialize (ctx))
return;
+ the_isl_ctx = ctx;
build_scops (&scops);
if (dump_file && (dump_flags & TDF_DETAILS))
print_global_statistics (dump_file);
}
- bb_pbb_mapping = htab_create (10, bb_pbb_map_hash, eq_bb_pbb_map, free);
+ FOR_EACH_VEC_ELT (scops, i, scop)
+ if (dbg_cnt (graphite_scop))
+ {
+ scop->ctx = ctx;
+ build_poly_scop (scop);
- for (i = 0; VEC_iterate (scop_p, scops, i, scop); i++)
- {
- bool transform_done = false;
-
- if (!build_poly_scop (scop))
- continue;
+ if (POLY_SCOP_P (scop)
+ && apply_poly_transforms (scop)
+ && graphite_regenerate_ast_isl (scop))
+ need_cfg_cleanup_p = true;
- if (apply_poly_transforms (scop))
- transform_done = gloog (scop, bb_pbb_mapping);
- else
- check_poly_representation (scop);
+ }
- if (transform_done)
- need_cfg_cleanup_p = true;
- }
-
- htab_delete (bb_pbb_mapping);
free_scops (scops);
graphite_finalize (need_cfg_cleanup_p);
+ the_isl_ctx = NULL;
+ isl_ctx_free (ctx);
}
-#else /* If Cloog is not available: #ifndef HAVE_cloog. */
+#else /* If ISL is not available: #ifndef HAVE_isl. */
-void
+static void
graphite_transform_loops (void)
{
- sorry ("Graphite loop optimizations cannot be used");
+ sorry ("Graphite loop optimizations cannot be used (ISL is not available).");
}
#endif
+
+
+static unsigned int
+graphite_transforms (struct function *fun)
+{
+ if (number_of_loops (fun) <= 1)
+ return 0;
+
+ graphite_transform_loops ();
+
+ return 0;
+}
+
+static bool
+gate_graphite_transforms (void)
+{
+ /* Enable -fgraphite pass if any one of the graphite optimization flags
+ is turned on. */
+ if (flag_loop_block
+ || flag_loop_interchange
+ || flag_loop_strip_mine
+ || flag_graphite_identity
+ || flag_loop_parallelize_all
+ || flag_loop_optimize_isl
+ || flag_loop_unroll_jam)
+ flag_graphite = 1;
+
+ return flag_graphite != 0;
+}
+
+namespace {
+
+const pass_data pass_data_graphite =
+{
+ GIMPLE_PASS, /* type */
+ "graphite0", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ TV_GRAPHITE, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_graphite : public gimple_opt_pass
+{
+public:
+ pass_graphite (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_graphite, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *) { return gate_graphite_transforms (); }
+
+}; // class pass_graphite
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_graphite (gcc::context *ctxt)
+{
+ return new pass_graphite (ctxt);
+}
+
+namespace {
+
+const pass_data pass_data_graphite_transforms =
+{
+ GIMPLE_PASS, /* type */
+ "graphite", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ TV_GRAPHITE_TRANSFORMS, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_graphite_transforms : public gimple_opt_pass
+{
+public:
+ pass_graphite_transforms (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *) { return gate_graphite_transforms (); }
+ virtual unsigned int execute (function *fun) { return graphite_transforms (fun); }
+
+}; // class pass_graphite_transforms
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_graphite_transforms (gcc::context *ctxt)
+{
+ return new pass_graphite_transforms (ctxt);
+}
+
+