]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graphite.c
Update copyright years.
[thirdparty/gcc.git] / gcc / graphite.c
CommitLineData
f8bf9252 1/* Gimple Represented as Polyhedra.
8d9254fc 2 Copyright (C) 2006-2020 Free Software Foundation, Inc.
f8bf9252
SP
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
204b560f 23 to GIMPLE.
f8bf9252
SP
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
d6bb5ccf 28 the related work. */
f8bf9252 29
4d776011 30#define USES_ISL
33ad93b9 31
4d776011 32#include "config.h"
f8bf9252
SP
33#include "system.h"
34#include "coretypes.h"
c7131fb2 35#include "backend.h"
9c358739
AM
36#include "diagnostic-core.h"
37#include "cfgloop.h"
38#include "tree-pass.h"
7009b073 39#include "pretty-print.h"
b25f84d0 40#include "cfganal.h"
9c358739
AM
41
42#ifdef HAVE_isl
9fdcd34e 43#include "cfghooks.h"
40e23961 44#include "tree.h"
c7131fb2 45#include "gimple.h"
ab0e5308 46#include "ssa.h"
c7131fb2 47#include "fold-const.h"
5be5c238 48#include "gimple-iterator.h"
442b4905
AM
49#include "tree-cfg.h"
50#include "tree-ssa-loop.h"
f8bf9252
SP
51#include "tree-data-ref.h"
52#include "tree-scalar-evolution.h"
6a7441f5 53#include "dbgcnt.h"
c1bf2a39 54#include "tree-parloops.h"
4484a35a 55#include "tree-cfgcleanup.h"
558b3185 56#include "tree-vectorizer.h"
ab0e5308 57#include "tree-ssa-loop-manip.h"
6fe00fb7
RB
58#include "tree-ssa.h"
59#include "tree-into-ssa.h"
cf98f0f4 60#include "graphite.h"
57d598f7 61
204b560f 62/* Print global statistics to FILE. */
4d6c7237
SP
63
64static void
204b560f 65print_global_statistics (FILE* file)
4d6c7237 66{
204b560f
SP
67 long n_bbs = 0;
68 long n_loops = 0;
69 long n_stmts = 0;
70 long n_conditions = 0;
3995f3a2
JH
71 profile_count n_p_bbs = profile_count::zero ();
72 profile_count n_p_loops = profile_count::zero ();
73 profile_count n_p_stmts = profile_count::zero ();
74 profile_count n_p_conditions = profile_count::zero ();
4d6c7237 75
204b560f 76 basic_block bb;
4d6c7237 77
04a90bec 78 FOR_ALL_BB_FN (bb, cfun)
204b560f
SP
79 {
80 gimple_stmt_iterator psi;
4d6c7237 81
204b560f 82 n_bbs++;
3995f3a2
JH
83 if (bb->count.initialized_p ())
84 n_p_bbs += bb->count;
4d6c7237 85
204b560f
SP
86 /* Ignore artificial surrounding loop. */
87 if (bb == bb->loop_father->header
88 && bb->index != 0)
4d6c7237 89 {
204b560f
SP
90 n_loops++;
91 n_p_loops += bb->count;
4d6c7237 92 }
4d6c7237 93
d630245f 94 if (EDGE_COUNT (bb->succs) > 1)
204b560f
SP
95 {
96 n_conditions++;
3995f3a2
JH
97 if (bb->count.initialized_p ())
98 n_p_conditions += bb->count;
204b560f 99 }
4d6c7237 100
204b560f
SP
101 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
102 {
103 n_stmts++;
3995f3a2
JH
104 if (bb->count.initialized_p ())
105 n_p_stmts += bb->count;
204b560f 106 }
4d6c7237
SP
107 }
108
204b560f
SP
109 fprintf (file, "\nGlobal statistics (");
110 fprintf (file, "BBS:%ld, ", n_bbs);
111 fprintf (file, "LOOPS:%ld, ", n_loops);
112 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
113 fprintf (file, "STMTS:%ld)\n", n_stmts);
c46bd472 114 fprintf (file, "Global profiling statistics (");
3995f3a2
JH
115 fprintf (file, "BBS:");
116 n_p_bbs.dump (file);
117 fprintf (file, ", LOOPS:");
118 n_p_loops.dump (file);
119 fprintf (file, ", CONDITIONS:");
120 n_p_conditions.dump (file);
121 fprintf (file, ", STMTS:");
122 n_p_stmts.dump (file);
c46bd472 123 fprintf (file, ")\n\n");
f8bf9252
SP
124}
125
204b560f 126/* Print statistics for SCOP to FILE. */
f8bf9252
SP
127
128static void
204b560f 129print_graphite_scop_statistics (FILE* file, scop_p scop)
f8bf9252 130{
204b560f
SP
131 long n_bbs = 0;
132 long n_loops = 0;
133 long n_stmts = 0;
134 long n_conditions = 0;
3995f3a2
JH
135 profile_count n_p_bbs = profile_count::zero ();
136 profile_count n_p_loops = profile_count::zero ();
137 profile_count n_p_stmts = profile_count::zero ();
138 profile_count n_p_conditions = profile_count::zero ();
f8bf9252 139
204b560f 140 basic_block bb;
f8bf9252 141
04a90bec 142 FOR_ALL_BB_FN (bb, cfun)
f8bf9252 143 {
204b560f
SP
144 gimple_stmt_iterator psi;
145 loop_p loop = bb->loop_father;
f8bf9252 146
d37fc3aa 147 if (!bb_in_sese_p (bb, scop->scop_info->region))
204b560f 148 continue;
f8bf9252 149
204b560f 150 n_bbs++;
3995f3a2
JH
151 if (bb->count.initialized_p ())
152 n_p_bbs += bb->count;
f8bf9252 153
d630245f 154 if (EDGE_COUNT (bb->succs) > 1)
f8bf9252 155 {
204b560f
SP
156 n_conditions++;
157 n_p_conditions += bb->count;
f8bf9252 158 }
f8bf9252 159
204b560f 160 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
f8bf9252 161 {
204b560f
SP
162 n_stmts++;
163 n_p_stmts += bb->count;
f8bf9252 164 }
f8bf9252 165
d37fc3aa 166 if (loop->header == bb && loop_in_sese_p (loop, scop->scop_info->region))
204b560f
SP
167 {
168 n_loops++;
169 n_p_loops += bb->count;
170 }
171 }
6a114766 172
7009b073
SP
173 fprintf (file, "\nFunction Name: %s\n", current_function_name ());
174
d37fc3aa
AK
175 edge scop_begin = scop->scop_info->region.entry;
176 edge scop_end = scop->scop_info->region.exit;
7009b073
SP
177
178 fprintf (file, "\nSCoP (entry_edge (bb_%d, bb_%d), ",
179 scop_begin->src->index, scop_begin->dest->index);
180 fprintf (file, "exit_edge (bb_%d, bb_%d))",
181 scop_end->src->index, scop_end->dest->index);
182
204b560f
SP
183 fprintf (file, "\nSCoP statistics (");
184 fprintf (file, "BBS:%ld, ", n_bbs);
185 fprintf (file, "LOOPS:%ld, ", n_loops);
186 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
187 fprintf (file, "STMTS:%ld)\n", n_stmts);
c46bd472 188 fprintf (file, "SCoP profiling statistics (");
3995f3a2
JH
189 fprintf (file, "BBS:");
190 n_p_bbs.dump (file);
191 fprintf (file, ", LOOPS:");
192 n_p_loops.dump (file);
193 fprintf (file, ", CONDITIONS:");
194 n_p_conditions.dump (file);
195 fprintf (file, ", STMTS:");
196 n_p_stmts.dump (file);
c46bd472 197 fprintf (file, ")\n\n");
f8bf9252
SP
198}
199
204b560f 200/* Print statistics for SCOPS to FILE. */
f8bf9252 201
204b560f 202static void
9771b263 203print_graphite_statistics (FILE* file, vec<scop_p> scops)
f8bf9252 204{
f8bf9252 205 int i;
204b560f 206 scop_p scop;
f8bf9252 207
9771b263 208 FOR_EACH_VEC_ELT (scops, i, scop)
204b560f 209 print_graphite_scop_statistics (file, scop);
f8bf9252
SP
210}
211
124f4f57
RB
212struct seir_cache_key
213{
214 hashval_t hash;
215 int entry_dest;
216 int exit_src;
217 int loop_num;
218 tree expr;
219};
220
221struct sese_scev_hash : typed_noop_remove <seir_cache_key>
222{
223 typedef seir_cache_key value_type;
224 typedef seir_cache_key compare_type;
225 static hashval_t hash (const seir_cache_key &key) { return key.hash; }
226 static bool
227 equal (const seir_cache_key &key1, const seir_cache_key &key2)
228 {
229 return (key1.hash == key2.hash
230 && key1.entry_dest == key2.entry_dest
231 && key1.exit_src == key2.exit_src
232 && key1.loop_num == key2.loop_num
233 && operand_equal_p (key1.expr, key2.expr, 0));
234 }
235 static void mark_deleted (seir_cache_key &key) { key.expr = NULL_TREE; }
236 static void mark_empty (seir_cache_key &key) { key.entry_dest = 0; }
237 static bool is_deleted (const seir_cache_key &key) { return !key.expr; }
238 static bool is_empty (const seir_cache_key &key) { return key.entry_dest == 0; }
239};
240
241static hash_map<sese_scev_hash, tree> *seir_cache;
242
243/* Same as scalar_evolution_in_region but caches results so we avoid
244 re-computing evolutions during transform phase. */
245
246tree
247cached_scalar_evolution_in_region (const sese_l &region, loop_p loop,
248 tree expr)
249{
250 seir_cache_key key;
251 key.entry_dest = region.entry->dest->index;
252 key.exit_src = region.exit->src->index;
253 key.loop_num = loop->num;
254 key.expr = expr;
255 inchash::hash hstate (0);
256 hstate.add_int (key.entry_dest);
257 hstate.add_int (key.exit_src);
258 hstate.add_int (key.loop_num);
259 inchash::add_expr (key.expr, hstate);
260 key.hash = hstate.end ();
261
262 bool existed;
263 tree &chrec = seir_cache->get_or_insert (key, &existed);
264 if (!existed)
265 chrec = scalar_evolution_in_region (region, loop, expr);
266 return chrec;
267}
268
87ccab5d
AK
269/* Deletes all scops in SCOPS. */
270
271static void
272free_scops (vec<scop_p> scops)
273{
274 int i;
275 scop_p scop;
276
277 FOR_EACH_VEC_ELT (scops, i, scop)
278 free_scop (scop);
279
280 scops.release ();
281}
282
ab0e5308
RB
283/* Transforms LOOP to the canonical loop closed SSA form. */
284
285static void
82c066f5 286canonicalize_loop_closed_ssa (loop_p loop, edge e)
ab0e5308 287{
ab0e5308 288 basic_block bb;
4d6e2f33 289 gphi_iterator psi;
ab0e5308 290
ab0e5308
RB
291 bb = e->dest;
292
4d6e2f33
RB
293 /* Make the loop-close PHI node BB contain only PHIs and have a
294 single predecessor. */
ab0e5308
RB
295 if (single_pred_p (bb))
296 {
297 e = split_block_after_labels (bb);
4d6e2f33 298 bb = e->src;
ab0e5308
RB
299 }
300 else
301 {
ab0e5308
RB
302 basic_block close = split_edge (e);
303 e = single_succ_edge (close);
304 for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
305 {
306 gphi *phi = psi.phi ();
307 use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
308 tree arg = USE_FROM_PTR (use_p);
309
310 /* Only add close phi nodes for SSA_NAMEs defined in LOOP. */
311 if (TREE_CODE (arg) != SSA_NAME
621e5370
RB
312 || SSA_NAME_IS_DEFAULT_DEF (arg)
313 || ! flow_bb_inside_loop_p (loop,
314 gimple_bb (SSA_NAME_DEF_STMT (arg))))
ab0e5308
RB
315 continue;
316
317 tree res = copy_ssa_name (arg);
318 gphi *close_phi = create_phi_node (res, close);
319 add_phi_arg (close_phi, arg, gimple_phi_arg_edge (close_phi, 0),
320 UNKNOWN_LOCATION);
321 SET_USE (use_p, res);
322 }
4d6e2f33
RB
323 bb = close;
324 }
325
326 /* Eliminate duplicates. This relies on processing loops from
327 innermost to outer. */
328 for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
329 {
330 gphi_iterator gsi = psi;
331 gphi *phi = psi.phi ();
332
333 /* At this point, PHI should be a close phi in normal form. */
334 gcc_assert (gimple_phi_num_args (phi) == 1);
ab0e5308 335
4d6e2f33
RB
336 /* Iterate over the next phis and remove duplicates. */
337 gsi_next (&gsi);
338 while (!gsi_end_p (gsi))
339 if (gimple_phi_arg_def (phi, 0) == gimple_phi_arg_def (gsi.phi (), 0))
340 {
341 replace_uses_by (gimple_phi_result (gsi.phi ()),
342 gimple_phi_result (phi));
343 remove_phi_node (&gsi, true);
344 }
345 else
346 gsi_next (&gsi);
ab0e5308
RB
347 }
348}
349
350/* Converts the current loop closed SSA form to a canonical form
351 expected by the Graphite code generation.
352
353 The loop closed SSA form has the following invariant: a variable
354 defined in a loop that is used outside the loop appears only in the
355 phi nodes in the destination of the loop exit. These phi nodes are
356 called close phi nodes.
357
358 The canonical loop closed SSA form contains the extra invariants:
359
360 - when the loop contains only one exit, the close phi nodes contain
361 only one argument. That implies that the basic block that contains
362 the close phi nodes has only one predecessor, that is a basic block
363 in the loop.
364
365 - the basic block containing the close phi nodes does not contain
366 other statements.
367
368 - there exist only one phi node per definition in the loop.
82c066f5
RB
369
370 In addition to that we also make sure that loop exit edges are
371 first in the successor edge vector. This is to make RPO order
372 as computed by pre_and_rev_post_order_compute be consistent with
373 what initial schedule generation expects.
ab0e5308
RB
374*/
375
376static void
82c066f5 377canonicalize_loop_form (void)
ab0e5308
RB
378{
379 loop_p loop;
4d6e2f33 380 FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
82c066f5
RB
381 {
382 edge e = single_exit (loop);
b0bd3e52 383 if (!e || (e->flags & (EDGE_COMPLEX|EDGE_FAKE)))
82c066f5
RB
384 continue;
385
386 canonicalize_loop_closed_ssa (loop, e);
387
388 /* If the exit is not first in the edge vector make it so. */
389 if (e != EDGE_SUCC (e->src, 0))
390 {
391 unsigned ei;
392 for (ei = 0; EDGE_SUCC (e->src, ei) != e; ++ei)
393 ;
394 std::swap (EDGE_SUCC (e->src, ei), EDGE_SUCC (e->src, 0));
395 }
396 }
ab0e5308 397
b33086c0
RB
398 /* We can end up releasing duplicate exit PHIs and also introduce
399 additional copies so the cached information isn't correct anymore. */
400 scev_reset ();
401
ab0e5308
RB
402 checking_verify_loop_closed_ssa (true);
403}
404
33ad93b9
RG
405isl_ctx *the_isl_ctx;
406
f8bf9252
SP
407/* Perform a set of linear transforms on the loops of the current
408 function. */
409
410void
411graphite_transform_loops (void)
412{
413 int i;
414 scop_p scop;
6fe00fb7 415 bool changed = false;
6e1aa848 416 vec<scop_p> scops = vNULL;
33ad93b9 417 isl_ctx *ctx;
f8bf9252 418
62e0a1ed
RG
419 /* If a function is parallel it was most probably already run through graphite
420 once. No need to run again. */
421 if (parallelized_function_p (cfun->decl))
422 return;
423
6fe00fb7 424 calculate_dominance_info (CDI_DOMINATORS);
f8bf9252 425
b25f84d0
RB
426 /* We rely on post-dominators during merging of SESE regions so those
427 have to be meaningful. */
428 connect_infinite_loops_to_exit ();
429
ab0e5308
RB
430 ctx = isl_ctx_alloc ();
431 isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
33ad93b9 432 the_isl_ctx = ctx;
ab0e5308 433
26993e95 434 sort_sibling_loops (cfun);
82c066f5 435 canonicalize_loop_form ();
ab0e5308 436
c46bd472
RB
437 /* Print the loop structure. */
438 if (dump_file && (dump_flags & TDF_DETAILS))
439 {
440 print_loops (dump_file, 2);
441 print_loops (dump_file, 3);
442 }
443
124f4f57
RB
444 seir_cache = new hash_map<sese_scev_hash, tree>;
445
ab0e5308 446 calculate_dominance_info (CDI_POST_DOMINATORS);
204b560f 447 build_scops (&scops);
ab0e5308 448 free_dominance_info (CDI_POST_DOMINATORS);
f8bf9252 449
b25f84d0
RB
450 /* Remove the fake exits before transform given they are not reflected
451 in loop structures we end up verifying. */
452 remove_fake_exit_edges ();
453
f8bf9252 454 if (dump_file && (dump_flags & TDF_DETAILS))
f8bf9252 455 {
204b560f
SP
456 print_graphite_statistics (dump_file, scops);
457 print_global_statistics (dump_file);
458 }
0b040072 459
9771b263 460 FOR_EACH_VEC_ELT (scops, i, scop)
6a7441f5
SP
461 if (dbg_cnt (graphite_scop))
462 {
8e4dc590 463 scop->isl_context = ctx;
36f40be0
AK
464 if (!build_poly_scop (scop))
465 continue;
466
467 if (!apply_poly_transforms (scop))
468 continue;
469
6fe00fb7 470 changed = true;
bbeeac91
DM
471 if (graphite_regenerate_ast_isl (scop)
472 && dump_enabled_p ())
e33507e3 473 {
4f5b9c80 474 dump_user_location_t loc = find_loop_location
e33507e3
RB
475 (scops[i]->scop_info->region.entry->dest->loop_father);
476 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
477 "loop nest optimized\n");
478 }
efa21390 479 }
f8bf9252 480
124f4f57
RB
481 delete seir_cache;
482 seir_cache = NULL;
483
6fe00fb7
RB
484 if (changed)
485 {
486 mark_virtual_operands_for_renaming (cfun);
487 update_ssa (TODO_update_ssa);
488 checking_verify_ssa (true, true);
489 rewrite_into_loop_closed_ssa (NULL, 0);
490 scev_reset ();
491 checking_verify_loop_structure ();
492 }
493
4d6e2f33
RB
494 if (dump_file && (dump_flags & TDF_DETAILS))
495 {
496 loop_p loop;
497 int num_no_dependency = 0;
498
499 FOR_EACH_LOOP (loop, 0)
500 if (loop->can_be_parallel)
501 num_no_dependency++;
502
503 fprintf (dump_file, "%d loops carried no dependency.\n",
504 num_no_dependency);
505 }
506
204b560f 507 free_scops (scops);
33ad93b9
RG
508 the_isl_ctx = NULL;
509 isl_ctx_free (ctx);
6fe00fb7
RB
510
511 if (changed)
512 {
513 cleanup_tree_cfg ();
514 profile_status_for_fn (cfun) = PROFILE_ABSENT;
515 release_recorded_exits (cfun);
516 tree_estimate_probability (false);
517 }
f8bf9252
SP
518}
519
e357a5e0 520#else /* If isl is not available: #ifndef HAVE_isl. */
f8bf9252 521
c1bf2a39 522static void
f8bf9252
SP
523graphite_transform_loops (void)
524{
e357a5e0 525 sorry ("Graphite loop optimizations cannot be used (isl is not available).");
f8bf9252
SP
526}
527
528#endif
c1bf2a39
AM
529
530
531static unsigned int
726338f4 532graphite_transforms (struct function *fun)
c1bf2a39 533{
726338f4 534 if (number_of_loops (fun) <= 1)
c1bf2a39
AM
535 return 0;
536
537 graphite_transform_loops ();
538
539 return 0;
540}
541
542static bool
543gate_graphite_transforms (void)
544{
545 /* Enable -fgraphite pass if any one of the graphite optimization flags
546 is turned on. */
d6bb5ccf 547 if (flag_graphite_identity
c1bf2a39 548 || flag_loop_parallelize_all
84c36240 549 || flag_loop_nest_optimize)
c1bf2a39
AM
550 flag_graphite = 1;
551
552 return flag_graphite != 0;
553}
554
17795822
TS
555namespace {
556
557const pass_data pass_data_graphite =
c1bf2a39
AM
558{
559 GIMPLE_PASS, /* type */
560 "graphite0", /* name */
561 OPTGROUP_LOOP, /* optinfo_flags */
c1bf2a39
AM
562 TV_GRAPHITE, /* tv_id */
563 ( PROP_cfg | PROP_ssa ), /* properties_required */
564 0, /* properties_provided */
565 0, /* properties_destroyed */
566 0, /* todo_flags_start */
567 0, /* todo_flags_finish */
568};
569
17795822 570class pass_graphite : public gimple_opt_pass
c1bf2a39
AM
571{
572public:
573 pass_graphite (gcc::context *ctxt)
574 : gimple_opt_pass (pass_data_graphite, ctxt)
575 {}
576
577 /* opt_pass methods: */
1a3d085c 578 virtual bool gate (function *) { return gate_graphite_transforms (); }
c1bf2a39
AM
579
580}; // class pass_graphite
581
17795822
TS
582} // anon namespace
583
c1bf2a39
AM
584gimple_opt_pass *
585make_pass_graphite (gcc::context *ctxt)
586{
587 return new pass_graphite (ctxt);
588}
589
17795822
TS
590namespace {
591
592const pass_data pass_data_graphite_transforms =
c1bf2a39
AM
593{
594 GIMPLE_PASS, /* type */
595 "graphite", /* name */
596 OPTGROUP_LOOP, /* optinfo_flags */
c1bf2a39
AM
597 TV_GRAPHITE_TRANSFORMS, /* tv_id */
598 ( PROP_cfg | PROP_ssa ), /* properties_required */
599 0, /* properties_provided */
600 0, /* properties_destroyed */
601 0, /* todo_flags_start */
602 0, /* todo_flags_finish */
603};
604
17795822 605class pass_graphite_transforms : public gimple_opt_pass
c1bf2a39
AM
606{
607public:
608 pass_graphite_transforms (gcc::context *ctxt)
609 : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
610 {}
611
612 /* opt_pass methods: */
1a3d085c 613 virtual bool gate (function *) { return gate_graphite_transforms (); }
726338f4 614 virtual unsigned int execute (function *fun) { return graphite_transforms (fun); }
c1bf2a39
AM
615
616}; // class pass_graphite_transforms
617
17795822
TS
618} // anon namespace
619
c1bf2a39
AM
620gimple_opt_pass *
621make_pass_graphite_transforms (gcc::context *ctxt)
622{
623 return new pass_graphite_transforms (ctxt);
624}
625
626