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)
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
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
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. */
40 #include <isl/options.h>
41 #include <isl/union_map.h>
45 #include "coretypes.h"
46 #include "diagnostic-core.h"
54 #include "hard-reg-set.h"
57 #include "dominance.h"
59 #include "basic-block.h"
60 #include "tree-ssa-alias.h"
61 #include "internal-fn.h"
62 #include "gimple-expr.h"
65 #include "gimple-iterator.h"
67 #include "tree-ssa-loop.h"
68 #include "tree-dump.h"
70 #include "tree-chrec.h"
71 #include "tree-data-ref.h"
72 #include "tree-scalar-evolution.h"
75 #include "tree-parloops.h"
76 #include "tree-pass.h"
77 #include "tree-cfgcleanup.h"
81 #include "graphite-poly.h"
82 #include "graphite-scop-detection.h"
83 #include "graphite-isl-ast-to-gimple.h"
84 #include "graphite-sese-to-poly.h"
86 /* Print global statistics to FILE. */
89 print_global_statistics (FILE* file
)
94 long n_conditions
= 0;
98 long n_p_conditions
= 0;
102 FOR_ALL_BB_FN (bb
, cfun
)
104 gimple_stmt_iterator psi
;
107 n_p_bbs
+= bb
->count
;
109 /* Ignore artificial surrounding loop. */
110 if (bb
== bb
->loop_father
->header
114 n_p_loops
+= bb
->count
;
117 if (EDGE_COUNT (bb
->succs
) > 1)
120 n_p_conditions
+= bb
->count
;
123 for (psi
= gsi_start_bb (bb
); !gsi_end_p (psi
); gsi_next (&psi
))
126 n_p_stmts
+= bb
->count
;
130 fprintf (file
, "\nGlobal statistics (");
131 fprintf (file
, "BBS:%ld, ", n_bbs
);
132 fprintf (file
, "LOOPS:%ld, ", n_loops
);
133 fprintf (file
, "CONDITIONS:%ld, ", n_conditions
);
134 fprintf (file
, "STMTS:%ld)\n", n_stmts
);
135 fprintf (file
, "\nGlobal profiling statistics (");
136 fprintf (file
, "BBS:%ld, ", n_p_bbs
);
137 fprintf (file
, "LOOPS:%ld, ", n_p_loops
);
138 fprintf (file
, "CONDITIONS:%ld, ", n_p_conditions
);
139 fprintf (file
, "STMTS:%ld)\n", n_p_stmts
);
142 /* Print statistics for SCOP to FILE. */
145 print_graphite_scop_statistics (FILE* file
, scop_p scop
)
150 long n_conditions
= 0;
154 long n_p_conditions
= 0;
158 FOR_ALL_BB_FN (bb
, cfun
)
160 gimple_stmt_iterator psi
;
161 loop_p loop
= bb
->loop_father
;
163 if (!bb_in_sese_p (bb
, SCOP_REGION (scop
)))
167 n_p_bbs
+= bb
->count
;
169 if (EDGE_COUNT (bb
->succs
) > 1)
172 n_p_conditions
+= bb
->count
;
175 for (psi
= gsi_start_bb (bb
); !gsi_end_p (psi
); gsi_next (&psi
))
178 n_p_stmts
+= bb
->count
;
181 if (loop
->header
== bb
&& loop_in_sese_p (loop
, SCOP_REGION (scop
)))
184 n_p_loops
+= bb
->count
;
188 fprintf (file
, "\nSCoP statistics (");
189 fprintf (file
, "BBS:%ld, ", n_bbs
);
190 fprintf (file
, "LOOPS:%ld, ", n_loops
);
191 fprintf (file
, "CONDITIONS:%ld, ", n_conditions
);
192 fprintf (file
, "STMTS:%ld)\n", n_stmts
);
193 fprintf (file
, "\nSCoP profiling statistics (");
194 fprintf (file
, "BBS:%ld, ", n_p_bbs
);
195 fprintf (file
, "LOOPS:%ld, ", n_p_loops
);
196 fprintf (file
, "CONDITIONS:%ld, ", n_p_conditions
);
197 fprintf (file
, "STMTS:%ld)\n", n_p_stmts
);
200 /* Print statistics for SCOPS to FILE. */
203 print_graphite_statistics (FILE* file
, vec
<scop_p
> scops
)
209 FOR_EACH_VEC_ELT (scops
, i
, scop
)
210 print_graphite_scop_statistics (file
, scop
);
213 /* Initialize graphite: when there are no loops returns false. */
216 graphite_initialize (isl_ctx
*ctx
)
218 if (number_of_loops (cfun
) <= 1
219 /* FIXME: This limit on the number of basic blocks of a function
220 should be removed when the SCOP detection is faster. */
221 || (n_basic_blocks_for_fn (cfun
) >
222 PARAM_VALUE (PARAM_GRAPHITE_MAX_BBS_PER_FUNCTION
)))
224 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
225 print_global_statistics (dump_file
);
232 recompute_all_dominators ();
233 initialize_original_copy_tables ();
235 if (dump_file
&& dump_flags
)
236 dump_function_to_file (current_function_decl
, dump_file
, dump_flags
);
241 /* Finalize graphite: perform CFG cleanup when NEED_CFG_CLEANUP_P is
245 graphite_finalize (bool need_cfg_cleanup_p
)
247 if (need_cfg_cleanup_p
)
251 profile_status_for_fn (cfun
) = PROFILE_ABSENT
;
252 release_recorded_exits ();
253 tree_estimate_probability ();
256 free_original_copy_tables ();
258 if (dump_file
&& dump_flags
)
259 print_loops (dump_file
, 3);
262 isl_ctx
*the_isl_ctx
;
264 /* Perform a set of linear transforms on the loops of the current
268 graphite_transform_loops (void)
272 bool need_cfg_cleanup_p
= false;
273 vec
<scop_p
> scops
= vNULL
;
276 /* If a function is parallel it was most probably already run through graphite
277 once. No need to run again. */
278 if (parallelized_function_p (cfun
->decl
))
281 ctx
= isl_ctx_alloc ();
282 isl_options_set_on_error (ctx
, ISL_ON_ERROR_ABORT
);
283 if (!graphite_initialize (ctx
))
287 build_scops (&scops
);
289 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
291 print_graphite_statistics (dump_file
, scops
);
292 print_global_statistics (dump_file
);
295 FOR_EACH_VEC_ELT (scops
, i
, scop
)
296 if (dbg_cnt (graphite_scop
))
299 build_poly_scop (scop
);
301 if (POLY_SCOP_P (scop
)
302 && apply_poly_transforms (scop
)
303 && graphite_regenerate_ast_isl (scop
))
304 need_cfg_cleanup_p
= true;
309 graphite_finalize (need_cfg_cleanup_p
);
314 #else /* If ISL is not available: #ifndef HAVE_isl. */
317 graphite_transform_loops (void)
319 sorry ("Graphite loop optimizations cannot be used (ISL is not available).");
326 graphite_transforms (struct function
*fun
)
328 if (number_of_loops (fun
) <= 1)
331 graphite_transform_loops ();
337 gate_graphite_transforms (void)
339 /* Enable -fgraphite pass if any one of the graphite optimization flags
342 || flag_loop_interchange
343 || flag_loop_strip_mine
344 || flag_graphite_identity
345 || flag_loop_parallelize_all
346 || flag_loop_optimize_isl
347 || flag_loop_unroll_jam
)
350 return flag_graphite
!= 0;
355 const pass_data pass_data_graphite
=
357 GIMPLE_PASS
, /* type */
358 "graphite0", /* name */
359 OPTGROUP_LOOP
, /* optinfo_flags */
360 TV_GRAPHITE
, /* tv_id */
361 ( PROP_cfg
| PROP_ssa
), /* properties_required */
362 0, /* properties_provided */
363 0, /* properties_destroyed */
364 0, /* todo_flags_start */
365 0, /* todo_flags_finish */
368 class pass_graphite
: public gimple_opt_pass
371 pass_graphite (gcc::context
*ctxt
)
372 : gimple_opt_pass (pass_data_graphite
, ctxt
)
375 /* opt_pass methods: */
376 virtual bool gate (function
*) { return gate_graphite_transforms (); }
378 }; // class pass_graphite
383 make_pass_graphite (gcc::context
*ctxt
)
385 return new pass_graphite (ctxt
);
390 const pass_data pass_data_graphite_transforms
=
392 GIMPLE_PASS
, /* type */
393 "graphite", /* name */
394 OPTGROUP_LOOP
, /* optinfo_flags */
395 TV_GRAPHITE_TRANSFORMS
, /* tv_id */
396 ( PROP_cfg
| PROP_ssa
), /* properties_required */
397 0, /* properties_provided */
398 0, /* properties_destroyed */
399 0, /* todo_flags_start */
400 0, /* todo_flags_finish */
403 class pass_graphite_transforms
: public gimple_opt_pass
406 pass_graphite_transforms (gcc::context
*ctxt
)
407 : gimple_opt_pass (pass_data_graphite_transforms
, ctxt
)
410 /* opt_pass methods: */
411 virtual bool gate (function
*) { return gate_graphite_transforms (); }
412 virtual unsigned int execute (function
*fun
) { return graphite_transforms (fun
); }
414 }; // class pass_graphite_transforms
419 make_pass_graphite_transforms (gcc::context
*ctxt
)
421 return new pass_graphite_transforms (ctxt
);