57d598f76c
2011-03-12 Sebastian Pop <sebastian.pop@amd.com> PR tree-optimization/47127 * graphite-clast-to-gimple.c (build_cloog_prog): Removed state parameter. (set_cloog_options): Same. (scop_to_clast): Same. (print_clast_stmt): Do not call cloog_state_malloc and cloog_state_free. (print_generated_program): Same. (gloog): Same. * graphite-clast-to-gimple.h (cloog_state): Declared. (scop_to_clast): Adjust declaration. * graphite.c (cloog_state): Defined here. (graphite_initialize): Call cloog_state_malloc. (graphite_finalize): Call cloog_state_free. From-SVN: r170907
294 lines
7.0 KiB
C
294 lines
7.0 KiB
C
/* Gimple Represented as Polyhedra.
|
|
Copyright (C) 2006, 2007, 2008, 2009, 2010 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"
|
|
#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 "ppl_c.h"
|
|
#include "graphite-ppl.h"
|
|
#include "graphite-poly.h"
|
|
#include "graphite-scop-detection.h"
|
|
#include "graphite-clast-to-gimple.h"
|
|
#include "graphite-sese-to-poly.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 (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;
|
|
}
|
|
}
|
|
|
|
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 (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, "\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, heap) *scops)
|
|
{
|
|
int i;
|
|
|
|
scop_p scop;
|
|
|
|
FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
|
|
print_graphite_scop_statistics (file, scop);
|
|
}
|
|
|
|
/* Initialize graphite: when there are no loops returns false. */
|
|
|
|
static bool
|
|
graphite_initialize (void)
|
|
{
|
|
int ppl_initialized;
|
|
|
|
if (number_of_loops () <= 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);
|
|
|
|
return false;
|
|
}
|
|
|
|
scev_reset ();
|
|
recompute_all_dominators ();
|
|
initialize_original_copy_tables ();
|
|
|
|
ppl_initialized = ppl_initialize ();
|
|
gcc_assert (ppl_initialized == 0);
|
|
|
|
cloog_state = cloog_state_malloc ();
|
|
cloog_initialize ();
|
|
|
|
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);
|
|
cloog_finalize ();
|
|
ppl_finalize ();
|
|
free_original_copy_tables ();
|
|
|
|
if (dump_file && dump_flags)
|
|
print_loops (dump_file, 3);
|
|
}
|
|
|
|
/* 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, heap) *scops = NULL;
|
|
htab_t bb_pbb_mapping;
|
|
|
|
if (!graphite_initialize ())
|
|
return;
|
|
|
|
build_scops (&scops);
|
|
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
|
{
|
|
print_graphite_statistics (dump_file, scops);
|
|
print_global_statistics (dump_file);
|
|
}
|
|
|
|
bb_pbb_mapping = htab_create (10, bb_pbb_map_hash, eq_bb_pbb_map, free);
|
|
|
|
FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
|
|
if (dbg_cnt (graphite_scop))
|
|
{
|
|
build_poly_scop (scop);
|
|
|
|
if (POLY_SCOP_P (scop)
|
|
&& apply_poly_transforms (scop)
|
|
&& gloog (scop, bb_pbb_mapping))
|
|
need_cfg_cleanup_p = true;
|
|
}
|
|
|
|
htab_delete (bb_pbb_mapping);
|
|
free_scops (scops);
|
|
graphite_finalize (need_cfg_cleanup_p);
|
|
}
|
|
|
|
#else /* If Cloog is not available: #ifndef HAVE_cloog. */
|
|
|
|
void
|
|
graphite_transform_loops (void)
|
|
{
|
|
sorry ("Graphite loop optimizations cannot be used");
|
|
}
|
|
|
|
#endif
|