0fc822d0f9
2013-04-30 Richard Biener <rguenther@suse.de> * function.h (loops_for_fn): New inline function. (set_loops_for_fn): Likewise. * cfgloop.h (place_new_loop): Add struct function parameter. (get_loop): Likewise. (get_loops): Likewise. (number_of_loops): Likewise. (fel_next): Adjust. (fel_init): Likewise. * cfg.c (get_loop_copy): Adjust. * cfgloop.c (flow_loops_dump): Likewise. (record_loop_exits): Likewise. (verify_loop_structure): Likewise. * cfgloopanal.c (mark_irreducible_loops): Likewise. (estimate_reg_pressure_cost): Likewise. (mark_loop_exit_edges): Likewise. * cfgloopmanip.c (place_new_loop): Likewise. (add_loop): Likewise. (duplicate_loop): Likewise. * graph.c (draw_cfg_nodes): Likewise. * graphite-clast-to-gimple.c (translate_clast_user): Likewise. * graphite-sese-to-poly.c (build_scop_scattering): Likewise. (extract_affine_chrec): Likewise. (build_scop_iteration_domain): Likewise. * graphite.c (graphite_initialize): Likewise. * ira-build.c (create_loop_tree_nodes): Likewise. (more_one_region_p): Likewise. (rebuild_regno_allocno_maps): Likewise. (mark_loops_for_removal): Likewise. (mark_all_loops_for_removal): Likewise. (remove_unnecessary_regions): Likewise. (ira_build): Likewise. * ira-emit.c (setup_entered_from_non_parent_p): Likewise. * loop-init.c (fix_loop_structure): Likewise. (gate_rtl_move_loop_invariants): Likewise. (gate_rtl_unswitch): Likewise. (gate_rtl_unroll_and_peel_loops): Likewise. (rtl_doloop): Likewise. * lto-streamer-in.c (input_cfg): Likewise. * lto-streamer-out.c (output_cfg): Likewise. * modulo-sched.c (sms_schedule): Likewise. * predict.c (tree_estimate_probability): Likewise. (tree_estimate_probability_driver): Likewise. (estimate_loops): Likewise. * tree-cfg.c (fixup_loop_arrays_after_move): Likewise. (move_sese_region_to_fn): Likewise. (debug_loop_num): Likewise. * tree-chrec.c (chrec_evaluate): Likewise. (hide_evolution_in_other_loops_than_loop): Likewise. (chrec_component_in_loop_num): Likewise. (reset_evolution_in_loop): Likewise. (evolution_function_is_invariant_rec_p): Likewise. * tree-if-conv.c (main_tree_if_conversion): Likewise. * tree-inline.c (copy_loops): Likewise. (copy_cfg_body): Likewise. (tree_function_versioning): Likewise. * tree-loop-distribution.c (rdg_flag_loop_exits): Likewise. * tree-scalar-evolution.c (chrec_contains_symbols_defined_in_loop): Likewise. (add_to_evolution_1): Likewise. (scev_const_prop): Likewise. * tree-scalar-evolution.h (get_chrec_loop): Likewise. * tree-ssa-loop-ch.c (copy_loop_headers): Likewise. * tree-ssa-loop-im.c (analyze_memory_references): Likewise. (tree_ssa_lim_initialize): Likewise. * tree-ssa-loop-manip.c (rewrite_into_loop_closed_ssa): Likewise. (verify_loop_closed_ssa): Likewise. * tree-ssa-loop.c (tree_ssa_loop_init): Likewise. (tree_ssa_loop_im): Likewise. (tree_ssa_loop_unswitch): Likewise. (tree_vectorize): Likewise. (check_data_deps): Likewise. (tree_ssa_loop_ivcanon): Likewise. (tree_ssa_loop_bounds): Likewise. (tree_complete_unroll): Likewise. (tree_complete_unroll_inner): Likewise. (tree_parallelize_loops): Likewise. (tree_ssa_loop_prefetch): Likewise. (tree_ssa_loop_ivopts): Likewise. * tree-ssa.c (execute_update_addresses_taken): Liekwise. * tree-vectorizer.c (vectorize_loops): Likewise. From-SVN: r198441
311 lines
7.3 KiB
C
311 lines
7.3 KiB
C
/* Gimple Represented as Polyhedra.
|
|
Copyright (C) 2006-2013 Free Software Foundation, Inc.
|
|
Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
GCC is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
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/>. */
|
|
|
|
/* This pass converts GIMPLE to GRAPHITE, performs some loop
|
|
transformations and then converts the resulting representation back
|
|
to GIMPLE.
|
|
|
|
An early description of this pass can be found in the GCC Summit'06
|
|
paper "GRAPHITE: Polyhedral Analyses and Optimizations for GCC".
|
|
The wiki page http://gcc.gnu.org/wiki/Graphite contains pointers to
|
|
the related work.
|
|
|
|
One important document to read is CLooG's internal manual:
|
|
http://repo.or.cz/w/cloog-ppl.git?a=blob_plain;f=doc/cloog.texi;hb=HEAD
|
|
that describes the data structure of loops used in this file, and
|
|
the functions that are used for transforming the code. */
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef HAVE_cloog
|
|
#include <isl/set.h>
|
|
#include <isl/map.h>
|
|
#include <isl/options.h>
|
|
#include <isl/union_map.h>
|
|
#include <cloog/cloog.h>
|
|
#include <cloog/isl/domain.h>
|
|
#include <cloog/isl/cloog.h>
|
|
#endif
|
|
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "diagnostic-core.h"
|
|
#include "tree-flow.h"
|
|
#include "tree-dump.h"
|
|
#include "cfgloop.h"
|
|
#include "tree-chrec.h"
|
|
#include "tree-data-ref.h"
|
|
#include "tree-scalar-evolution.h"
|
|
#include "sese.h"
|
|
#include "dbgcnt.h"
|
|
|
|
#ifdef HAVE_cloog
|
|
|
|
#include "graphite-poly.h"
|
|
#include "graphite-scop-detection.h"
|
|
#include "graphite-clast-to-gimple.h"
|
|
#include "graphite-sese-to-poly.h"
|
|
#include "graphite-htab.h"
|
|
|
|
CloogState *cloog_state;
|
|
|
|
/* Print global statistics to FILE. */
|
|
|
|
static void
|
|
print_global_statistics (FILE* file)
|
|
{
|
|
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;
|
|
|
|
n_bbs++;
|
|
n_p_bbs += bb->count;
|
|
|
|
/* Ignore artificial surrounding loop. */
|
|
if (bb == bb->loop_father->header
|
|
&& bb->index != 0)
|
|
{
|
|
n_loops++;
|
|
n_p_loops += bb->count;
|
|
}
|
|
|
|
if (EDGE_COUNT (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;
|
|
}
|
|
}
|
|
|
|
fprintf (file, "\nGlobal 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, "\nGlobal 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 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 (EDGE_COUNT (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, "\nSCoP 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, "\nSCoP 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> scops)
|
|
{
|
|
int i;
|
|
|
|
scop_p scop;
|
|
|
|
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 (isl_ctx *ctx)
|
|
{
|
|
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 > 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_state = cloog_isl_state_malloc (ctx);
|
|
|
|
if (dump_file && dump_flags)
|
|
dump_function_to_file (current_function_decl, dump_file, dump_flags);
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Finalize graphite: perform CFG cleanup when NEED_CFG_CLEANUP_P is
|
|
true. */
|
|
|
|
static void
|
|
graphite_finalize (bool need_cfg_cleanup_p)
|
|
{
|
|
if (need_cfg_cleanup_p)
|
|
{
|
|
scev_reset ();
|
|
cleanup_tree_cfg ();
|
|
profile_status = PROFILE_ABSENT;
|
|
release_recorded_exits ();
|
|
tree_estimate_probability ();
|
|
}
|
|
|
|
cloog_state_free (cloog_state);
|
|
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. */
|
|
|
|
void
|
|
graphite_transform_loops (void)
|
|
{
|
|
int i;
|
|
scop_p scop;
|
|
bool need_cfg_cleanup_p = false;
|
|
vec<scop_p> scops = vNULL;
|
|
bb_pbb_htab_type bb_pbb_mapping;
|
|
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;
|
|
|
|
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_graphite_statistics (dump_file, scops);
|
|
print_global_statistics (dump_file);
|
|
}
|
|
|
|
bb_pbb_mapping.create (10);
|
|
|
|
FOR_EACH_VEC_ELT (scops, i, scop)
|
|
if (dbg_cnt (graphite_scop))
|
|
{
|
|
scop->ctx = ctx;
|
|
build_poly_scop (scop);
|
|
|
|
if (POLY_SCOP_P (scop)
|
|
&& apply_poly_transforms (scop)
|
|
&& gloog (scop, bb_pbb_mapping))
|
|
need_cfg_cleanup_p = true;
|
|
}
|
|
|
|
bb_pbb_mapping.dispose ();
|
|
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. */
|
|
|
|
void
|
|
graphite_transform_loops (void)
|
|
{
|
|
sorry ("Graphite loop optimizations cannot be used");
|
|
}
|
|
|
|
#endif
|