]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graphite.c
gcc/
[thirdparty/gcc.git] / gcc / graphite.c
CommitLineData
255b6be7 1/* Gimple Represented as Polyhedra.
3aea1f79 2 Copyright (C) 2006-2014 Free Software Foundation, Inc.
255b6be7 3 Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21/* This pass converts GIMPLE to GRAPHITE, performs some loop
22 transformations and then converts the resulting representation back
26c166eb 23 to GIMPLE.
255b6be7 24
25 An early description of this pass can be found in the GCC Summit'06
26 paper "GRAPHITE: Polyhedral Analyses and Optimizations for GCC".
27 The wiki page http://gcc.gnu.org/wiki/Graphite contains pointers to
26c166eb 28 the related work.
255b6be7 29
30 One important document to read is CLooG's internal manual:
31 http://repo.or.cz/w/cloog-ppl.git?a=blob_plain;f=doc/cloog.texi;hb=HEAD
32 that describes the data structure of loops used in this file, and
33 the functions that are used for transforming the code. */
34
35#include "config.h"
87e20041 36
37#ifdef HAVE_cloog
38#include <isl/set.h>
39#include <isl/map.h>
40#include <isl/options.h>
41#include <isl/union_map.h>
42#include <cloog/cloog.h>
43#include <cloog/isl/domain.h>
44#include <cloog/isl/cloog.h>
45#endif
46
255b6be7 47#include "system.h"
48#include "coretypes.h"
52f91c04 49#include "diagnostic-core.h"
41a8aa41 50#include "tree.h"
bc61cadb 51#include "basic-block.h"
52#include "tree-ssa-alias.h"
53#include "internal-fn.h"
54#include "gimple-expr.h"
55#include "is-a.h"
073c1fd5 56#include "gimple.h"
dcf1a1ec 57#include "gimple-iterator.h"
073c1fd5 58#include "tree-cfg.h"
59#include "tree-ssa-loop.h"
255b6be7 60#include "tree-dump.h"
255b6be7 61#include "cfgloop.h"
62#include "tree-chrec.h"
63#include "tree-data-ref.h"
64#include "tree-scalar-evolution.h"
26c166eb 65#include "sese.h"
e819c864 66#include "dbgcnt.h"
64641360 67#include "tree-parloops.h"
68#include "tree-pass.h"
424a4a92 69#include "tree-cfgcleanup.h"
255b6be7 70
71#ifdef HAVE_cloog
d970c7fe 72
26c166eb 73#include "graphite-poly.h"
74#include "graphite-scop-detection.h"
75#include "graphite-clast-to-gimple.h"
5eb0077d 76#include "graphite-isl-ast-to-gimple.h"
26c166eb 77#include "graphite-sese-to-poly.h"
d9dd21a8 78#include "graphite-htab.h"
255b6be7 79
98b9957e 80CloogState *cloog_state;
81
26c166eb 82/* Print global statistics to FILE. */
7d3f5847 83
84static void
26c166eb 85print_global_statistics (FILE* file)
7d3f5847 86{
26c166eb 87 long n_bbs = 0;
88 long n_loops = 0;
89 long n_stmts = 0;
90 long n_conditions = 0;
91 long n_p_bbs = 0;
92 long n_p_loops = 0;
93 long n_p_stmts = 0;
94 long n_p_conditions = 0;
7d3f5847 95
26c166eb 96 basic_block bb;
7d3f5847 97
ed7d889a 98 FOR_ALL_BB_FN (bb, cfun)
26c166eb 99 {
100 gimple_stmt_iterator psi;
7d3f5847 101
26c166eb 102 n_bbs++;
103 n_p_bbs += bb->count;
7d3f5847 104
26c166eb 105 /* Ignore artificial surrounding loop. */
106 if (bb == bb->loop_father->header
107 && bb->index != 0)
7d3f5847 108 {
26c166eb 109 n_loops++;
110 n_p_loops += bb->count;
7d3f5847 111 }
7d3f5847 112
7bf60644 113 if (EDGE_COUNT (bb->succs) > 1)
26c166eb 114 {
115 n_conditions++;
116 n_p_conditions += bb->count;
117 }
7d3f5847 118
26c166eb 119 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
120 {
121 n_stmts++;
122 n_p_stmts += bb->count;
123 }
7d3f5847 124 }
125
26c166eb 126 fprintf (file, "\nGlobal statistics (");
127 fprintf (file, "BBS:%ld, ", n_bbs);
128 fprintf (file, "LOOPS:%ld, ", n_loops);
129 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
130 fprintf (file, "STMTS:%ld)\n", n_stmts);
131 fprintf (file, "\nGlobal profiling statistics (");
132 fprintf (file, "BBS:%ld, ", n_p_bbs);
133 fprintf (file, "LOOPS:%ld, ", n_p_loops);
134 fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
135 fprintf (file, "STMTS:%ld)\n", n_p_stmts);
255b6be7 136}
137
26c166eb 138/* Print statistics for SCOP to FILE. */
255b6be7 139
140static void
26c166eb 141print_graphite_scop_statistics (FILE* file, scop_p scop)
255b6be7 142{
26c166eb 143 long n_bbs = 0;
144 long n_loops = 0;
145 long n_stmts = 0;
146 long n_conditions = 0;
147 long n_p_bbs = 0;
148 long n_p_loops = 0;
149 long n_p_stmts = 0;
150 long n_p_conditions = 0;
255b6be7 151
26c166eb 152 basic_block bb;
255b6be7 153
ed7d889a 154 FOR_ALL_BB_FN (bb, cfun)
255b6be7 155 {
26c166eb 156 gimple_stmt_iterator psi;
157 loop_p loop = bb->loop_father;
255b6be7 158
26c166eb 159 if (!bb_in_sese_p (bb, SCOP_REGION (scop)))
160 continue;
255b6be7 161
26c166eb 162 n_bbs++;
163 n_p_bbs += bb->count;
255b6be7 164
7bf60644 165 if (EDGE_COUNT (bb->succs) > 1)
255b6be7 166 {
26c166eb 167 n_conditions++;
168 n_p_conditions += bb->count;
255b6be7 169 }
255b6be7 170
26c166eb 171 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
255b6be7 172 {
26c166eb 173 n_stmts++;
174 n_p_stmts += bb->count;
255b6be7 175 }
255b6be7 176
26c166eb 177 if (loop->header == bb && loop_in_sese_p (loop, SCOP_REGION (scop)))
178 {
179 n_loops++;
180 n_p_loops += bb->count;
181 }
182 }
145bdf6a 183
26c166eb 184 fprintf (file, "\nSCoP statistics (");
185 fprintf (file, "BBS:%ld, ", n_bbs);
186 fprintf (file, "LOOPS:%ld, ", n_loops);
187 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
188 fprintf (file, "STMTS:%ld)\n", n_stmts);
189 fprintf (file, "\nSCoP profiling statistics (");
190 fprintf (file, "BBS:%ld, ", n_p_bbs);
191 fprintf (file, "LOOPS:%ld, ", n_p_loops);
192 fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
193 fprintf (file, "STMTS:%ld)\n", n_p_stmts);
255b6be7 194}
195
26c166eb 196/* Print statistics for SCOPS to FILE. */
255b6be7 197
26c166eb 198static void
f1f41a6c 199print_graphite_statistics (FILE* file, vec<scop_p> scops)
255b6be7 200{
255b6be7 201 int i;
255b6be7 202
26c166eb 203 scop_p scop;
255b6be7 204
f1f41a6c 205 FOR_EACH_VEC_ELT (scops, i, scop)
26c166eb 206 print_graphite_scop_statistics (file, scop);
255b6be7 207}
208
26c166eb 209/* Initialize graphite: when there are no loops returns false. */
255b6be7 210
211static bool
87e20041 212graphite_initialize (isl_ctx *ctx)
255b6be7 213{
41f75a99 214 if (number_of_loops (cfun) <= 1
ef98ee10 215 /* FIXME: This limit on the number of basic blocks of a function
216 should be removed when the SCOP detection is faster. */
a28770e1 217 || (n_basic_blocks_for_fn (cfun) >
218 PARAM_VALUE (PARAM_GRAPHITE_MAX_BBS_PER_FUNCTION)))
255b6be7 219 {
26c166eb 220 if (dump_file && (dump_flags & TDF_DETAILS))
221 print_global_statistics (dump_file);
255b6be7 222
87e20041 223 isl_ctx_free (ctx);
26c166eb 224 return false;
255b6be7 225 }
226
d4d6f501 227 scev_reset ();
26c166eb 228 recompute_all_dominators ();
229 initialize_original_copy_tables ();
f0fc00f2 230
87e20041 231 cloog_state = cloog_isl_state_malloc (ctx);
255b6be7 232
26c166eb 233 if (dump_file && dump_flags)
234 dump_function_to_file (current_function_decl, dump_file, dump_flags);
255b6be7 235
26c166eb 236 return true;
255b6be7 237}
238
26c166eb 239/* Finalize graphite: perform CFG cleanup when NEED_CFG_CLEANUP_P is
240 true. */
255b6be7 241
242static void
26c166eb 243graphite_finalize (bool need_cfg_cleanup_p)
255b6be7 244{
26c166eb 245 if (need_cfg_cleanup_p)
675d86b2 246 {
d9458edc 247 scev_reset ();
675d86b2 248 cleanup_tree_cfg ();
f26d8580 249 profile_status_for_fn (cfun) = PROFILE_ABSENT;
675d86b2 250 release_recorded_exits ();
251 tree_estimate_probability ();
252 }
255b6be7 253
98b9957e 254 cloog_state_free (cloog_state);
26c166eb 255 free_original_copy_tables ();
d0483ac6 256
26c166eb 257 if (dump_file && dump_flags)
258 print_loops (dump_file, 3);
255b6be7 259}
260
87e20041 261isl_ctx *the_isl_ctx;
262
255b6be7 263/* Perform a set of linear transforms on the loops of the current
264 function. */
265
266void
267graphite_transform_loops (void)
268{
269 int i;
270 scop_p scop;
26c166eb 271 bool need_cfg_cleanup_p = false;
1e094109 272 vec<scop_p> scops = vNULL;
87e20041 273 isl_ctx *ctx;
255b6be7 274
479a6d79 275 /* If a function is parallel it was most probably already run through graphite
276 once. No need to run again. */
277 if (parallelized_function_p (cfun->decl))
278 return;
279
87e20041 280 ctx = isl_ctx_alloc ();
9af5ce0c 281 isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
87e20041 282 if (!graphite_initialize (ctx))
255b6be7 283 return;
284
87e20041 285 the_isl_ctx = ctx;
26c166eb 286 build_scops (&scops);
255b6be7 287
288 if (dump_file && (dump_flags & TDF_DETAILS))
255b6be7 289 {
26c166eb 290 print_graphite_statistics (dump_file, scops);
291 print_global_statistics (dump_file);
292 }
35fb1eb0 293
c1f445d2 294 bb_pbb_htab_type bb_pbb_mapping (10);
f1f41a6c 295 FOR_EACH_VEC_ELT (scops, i, scop)
e819c864 296 if (dbg_cnt (graphite_scop))
297 {
87e20041 298 scop->ctx = ctx;
8c6b3774 299 build_poly_scop (scop);
255b6be7 300
8c6b3774 301 if (POLY_SCOP_P (scop)
302 && apply_poly_transforms (scop)
5eb0077d 303 && (((flag_graphite_code_gen == FGRAPHITE_CODE_GEN_ISL)
304 && graphite_regenerate_ast_isl (scop))
305 || ((flag_graphite_code_gen == FGRAPHITE_CODE_GEN_CLOOG)
306 && graphite_regenerate_ast_cloog (scop, &bb_pbb_mapping))))
8c6b3774 307 need_cfg_cleanup_p = true;
308 }
255b6be7 309
26c166eb 310 free_scops (scops);
311 graphite_finalize (need_cfg_cleanup_p);
87e20041 312 the_isl_ctx = NULL;
313 isl_ctx_free (ctx);
255b6be7 314}
315
316#else /* If Cloog is not available: #ifndef HAVE_cloog. */
317
64641360 318static void
255b6be7 319graphite_transform_loops (void)
320{
255b6be7 321 sorry ("Graphite loop optimizations cannot be used");
322}
323
324#endif
64641360 325
326
327static unsigned int
b3083327 328graphite_transforms (struct function *fun)
64641360 329{
b3083327 330 if (number_of_loops (fun) <= 1)
64641360 331 return 0;
332
333 graphite_transform_loops ();
334
335 return 0;
336}
337
338static bool
339gate_graphite_transforms (void)
340{
341 /* Enable -fgraphite pass if any one of the graphite optimization flags
342 is turned on. */
343 if (flag_loop_block
344 || flag_loop_interchange
345 || flag_loop_strip_mine
346 || flag_graphite_identity
347 || flag_loop_parallelize_all
348 || flag_loop_optimize_isl)
349 flag_graphite = 1;
350
351 return flag_graphite != 0;
352}
353
354namespace {
355
356const pass_data pass_data_graphite =
357{
358 GIMPLE_PASS, /* type */
359 "graphite0", /* name */
360 OPTGROUP_LOOP, /* optinfo_flags */
64641360 361 false, /* has_execute */
362 TV_GRAPHITE, /* tv_id */
363 ( PROP_cfg | PROP_ssa ), /* properties_required */
364 0, /* properties_provided */
365 0, /* properties_destroyed */
366 0, /* todo_flags_start */
367 0, /* todo_flags_finish */
368};
369
370class pass_graphite : public gimple_opt_pass
371{
372public:
373 pass_graphite (gcc::context *ctxt)
374 : gimple_opt_pass (pass_data_graphite, ctxt)
375 {}
376
377 /* opt_pass methods: */
31315c24 378 virtual bool gate (function *) { return gate_graphite_transforms (); }
64641360 379
380}; // class pass_graphite
381
382} // anon namespace
383
384gimple_opt_pass *
385make_pass_graphite (gcc::context *ctxt)
386{
387 return new pass_graphite (ctxt);
388}
389
390namespace {
391
392const pass_data pass_data_graphite_transforms =
393{
394 GIMPLE_PASS, /* type */
395 "graphite", /* name */
396 OPTGROUP_LOOP, /* optinfo_flags */
64641360 397 true, /* has_execute */
398 TV_GRAPHITE_TRANSFORMS, /* tv_id */
399 ( PROP_cfg | PROP_ssa ), /* properties_required */
400 0, /* properties_provided */
401 0, /* properties_destroyed */
402 0, /* todo_flags_start */
403 0, /* todo_flags_finish */
404};
405
406class pass_graphite_transforms : public gimple_opt_pass
407{
408public:
409 pass_graphite_transforms (gcc::context *ctxt)
410 : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
411 {}
412
413 /* opt_pass methods: */
31315c24 414 virtual bool gate (function *) { return gate_graphite_transforms (); }
b3083327 415 virtual unsigned int execute (function *fun) { return graphite_transforms (fun); }
64641360 416
417}; // class pass_graphite_transforms
418
419} // anon namespace
420
421gimple_opt_pass *
422make_pass_graphite_transforms (gcc::context *ctxt)
423{
424 return new pass_graphite_transforms (ctxt);
425}
426
427