Rebase.
[official-gcc.git] / gcc / graphite.c
blobaa5b8d8aa490a1810c902daa090ffd69b5c88e9c
1 /* Gimple Represented as Polyhedra.
2 Copyright (C) 2006-2014 Free Software Foundation, Inc.
3 Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* This pass converts GIMPLE to GRAPHITE, performs some loop
22 transformations and then converts the resulting representation back
23 to GIMPLE.
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
28 the related work.
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. */
35 #include "config.h"
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
47 #include "system.h"
48 #include "coretypes.h"
49 #include "diagnostic-core.h"
50 #include "tree.h"
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"
56 #include "gimple.h"
57 #include "gimple-iterator.h"
58 #include "tree-cfg.h"
59 #include "tree-ssa-loop.h"
60 #include "tree-dump.h"
61 #include "cfgloop.h"
62 #include "tree-chrec.h"
63 #include "tree-data-ref.h"
64 #include "tree-scalar-evolution.h"
65 #include "sese.h"
66 #include "dbgcnt.h"
67 #include "tree-parloops.h"
68 #include "tree-pass.h"
69 #include "tree-cfgcleanup.h"
71 #ifdef HAVE_cloog
73 #include "graphite-poly.h"
74 #include "graphite-scop-detection.h"
75 #include "graphite-clast-to-gimple.h"
76 #include "graphite-isl-ast-to-gimple.h"
77 #include "graphite-sese-to-poly.h"
78 #include "graphite-htab.h"
80 CloogState *cloog_state;
82 /* Print global statistics to FILE. */
84 static void
85 print_global_statistics (FILE* file)
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;
96 basic_block bb;
98 FOR_ALL_BB_FN (bb, cfun)
100 gimple_stmt_iterator psi;
102 n_bbs++;
103 n_p_bbs += bb->count;
105 /* Ignore artificial surrounding loop. */
106 if (bb == bb->loop_father->header
107 && bb->index != 0)
109 n_loops++;
110 n_p_loops += bb->count;
113 if (EDGE_COUNT (bb->succs) > 1)
115 n_conditions++;
116 n_p_conditions += bb->count;
119 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
121 n_stmts++;
122 n_p_stmts += bb->count;
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);
138 /* Print statistics for SCOP to FILE. */
140 static void
141 print_graphite_scop_statistics (FILE* file, scop_p scop)
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;
152 basic_block bb;
154 FOR_ALL_BB_FN (bb, cfun)
156 gimple_stmt_iterator psi;
157 loop_p loop = bb->loop_father;
159 if (!bb_in_sese_p (bb, SCOP_REGION (scop)))
160 continue;
162 n_bbs++;
163 n_p_bbs += bb->count;
165 if (EDGE_COUNT (bb->succs) > 1)
167 n_conditions++;
168 n_p_conditions += bb->count;
171 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
173 n_stmts++;
174 n_p_stmts += bb->count;
177 if (loop->header == bb && loop_in_sese_p (loop, SCOP_REGION (scop)))
179 n_loops++;
180 n_p_loops += bb->count;
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);
196 /* Print statistics for SCOPS to FILE. */
198 static void
199 print_graphite_statistics (FILE* file, vec<scop_p> scops)
201 int i;
203 scop_p scop;
205 FOR_EACH_VEC_ELT (scops, i, scop)
206 print_graphite_scop_statistics (file, scop);
209 /* Initialize graphite: when there are no loops returns false. */
211 static bool
212 graphite_initialize (isl_ctx *ctx)
214 if (number_of_loops (cfun) <= 1
215 /* FIXME: This limit on the number of basic blocks of a function
216 should be removed when the SCOP detection is faster. */
217 || (n_basic_blocks_for_fn (cfun) >
218 PARAM_VALUE (PARAM_GRAPHITE_MAX_BBS_PER_FUNCTION)))
220 if (dump_file && (dump_flags & TDF_DETAILS))
221 print_global_statistics (dump_file);
223 isl_ctx_free (ctx);
224 return false;
227 scev_reset ();
228 recompute_all_dominators ();
229 initialize_original_copy_tables ();
231 cloog_state = cloog_isl_state_malloc (ctx);
233 if (dump_file && dump_flags)
234 dump_function_to_file (current_function_decl, dump_file, dump_flags);
236 return true;
239 /* Finalize graphite: perform CFG cleanup when NEED_CFG_CLEANUP_P is
240 true. */
242 static void
243 graphite_finalize (bool need_cfg_cleanup_p)
245 if (need_cfg_cleanup_p)
247 scev_reset ();
248 cleanup_tree_cfg ();
249 profile_status_for_fn (cfun) = PROFILE_ABSENT;
250 release_recorded_exits ();
251 tree_estimate_probability ();
254 cloog_state_free (cloog_state);
255 free_original_copy_tables ();
257 if (dump_file && dump_flags)
258 print_loops (dump_file, 3);
261 isl_ctx *the_isl_ctx;
263 /* Perform a set of linear transforms on the loops of the current
264 function. */
266 void
267 graphite_transform_loops (void)
269 int i;
270 scop_p scop;
271 bool need_cfg_cleanup_p = false;
272 vec<scop_p> scops = vNULL;
273 isl_ctx *ctx;
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;
280 ctx = isl_ctx_alloc ();
281 isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
282 if (!graphite_initialize (ctx))
283 return;
285 the_isl_ctx = ctx;
286 build_scops (&scops);
288 if (dump_file && (dump_flags & TDF_DETAILS))
290 print_graphite_statistics (dump_file, scops);
291 print_global_statistics (dump_file);
294 bb_pbb_htab_type bb_pbb_mapping (10);
295 FOR_EACH_VEC_ELT (scops, i, scop)
296 if (dbg_cnt (graphite_scop))
298 scop->ctx = ctx;
299 build_poly_scop (scop);
301 if (POLY_SCOP_P (scop)
302 && apply_poly_transforms (scop)
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))))
307 need_cfg_cleanup_p = true;
310 free_scops (scops);
311 graphite_finalize (need_cfg_cleanup_p);
312 the_isl_ctx = NULL;
313 isl_ctx_free (ctx);
316 #else /* If Cloog is not available: #ifndef HAVE_cloog. */
318 static void
319 graphite_transform_loops (void)
321 sorry ("Graphite loop optimizations cannot be used");
324 #endif
327 static unsigned int
328 graphite_transforms (struct function *fun)
330 if (number_of_loops (fun) <= 1)
331 return 0;
333 graphite_transform_loops ();
335 return 0;
338 static bool
339 gate_graphite_transforms (void)
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;
351 return flag_graphite != 0;
354 namespace {
356 const pass_data pass_data_graphite =
358 GIMPLE_PASS, /* type */
359 "graphite0", /* name */
360 OPTGROUP_LOOP, /* optinfo_flags */
361 TV_GRAPHITE, /* tv_id */
362 ( PROP_cfg | PROP_ssa ), /* properties_required */
363 0, /* properties_provided */
364 0, /* properties_destroyed */
365 0, /* todo_flags_start */
366 0, /* todo_flags_finish */
369 class pass_graphite : public gimple_opt_pass
371 public:
372 pass_graphite (gcc::context *ctxt)
373 : gimple_opt_pass (pass_data_graphite, ctxt)
376 /* opt_pass methods: */
377 virtual bool gate (function *) { return gate_graphite_transforms (); }
379 }; // class pass_graphite
381 } // anon namespace
383 gimple_opt_pass *
384 make_pass_graphite (gcc::context *ctxt)
386 return new pass_graphite (ctxt);
389 namespace {
391 const pass_data pass_data_graphite_transforms =
393 GIMPLE_PASS, /* type */
394 "graphite", /* name */
395 OPTGROUP_LOOP, /* optinfo_flags */
396 TV_GRAPHITE_TRANSFORMS, /* tv_id */
397 ( PROP_cfg | PROP_ssa ), /* properties_required */
398 0, /* properties_provided */
399 0, /* properties_destroyed */
400 0, /* todo_flags_start */
401 0, /* todo_flags_finish */
404 class pass_graphite_transforms : public gimple_opt_pass
406 public:
407 pass_graphite_transforms (gcc::context *ctxt)
408 : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
411 /* opt_pass methods: */
412 virtual bool gate (function *) { return gate_graphite_transforms (); }
413 virtual unsigned int execute (function *fun) { return graphite_transforms (fun); }
415 }; // class pass_graphite_transforms
417 } // anon namespace
419 gimple_opt_pass *
420 make_pass_graphite_transforms (gcc::context *ctxt)
422 return new pass_graphite_transforms (ctxt);