]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graphite.c
* configure.ac: Eliminate ClooG installation dependency.
[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
429cca51 37#ifdef HAVE_isl
87e20041 38#include <isl/set.h>
39#include <isl/map.h>
40#include <isl/options.h>
41#include <isl/union_map.h>
429cca51 42#ifdef HAVE_cloog
87e20041 43#include <cloog/cloog.h>
44#include <cloog/isl/domain.h>
45#include <cloog/isl/cloog.h>
46#endif
429cca51 47#endif
87e20041 48
255b6be7 49#include "system.h"
50#include "coretypes.h"
52f91c04 51#include "diagnostic-core.h"
41a8aa41 52#include "tree.h"
bc61cadb 53#include "basic-block.h"
54#include "tree-ssa-alias.h"
55#include "internal-fn.h"
56#include "gimple-expr.h"
57#include "is-a.h"
073c1fd5 58#include "gimple.h"
dcf1a1ec 59#include "gimple-iterator.h"
073c1fd5 60#include "tree-cfg.h"
61#include "tree-ssa-loop.h"
255b6be7 62#include "tree-dump.h"
255b6be7 63#include "cfgloop.h"
64#include "tree-chrec.h"
65#include "tree-data-ref.h"
66#include "tree-scalar-evolution.h"
26c166eb 67#include "sese.h"
e819c864 68#include "dbgcnt.h"
64641360 69#include "tree-parloops.h"
70#include "tree-pass.h"
424a4a92 71#include "tree-cfgcleanup.h"
255b6be7 72
429cca51 73#ifdef HAVE_isl
d970c7fe 74
26c166eb 75#include "graphite-poly.h"
76#include "graphite-scop-detection.h"
5eb0077d 77#include "graphite-isl-ast-to-gimple.h"
26c166eb 78#include "graphite-sese-to-poly.h"
d9dd21a8 79#include "graphite-htab.h"
255b6be7 80
429cca51 81#ifdef HAVE_cloog
82#include "graphite-clast-to-gimple.h"
83
98b9957e 84CloogState *cloog_state;
429cca51 85#endif
98b9957e 86
26c166eb 87/* Print global statistics to FILE. */
7d3f5847 88
89static void
26c166eb 90print_global_statistics (FILE* file)
7d3f5847 91{
26c166eb 92 long n_bbs = 0;
93 long n_loops = 0;
94 long n_stmts = 0;
95 long n_conditions = 0;
96 long n_p_bbs = 0;
97 long n_p_loops = 0;
98 long n_p_stmts = 0;
99 long n_p_conditions = 0;
7d3f5847 100
26c166eb 101 basic_block bb;
7d3f5847 102
ed7d889a 103 FOR_ALL_BB_FN (bb, cfun)
26c166eb 104 {
105 gimple_stmt_iterator psi;
7d3f5847 106
26c166eb 107 n_bbs++;
108 n_p_bbs += bb->count;
7d3f5847 109
26c166eb 110 /* Ignore artificial surrounding loop. */
111 if (bb == bb->loop_father->header
112 && bb->index != 0)
7d3f5847 113 {
26c166eb 114 n_loops++;
115 n_p_loops += bb->count;
7d3f5847 116 }
7d3f5847 117
7bf60644 118 if (EDGE_COUNT (bb->succs) > 1)
26c166eb 119 {
120 n_conditions++;
121 n_p_conditions += bb->count;
122 }
7d3f5847 123
26c166eb 124 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
125 {
126 n_stmts++;
127 n_p_stmts += bb->count;
128 }
7d3f5847 129 }
130
26c166eb 131 fprintf (file, "\nGlobal statistics (");
132 fprintf (file, "BBS:%ld, ", n_bbs);
133 fprintf (file, "LOOPS:%ld, ", n_loops);
134 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
135 fprintf (file, "STMTS:%ld)\n", n_stmts);
136 fprintf (file, "\nGlobal profiling statistics (");
137 fprintf (file, "BBS:%ld, ", n_p_bbs);
138 fprintf (file, "LOOPS:%ld, ", n_p_loops);
139 fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
140 fprintf (file, "STMTS:%ld)\n", n_p_stmts);
255b6be7 141}
142
26c166eb 143/* Print statistics for SCOP to FILE. */
255b6be7 144
145static void
26c166eb 146print_graphite_scop_statistics (FILE* file, scop_p scop)
255b6be7 147{
26c166eb 148 long n_bbs = 0;
149 long n_loops = 0;
150 long n_stmts = 0;
151 long n_conditions = 0;
152 long n_p_bbs = 0;
153 long n_p_loops = 0;
154 long n_p_stmts = 0;
155 long n_p_conditions = 0;
255b6be7 156
26c166eb 157 basic_block bb;
255b6be7 158
ed7d889a 159 FOR_ALL_BB_FN (bb, cfun)
255b6be7 160 {
26c166eb 161 gimple_stmt_iterator psi;
162 loop_p loop = bb->loop_father;
255b6be7 163
26c166eb 164 if (!bb_in_sese_p (bb, SCOP_REGION (scop)))
165 continue;
255b6be7 166
26c166eb 167 n_bbs++;
168 n_p_bbs += bb->count;
255b6be7 169
7bf60644 170 if (EDGE_COUNT (bb->succs) > 1)
255b6be7 171 {
26c166eb 172 n_conditions++;
173 n_p_conditions += bb->count;
255b6be7 174 }
255b6be7 175
26c166eb 176 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
255b6be7 177 {
26c166eb 178 n_stmts++;
179 n_p_stmts += bb->count;
255b6be7 180 }
255b6be7 181
26c166eb 182 if (loop->header == bb && loop_in_sese_p (loop, SCOP_REGION (scop)))
183 {
184 n_loops++;
185 n_p_loops += bb->count;
186 }
187 }
145bdf6a 188
26c166eb 189 fprintf (file, "\nSCoP statistics (");
190 fprintf (file, "BBS:%ld, ", n_bbs);
191 fprintf (file, "LOOPS:%ld, ", n_loops);
192 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
193 fprintf (file, "STMTS:%ld)\n", n_stmts);
194 fprintf (file, "\nSCoP profiling statistics (");
195 fprintf (file, "BBS:%ld, ", n_p_bbs);
196 fprintf (file, "LOOPS:%ld, ", n_p_loops);
197 fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
198 fprintf (file, "STMTS:%ld)\n", n_p_stmts);
255b6be7 199}
200
26c166eb 201/* Print statistics for SCOPS to FILE. */
255b6be7 202
26c166eb 203static void
f1f41a6c 204print_graphite_statistics (FILE* file, vec<scop_p> scops)
255b6be7 205{
255b6be7 206 int i;
255b6be7 207
26c166eb 208 scop_p scop;
255b6be7 209
f1f41a6c 210 FOR_EACH_VEC_ELT (scops, i, scop)
26c166eb 211 print_graphite_scop_statistics (file, scop);
255b6be7 212}
213
26c166eb 214/* Initialize graphite: when there are no loops returns false. */
255b6be7 215
216static bool
87e20041 217graphite_initialize (isl_ctx *ctx)
255b6be7 218{
41f75a99 219 if (number_of_loops (cfun) <= 1
ef98ee10 220 /* FIXME: This limit on the number of basic blocks of a function
221 should be removed when the SCOP detection is faster. */
a28770e1 222 || (n_basic_blocks_for_fn (cfun) >
223 PARAM_VALUE (PARAM_GRAPHITE_MAX_BBS_PER_FUNCTION)))
255b6be7 224 {
26c166eb 225 if (dump_file && (dump_flags & TDF_DETAILS))
226 print_global_statistics (dump_file);
255b6be7 227
87e20041 228 isl_ctx_free (ctx);
26c166eb 229 return false;
255b6be7 230 }
231
d4d6f501 232 scev_reset ();
26c166eb 233 recompute_all_dominators ();
234 initialize_original_copy_tables ();
f0fc00f2 235
429cca51 236#ifdef HAVE_cloog
87e20041 237 cloog_state = cloog_isl_state_malloc (ctx);
429cca51 238#endif
255b6be7 239
26c166eb 240 if (dump_file && dump_flags)
241 dump_function_to_file (current_function_decl, dump_file, dump_flags);
255b6be7 242
26c166eb 243 return true;
255b6be7 244}
245
26c166eb 246/* Finalize graphite: perform CFG cleanup when NEED_CFG_CLEANUP_P is
247 true. */
255b6be7 248
249static void
26c166eb 250graphite_finalize (bool need_cfg_cleanup_p)
255b6be7 251{
26c166eb 252 if (need_cfg_cleanup_p)
675d86b2 253 {
d9458edc 254 scev_reset ();
675d86b2 255 cleanup_tree_cfg ();
f26d8580 256 profile_status_for_fn (cfun) = PROFILE_ABSENT;
675d86b2 257 release_recorded_exits ();
258 tree_estimate_probability ();
259 }
255b6be7 260
429cca51 261#ifdef HAVE_cloog
98b9957e 262 cloog_state_free (cloog_state);
429cca51 263#endif
26c166eb 264 free_original_copy_tables ();
d0483ac6 265
26c166eb 266 if (dump_file && dump_flags)
267 print_loops (dump_file, 3);
255b6be7 268}
269
87e20041 270isl_ctx *the_isl_ctx;
271
255b6be7 272/* Perform a set of linear transforms on the loops of the current
273 function. */
274
275void
276graphite_transform_loops (void)
277{
278 int i;
279 scop_p scop;
26c166eb 280 bool need_cfg_cleanup_p = false;
1e094109 281 vec<scop_p> scops = vNULL;
87e20041 282 isl_ctx *ctx;
255b6be7 283
479a6d79 284 /* If a function is parallel it was most probably already run through graphite
285 once. No need to run again. */
286 if (parallelized_function_p (cfun->decl))
287 return;
288
87e20041 289 ctx = isl_ctx_alloc ();
9af5ce0c 290 isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
87e20041 291 if (!graphite_initialize (ctx))
255b6be7 292 return;
293
87e20041 294 the_isl_ctx = ctx;
26c166eb 295 build_scops (&scops);
255b6be7 296
297 if (dump_file && (dump_flags & TDF_DETAILS))
255b6be7 298 {
26c166eb 299 print_graphite_statistics (dump_file, scops);
300 print_global_statistics (dump_file);
301 }
35fb1eb0 302
c1f445d2 303 bb_pbb_htab_type bb_pbb_mapping (10);
429cca51 304
305#ifndef HAVE_cloog
306 if(flag_graphite_code_gen == FGRAPHITE_CODE_GEN_CLOOG)
307 {
308 flag_graphite_code_gen = FGRAPHITE_CODE_GEN_ISL;
309 printf ("The CLooG code generator cannot be used (CLooG is not "
310 "available). The ISL code generator was chosen.\n");
311 }
312#endif
313
f1f41a6c 314 FOR_EACH_VEC_ELT (scops, i, scop)
e819c864 315 if (dbg_cnt (graphite_scop))
316 {
87e20041 317 scop->ctx = ctx;
8c6b3774 318 build_poly_scop (scop);
255b6be7 319
429cca51 320#ifdef HAVE_cloog
8c6b3774 321 if (POLY_SCOP_P (scop)
322 && apply_poly_transforms (scop)
5eb0077d 323 && (((flag_graphite_code_gen == FGRAPHITE_CODE_GEN_ISL)
324 && graphite_regenerate_ast_isl (scop))
325 || ((flag_graphite_code_gen == FGRAPHITE_CODE_GEN_CLOOG)
326 && graphite_regenerate_ast_cloog (scop, &bb_pbb_mapping))))
8c6b3774 327 need_cfg_cleanup_p = true;
429cca51 328#else
329 if (POLY_SCOP_P (scop)
330 && apply_poly_transforms (scop)
331 && graphite_regenerate_ast_isl (scop))
332 need_cfg_cleanup_p = true;
333#endif
334
8c6b3774 335 }
255b6be7 336
26c166eb 337 free_scops (scops);
338 graphite_finalize (need_cfg_cleanup_p);
87e20041 339 the_isl_ctx = NULL;
340 isl_ctx_free (ctx);
255b6be7 341}
342
429cca51 343#else /* If ISL is not available: #ifndef HAVE_isl. */
255b6be7 344
64641360 345static void
255b6be7 346graphite_transform_loops (void)
347{
429cca51 348 sorry ("Graphite loop optimizations cannot be used (ISL is not available).");
255b6be7 349}
350
351#endif
64641360 352
353
354static unsigned int
b3083327 355graphite_transforms (struct function *fun)
64641360 356{
b3083327 357 if (number_of_loops (fun) <= 1)
64641360 358 return 0;
359
360 graphite_transform_loops ();
361
362 return 0;
363}
364
365static bool
366gate_graphite_transforms (void)
367{
368 /* Enable -fgraphite pass if any one of the graphite optimization flags
369 is turned on. */
370 if (flag_loop_block
371 || flag_loop_interchange
372 || flag_loop_strip_mine
373 || flag_graphite_identity
374 || flag_loop_parallelize_all
375 || flag_loop_optimize_isl)
376 flag_graphite = 1;
377
378 return flag_graphite != 0;
379}
380
381namespace {
382
383const pass_data pass_data_graphite =
384{
385 GIMPLE_PASS, /* type */
386 "graphite0", /* name */
387 OPTGROUP_LOOP, /* optinfo_flags */
64641360 388 TV_GRAPHITE, /* tv_id */
389 ( PROP_cfg | PROP_ssa ), /* properties_required */
390 0, /* properties_provided */
391 0, /* properties_destroyed */
392 0, /* todo_flags_start */
393 0, /* todo_flags_finish */
394};
395
396class pass_graphite : public gimple_opt_pass
397{
398public:
399 pass_graphite (gcc::context *ctxt)
400 : gimple_opt_pass (pass_data_graphite, ctxt)
401 {}
402
403 /* opt_pass methods: */
31315c24 404 virtual bool gate (function *) { return gate_graphite_transforms (); }
64641360 405
406}; // class pass_graphite
407
408} // anon namespace
409
410gimple_opt_pass *
411make_pass_graphite (gcc::context *ctxt)
412{
413 return new pass_graphite (ctxt);
414}
415
416namespace {
417
418const pass_data pass_data_graphite_transforms =
419{
420 GIMPLE_PASS, /* type */
421 "graphite", /* name */
422 OPTGROUP_LOOP, /* optinfo_flags */
64641360 423 TV_GRAPHITE_TRANSFORMS, /* tv_id */
424 ( PROP_cfg | PROP_ssa ), /* properties_required */
425 0, /* properties_provided */
426 0, /* properties_destroyed */
427 0, /* todo_flags_start */
428 0, /* todo_flags_finish */
429};
430
431class pass_graphite_transforms : public gimple_opt_pass
432{
433public:
434 pass_graphite_transforms (gcc::context *ctxt)
435 : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
436 {}
437
438 /* opt_pass methods: */
31315c24 439 virtual bool gate (function *) { return gate_graphite_transforms (); }
b3083327 440 virtual unsigned int execute (function *fun) { return graphite_transforms (fun); }
64641360 441
442}; // class pass_graphite_transforms
443
444} // anon namespace
445
446gimple_opt_pass *
447make_pass_graphite_transforms (gcc::context *ctxt)
448{
449 return new pass_graphite_transforms (ctxt);
450}
451
452