11debfc3dSmrg /* Gimple Represented as Polyhedra.
2*8feb0f0bSmrg Copyright (C) 2006-2020 Free Software Foundation, Inc.
31debfc3dSmrg Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
41debfc3dSmrg
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify
81debfc3dSmrg it under the terms of the GNU General Public License as published by
91debfc3dSmrg the Free Software Foundation; either version 3, or (at your option)
101debfc3dSmrg any later version.
111debfc3dSmrg
121debfc3dSmrg GCC is distributed in the hope that it will be useful,
131debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
141debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151debfc3dSmrg GNU General Public License for more details.
161debfc3dSmrg
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3. If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>. */
201debfc3dSmrg
211debfc3dSmrg /* This pass converts GIMPLE to GRAPHITE, performs some loop
221debfc3dSmrg transformations and then converts the resulting representation back
231debfc3dSmrg to GIMPLE.
241debfc3dSmrg
251debfc3dSmrg An early description of this pass can be found in the GCC Summit'06
261debfc3dSmrg paper "GRAPHITE: Polyhedral Analyses and Optimizations for GCC".
271debfc3dSmrg The wiki page http://gcc.gnu.org/wiki/Graphite contains pointers to
281debfc3dSmrg the related work. */
291debfc3dSmrg
301debfc3dSmrg #define USES_ISL
311debfc3dSmrg
321debfc3dSmrg #include "config.h"
331debfc3dSmrg #include "system.h"
341debfc3dSmrg #include "coretypes.h"
351debfc3dSmrg #include "backend.h"
361debfc3dSmrg #include "diagnostic-core.h"
371debfc3dSmrg #include "cfgloop.h"
381debfc3dSmrg #include "tree-pass.h"
391debfc3dSmrg #include "pretty-print.h"
40a2dc1f3fSmrg #include "cfganal.h"
411debfc3dSmrg
421debfc3dSmrg #ifdef HAVE_isl
431debfc3dSmrg #include "cfghooks.h"
441debfc3dSmrg #include "tree.h"
451debfc3dSmrg #include "gimple.h"
46a2dc1f3fSmrg #include "ssa.h"
471debfc3dSmrg #include "fold-const.h"
481debfc3dSmrg #include "gimple-iterator.h"
491debfc3dSmrg #include "tree-cfg.h"
501debfc3dSmrg #include "tree-ssa-loop.h"
511debfc3dSmrg #include "tree-data-ref.h"
521debfc3dSmrg #include "tree-scalar-evolution.h"
531debfc3dSmrg #include "dbgcnt.h"
541debfc3dSmrg #include "tree-parloops.h"
551debfc3dSmrg #include "tree-cfgcleanup.h"
561debfc3dSmrg #include "tree-vectorizer.h"
57a2dc1f3fSmrg #include "tree-ssa-loop-manip.h"
58a2dc1f3fSmrg #include "tree-ssa.h"
59a2dc1f3fSmrg #include "tree-into-ssa.h"
601debfc3dSmrg #include "graphite.h"
611debfc3dSmrg
621debfc3dSmrg /* Print global statistics to FILE. */
631debfc3dSmrg
641debfc3dSmrg static void
print_global_statistics(FILE * file)651debfc3dSmrg print_global_statistics (FILE* file)
661debfc3dSmrg {
671debfc3dSmrg long n_bbs = 0;
681debfc3dSmrg long n_loops = 0;
691debfc3dSmrg long n_stmts = 0;
701debfc3dSmrg long n_conditions = 0;
71a2dc1f3fSmrg profile_count n_p_bbs = profile_count::zero ();
72a2dc1f3fSmrg profile_count n_p_loops = profile_count::zero ();
73a2dc1f3fSmrg profile_count n_p_stmts = profile_count::zero ();
74a2dc1f3fSmrg profile_count n_p_conditions = profile_count::zero ();
751debfc3dSmrg
761debfc3dSmrg basic_block bb;
771debfc3dSmrg
781debfc3dSmrg FOR_ALL_BB_FN (bb, cfun)
791debfc3dSmrg {
801debfc3dSmrg gimple_stmt_iterator psi;
811debfc3dSmrg
821debfc3dSmrg n_bbs++;
83a2dc1f3fSmrg if (bb->count.initialized_p ())
841debfc3dSmrg n_p_bbs += bb->count;
851debfc3dSmrg
861debfc3dSmrg /* Ignore artificial surrounding loop. */
871debfc3dSmrg if (bb == bb->loop_father->header
881debfc3dSmrg && bb->index != 0)
891debfc3dSmrg {
901debfc3dSmrg n_loops++;
911debfc3dSmrg n_p_loops += bb->count;
921debfc3dSmrg }
931debfc3dSmrg
941debfc3dSmrg if (EDGE_COUNT (bb->succs) > 1)
951debfc3dSmrg {
961debfc3dSmrg n_conditions++;
97a2dc1f3fSmrg if (bb->count.initialized_p ())
981debfc3dSmrg n_p_conditions += bb->count;
991debfc3dSmrg }
1001debfc3dSmrg
1011debfc3dSmrg for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
1021debfc3dSmrg {
1031debfc3dSmrg n_stmts++;
104a2dc1f3fSmrg if (bb->count.initialized_p ())
1051debfc3dSmrg n_p_stmts += bb->count;
1061debfc3dSmrg }
1071debfc3dSmrg }
1081debfc3dSmrg
1091debfc3dSmrg fprintf (file, "\nGlobal statistics (");
1101debfc3dSmrg fprintf (file, "BBS:%ld, ", n_bbs);
1111debfc3dSmrg fprintf (file, "LOOPS:%ld, ", n_loops);
1121debfc3dSmrg fprintf (file, "CONDITIONS:%ld, ", n_conditions);
1131debfc3dSmrg fprintf (file, "STMTS:%ld)\n", n_stmts);
114a2dc1f3fSmrg fprintf (file, "Global profiling statistics (");
115a2dc1f3fSmrg fprintf (file, "BBS:");
116a2dc1f3fSmrg n_p_bbs.dump (file);
117a2dc1f3fSmrg fprintf (file, ", LOOPS:");
118a2dc1f3fSmrg n_p_loops.dump (file);
119a2dc1f3fSmrg fprintf (file, ", CONDITIONS:");
120a2dc1f3fSmrg n_p_conditions.dump (file);
121a2dc1f3fSmrg fprintf (file, ", STMTS:");
122a2dc1f3fSmrg n_p_stmts.dump (file);
123a2dc1f3fSmrg fprintf (file, ")\n\n");
1241debfc3dSmrg }
1251debfc3dSmrg
1261debfc3dSmrg /* Print statistics for SCOP to FILE. */
1271debfc3dSmrg
1281debfc3dSmrg static void
print_graphite_scop_statistics(FILE * file,scop_p scop)1291debfc3dSmrg print_graphite_scop_statistics (FILE* file, scop_p scop)
1301debfc3dSmrg {
1311debfc3dSmrg long n_bbs = 0;
1321debfc3dSmrg long n_loops = 0;
1331debfc3dSmrg long n_stmts = 0;
1341debfc3dSmrg long n_conditions = 0;
135a2dc1f3fSmrg profile_count n_p_bbs = profile_count::zero ();
136a2dc1f3fSmrg profile_count n_p_loops = profile_count::zero ();
137a2dc1f3fSmrg profile_count n_p_stmts = profile_count::zero ();
138a2dc1f3fSmrg profile_count n_p_conditions = profile_count::zero ();
1391debfc3dSmrg
1401debfc3dSmrg basic_block bb;
1411debfc3dSmrg
1421debfc3dSmrg FOR_ALL_BB_FN (bb, cfun)
1431debfc3dSmrg {
1441debfc3dSmrg gimple_stmt_iterator psi;
1451debfc3dSmrg loop_p loop = bb->loop_father;
1461debfc3dSmrg
1471debfc3dSmrg if (!bb_in_sese_p (bb, scop->scop_info->region))
1481debfc3dSmrg continue;
1491debfc3dSmrg
1501debfc3dSmrg n_bbs++;
151a2dc1f3fSmrg if (bb->count.initialized_p ())
1521debfc3dSmrg n_p_bbs += bb->count;
1531debfc3dSmrg
1541debfc3dSmrg if (EDGE_COUNT (bb->succs) > 1)
1551debfc3dSmrg {
1561debfc3dSmrg n_conditions++;
1571debfc3dSmrg n_p_conditions += bb->count;
1581debfc3dSmrg }
1591debfc3dSmrg
1601debfc3dSmrg for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
1611debfc3dSmrg {
1621debfc3dSmrg n_stmts++;
1631debfc3dSmrg n_p_stmts += bb->count;
1641debfc3dSmrg }
1651debfc3dSmrg
1661debfc3dSmrg if (loop->header == bb && loop_in_sese_p (loop, scop->scop_info->region))
1671debfc3dSmrg {
1681debfc3dSmrg n_loops++;
1691debfc3dSmrg n_p_loops += bb->count;
1701debfc3dSmrg }
1711debfc3dSmrg }
1721debfc3dSmrg
1731debfc3dSmrg fprintf (file, "\nFunction Name: %s\n", current_function_name ());
1741debfc3dSmrg
1751debfc3dSmrg edge scop_begin = scop->scop_info->region.entry;
1761debfc3dSmrg edge scop_end = scop->scop_info->region.exit;
1771debfc3dSmrg
1781debfc3dSmrg fprintf (file, "\nSCoP (entry_edge (bb_%d, bb_%d), ",
1791debfc3dSmrg scop_begin->src->index, scop_begin->dest->index);
1801debfc3dSmrg fprintf (file, "exit_edge (bb_%d, bb_%d))",
1811debfc3dSmrg scop_end->src->index, scop_end->dest->index);
1821debfc3dSmrg
1831debfc3dSmrg fprintf (file, "\nSCoP statistics (");
1841debfc3dSmrg fprintf (file, "BBS:%ld, ", n_bbs);
1851debfc3dSmrg fprintf (file, "LOOPS:%ld, ", n_loops);
1861debfc3dSmrg fprintf (file, "CONDITIONS:%ld, ", n_conditions);
1871debfc3dSmrg fprintf (file, "STMTS:%ld)\n", n_stmts);
188a2dc1f3fSmrg fprintf (file, "SCoP profiling statistics (");
189a2dc1f3fSmrg fprintf (file, "BBS:");
190a2dc1f3fSmrg n_p_bbs.dump (file);
191a2dc1f3fSmrg fprintf (file, ", LOOPS:");
192a2dc1f3fSmrg n_p_loops.dump (file);
193a2dc1f3fSmrg fprintf (file, ", CONDITIONS:");
194a2dc1f3fSmrg n_p_conditions.dump (file);
195a2dc1f3fSmrg fprintf (file, ", STMTS:");
196a2dc1f3fSmrg n_p_stmts.dump (file);
197a2dc1f3fSmrg fprintf (file, ")\n\n");
1981debfc3dSmrg }
1991debfc3dSmrg
2001debfc3dSmrg /* Print statistics for SCOPS to FILE. */
2011debfc3dSmrg
2021debfc3dSmrg static void
print_graphite_statistics(FILE * file,vec<scop_p> scops)2031debfc3dSmrg print_graphite_statistics (FILE* file, vec<scop_p> scops)
2041debfc3dSmrg {
2051debfc3dSmrg int i;
2061debfc3dSmrg scop_p scop;
2071debfc3dSmrg
2081debfc3dSmrg FOR_EACH_VEC_ELT (scops, i, scop)
2091debfc3dSmrg print_graphite_scop_statistics (file, scop);
2101debfc3dSmrg }
2111debfc3dSmrg
212c0a68be4Smrg struct seir_cache_key
213c0a68be4Smrg {
214c0a68be4Smrg hashval_t hash;
215c0a68be4Smrg int entry_dest;
216c0a68be4Smrg int exit_src;
217c0a68be4Smrg int loop_num;
218c0a68be4Smrg tree expr;
219c0a68be4Smrg };
220c0a68be4Smrg
221c0a68be4Smrg struct sese_scev_hash : typed_noop_remove <seir_cache_key>
222c0a68be4Smrg {
223c0a68be4Smrg typedef seir_cache_key value_type;
224c0a68be4Smrg typedef seir_cache_key compare_type;
hashsese_scev_hash225c0a68be4Smrg static hashval_t hash (const seir_cache_key &key) { return key.hash; }
226c0a68be4Smrg static bool
equalsese_scev_hash227c0a68be4Smrg equal (const seir_cache_key &key1, const seir_cache_key &key2)
228c0a68be4Smrg {
229c0a68be4Smrg return (key1.hash == key2.hash
230c0a68be4Smrg && key1.entry_dest == key2.entry_dest
231c0a68be4Smrg && key1.exit_src == key2.exit_src
232c0a68be4Smrg && key1.loop_num == key2.loop_num
233c0a68be4Smrg && operand_equal_p (key1.expr, key2.expr, 0));
234c0a68be4Smrg }
mark_deletedsese_scev_hash235c0a68be4Smrg static void mark_deleted (seir_cache_key &key) { key.expr = NULL_TREE; }
236*8feb0f0bSmrg static const bool empty_zero_p = false;
mark_emptysese_scev_hash237c0a68be4Smrg static void mark_empty (seir_cache_key &key) { key.entry_dest = 0; }
is_deletedsese_scev_hash238c0a68be4Smrg static bool is_deleted (const seir_cache_key &key) { return !key.expr; }
is_emptysese_scev_hash239c0a68be4Smrg static bool is_empty (const seir_cache_key &key) { return key.entry_dest == 0; }
240c0a68be4Smrg };
241c0a68be4Smrg
242c0a68be4Smrg static hash_map<sese_scev_hash, tree> *seir_cache;
243c0a68be4Smrg
244c0a68be4Smrg /* Same as scalar_evolution_in_region but caches results so we avoid
245c0a68be4Smrg re-computing evolutions during transform phase. */
246c0a68be4Smrg
247c0a68be4Smrg tree
cached_scalar_evolution_in_region(const sese_l & region,loop_p loop,tree expr)248c0a68be4Smrg cached_scalar_evolution_in_region (const sese_l ®ion, loop_p loop,
249c0a68be4Smrg tree expr)
250c0a68be4Smrg {
251c0a68be4Smrg seir_cache_key key;
252c0a68be4Smrg key.entry_dest = region.entry->dest->index;
253c0a68be4Smrg key.exit_src = region.exit->src->index;
254c0a68be4Smrg key.loop_num = loop->num;
255c0a68be4Smrg key.expr = expr;
256c0a68be4Smrg inchash::hash hstate (0);
257c0a68be4Smrg hstate.add_int (key.entry_dest);
258c0a68be4Smrg hstate.add_int (key.exit_src);
259c0a68be4Smrg hstate.add_int (key.loop_num);
260c0a68be4Smrg inchash::add_expr (key.expr, hstate);
261c0a68be4Smrg key.hash = hstate.end ();
262c0a68be4Smrg
263c0a68be4Smrg bool existed;
264c0a68be4Smrg tree &chrec = seir_cache->get_or_insert (key, &existed);
265c0a68be4Smrg if (!existed)
266c0a68be4Smrg chrec = scalar_evolution_in_region (region, loop, expr);
267c0a68be4Smrg return chrec;
268c0a68be4Smrg }
269c0a68be4Smrg
2701debfc3dSmrg /* Deletes all scops in SCOPS. */
2711debfc3dSmrg
2721debfc3dSmrg static void
free_scops(vec<scop_p> scops)2731debfc3dSmrg free_scops (vec<scop_p> scops)
2741debfc3dSmrg {
2751debfc3dSmrg int i;
2761debfc3dSmrg scop_p scop;
2771debfc3dSmrg
2781debfc3dSmrg FOR_EACH_VEC_ELT (scops, i, scop)
2791debfc3dSmrg free_scop (scop);
2801debfc3dSmrg
2811debfc3dSmrg scops.release ();
2821debfc3dSmrg }
2831debfc3dSmrg
284a2dc1f3fSmrg /* Transforms LOOP to the canonical loop closed SSA form. */
285a2dc1f3fSmrg
286a2dc1f3fSmrg static void
canonicalize_loop_closed_ssa(loop_p loop,edge e)287a2dc1f3fSmrg canonicalize_loop_closed_ssa (loop_p loop, edge e)
288a2dc1f3fSmrg {
289a2dc1f3fSmrg basic_block bb;
290a2dc1f3fSmrg gphi_iterator psi;
291a2dc1f3fSmrg
292a2dc1f3fSmrg bb = e->dest;
293a2dc1f3fSmrg
294a2dc1f3fSmrg /* Make the loop-close PHI node BB contain only PHIs and have a
295a2dc1f3fSmrg single predecessor. */
296a2dc1f3fSmrg if (single_pred_p (bb))
297a2dc1f3fSmrg {
298a2dc1f3fSmrg e = split_block_after_labels (bb);
299a2dc1f3fSmrg bb = e->src;
300a2dc1f3fSmrg }
301a2dc1f3fSmrg else
302a2dc1f3fSmrg {
303a2dc1f3fSmrg basic_block close = split_edge (e);
304a2dc1f3fSmrg e = single_succ_edge (close);
305a2dc1f3fSmrg for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
306a2dc1f3fSmrg {
307a2dc1f3fSmrg gphi *phi = psi.phi ();
308a2dc1f3fSmrg use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
309a2dc1f3fSmrg tree arg = USE_FROM_PTR (use_p);
310a2dc1f3fSmrg
311a2dc1f3fSmrg /* Only add close phi nodes for SSA_NAMEs defined in LOOP. */
312a2dc1f3fSmrg if (TREE_CODE (arg) != SSA_NAME
313a2dc1f3fSmrg || SSA_NAME_IS_DEFAULT_DEF (arg)
314a2dc1f3fSmrg || ! flow_bb_inside_loop_p (loop,
315a2dc1f3fSmrg gimple_bb (SSA_NAME_DEF_STMT (arg))))
316a2dc1f3fSmrg continue;
317a2dc1f3fSmrg
318a2dc1f3fSmrg tree res = copy_ssa_name (arg);
319a2dc1f3fSmrg gphi *close_phi = create_phi_node (res, close);
320a2dc1f3fSmrg add_phi_arg (close_phi, arg, gimple_phi_arg_edge (close_phi, 0),
321a2dc1f3fSmrg UNKNOWN_LOCATION);
322a2dc1f3fSmrg SET_USE (use_p, res);
323a2dc1f3fSmrg }
324a2dc1f3fSmrg bb = close;
325a2dc1f3fSmrg }
326a2dc1f3fSmrg
327a2dc1f3fSmrg /* Eliminate duplicates. This relies on processing loops from
328a2dc1f3fSmrg innermost to outer. */
329a2dc1f3fSmrg for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
330a2dc1f3fSmrg {
331a2dc1f3fSmrg gphi_iterator gsi = psi;
332a2dc1f3fSmrg gphi *phi = psi.phi ();
333a2dc1f3fSmrg
334a2dc1f3fSmrg /* At this point, PHI should be a close phi in normal form. */
335a2dc1f3fSmrg gcc_assert (gimple_phi_num_args (phi) == 1);
336a2dc1f3fSmrg
337a2dc1f3fSmrg /* Iterate over the next phis and remove duplicates. */
338a2dc1f3fSmrg gsi_next (&gsi);
339a2dc1f3fSmrg while (!gsi_end_p (gsi))
340a2dc1f3fSmrg if (gimple_phi_arg_def (phi, 0) == gimple_phi_arg_def (gsi.phi (), 0))
341a2dc1f3fSmrg {
342a2dc1f3fSmrg replace_uses_by (gimple_phi_result (gsi.phi ()),
343a2dc1f3fSmrg gimple_phi_result (phi));
344a2dc1f3fSmrg remove_phi_node (&gsi, true);
345a2dc1f3fSmrg }
346a2dc1f3fSmrg else
347a2dc1f3fSmrg gsi_next (&gsi);
348a2dc1f3fSmrg }
349a2dc1f3fSmrg }
350a2dc1f3fSmrg
351a2dc1f3fSmrg /* Converts the current loop closed SSA form to a canonical form
352a2dc1f3fSmrg expected by the Graphite code generation.
353a2dc1f3fSmrg
354a2dc1f3fSmrg The loop closed SSA form has the following invariant: a variable
355a2dc1f3fSmrg defined in a loop that is used outside the loop appears only in the
356a2dc1f3fSmrg phi nodes in the destination of the loop exit. These phi nodes are
357a2dc1f3fSmrg called close phi nodes.
358a2dc1f3fSmrg
359a2dc1f3fSmrg The canonical loop closed SSA form contains the extra invariants:
360a2dc1f3fSmrg
361a2dc1f3fSmrg - when the loop contains only one exit, the close phi nodes contain
362a2dc1f3fSmrg only one argument. That implies that the basic block that contains
363a2dc1f3fSmrg the close phi nodes has only one predecessor, that is a basic block
364a2dc1f3fSmrg in the loop.
365a2dc1f3fSmrg
366a2dc1f3fSmrg - the basic block containing the close phi nodes does not contain
367a2dc1f3fSmrg other statements.
368a2dc1f3fSmrg
369a2dc1f3fSmrg - there exist only one phi node per definition in the loop.
370a2dc1f3fSmrg
371a2dc1f3fSmrg In addition to that we also make sure that loop exit edges are
372a2dc1f3fSmrg first in the successor edge vector. This is to make RPO order
373a2dc1f3fSmrg as computed by pre_and_rev_post_order_compute be consistent with
374a2dc1f3fSmrg what initial schedule generation expects.
375a2dc1f3fSmrg */
376a2dc1f3fSmrg
377a2dc1f3fSmrg static void
canonicalize_loop_form(void)378a2dc1f3fSmrg canonicalize_loop_form (void)
379a2dc1f3fSmrg {
380a2dc1f3fSmrg loop_p loop;
381a2dc1f3fSmrg FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
382a2dc1f3fSmrg {
383a2dc1f3fSmrg edge e = single_exit (loop);
384a2dc1f3fSmrg if (!e || (e->flags & (EDGE_COMPLEX|EDGE_FAKE)))
385a2dc1f3fSmrg continue;
386a2dc1f3fSmrg
387a2dc1f3fSmrg canonicalize_loop_closed_ssa (loop, e);
388a2dc1f3fSmrg
389a2dc1f3fSmrg /* If the exit is not first in the edge vector make it so. */
390a2dc1f3fSmrg if (e != EDGE_SUCC (e->src, 0))
391a2dc1f3fSmrg {
392a2dc1f3fSmrg unsigned ei;
393a2dc1f3fSmrg for (ei = 0; EDGE_SUCC (e->src, ei) != e; ++ei)
394a2dc1f3fSmrg ;
395a2dc1f3fSmrg std::swap (EDGE_SUCC (e->src, ei), EDGE_SUCC (e->src, 0));
396a2dc1f3fSmrg }
397a2dc1f3fSmrg }
398a2dc1f3fSmrg
399a2dc1f3fSmrg /* We can end up releasing duplicate exit PHIs and also introduce
400a2dc1f3fSmrg additional copies so the cached information isn't correct anymore. */
401a2dc1f3fSmrg scev_reset ();
402a2dc1f3fSmrg
403a2dc1f3fSmrg checking_verify_loop_closed_ssa (true);
404a2dc1f3fSmrg }
405a2dc1f3fSmrg
4061debfc3dSmrg isl_ctx *the_isl_ctx;
4071debfc3dSmrg
4081debfc3dSmrg /* Perform a set of linear transforms on the loops of the current
4091debfc3dSmrg function. */
4101debfc3dSmrg
4111debfc3dSmrg void
graphite_transform_loops(void)4121debfc3dSmrg graphite_transform_loops (void)
4131debfc3dSmrg {
4141debfc3dSmrg int i;
4151debfc3dSmrg scop_p scop;
416a2dc1f3fSmrg bool changed = false;
4171debfc3dSmrg vec<scop_p> scops = vNULL;
4181debfc3dSmrg isl_ctx *ctx;
4191debfc3dSmrg
4201debfc3dSmrg /* If a function is parallel it was most probably already run through graphite
4211debfc3dSmrg once. No need to run again. */
4221debfc3dSmrg if (parallelized_function_p (cfun->decl))
4231debfc3dSmrg return;
4241debfc3dSmrg
425a2dc1f3fSmrg calculate_dominance_info (CDI_DOMINATORS);
426a2dc1f3fSmrg
427a2dc1f3fSmrg /* We rely on post-dominators during merging of SESE regions so those
428a2dc1f3fSmrg have to be meaningful. */
429a2dc1f3fSmrg connect_infinite_loops_to_exit ();
430a2dc1f3fSmrg
4311debfc3dSmrg ctx = isl_ctx_alloc ();
4321debfc3dSmrg isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
4331debfc3dSmrg the_isl_ctx = ctx;
434a2dc1f3fSmrg
435a2dc1f3fSmrg sort_sibling_loops (cfun);
436a2dc1f3fSmrg canonicalize_loop_form ();
437a2dc1f3fSmrg
438a2dc1f3fSmrg /* Print the loop structure. */
439a2dc1f3fSmrg if (dump_file && (dump_flags & TDF_DETAILS))
440a2dc1f3fSmrg {
441a2dc1f3fSmrg print_loops (dump_file, 2);
442a2dc1f3fSmrg print_loops (dump_file, 3);
443a2dc1f3fSmrg }
444a2dc1f3fSmrg
445c0a68be4Smrg seir_cache = new hash_map<sese_scev_hash, tree>;
446c0a68be4Smrg
447a2dc1f3fSmrg calculate_dominance_info (CDI_POST_DOMINATORS);
4481debfc3dSmrg build_scops (&scops);
449a2dc1f3fSmrg free_dominance_info (CDI_POST_DOMINATORS);
450a2dc1f3fSmrg
451a2dc1f3fSmrg /* Remove the fake exits before transform given they are not reflected
452a2dc1f3fSmrg in loop structures we end up verifying. */
453a2dc1f3fSmrg remove_fake_exit_edges ();
4541debfc3dSmrg
4551debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
4561debfc3dSmrg {
4571debfc3dSmrg print_graphite_statistics (dump_file, scops);
4581debfc3dSmrg print_global_statistics (dump_file);
4591debfc3dSmrg }
4601debfc3dSmrg
4611debfc3dSmrg FOR_EACH_VEC_ELT (scops, i, scop)
4621debfc3dSmrg if (dbg_cnt (graphite_scop))
4631debfc3dSmrg {
4641debfc3dSmrg scop->isl_context = ctx;
4651debfc3dSmrg if (!build_poly_scop (scop))
4661debfc3dSmrg continue;
4671debfc3dSmrg
4681debfc3dSmrg if (!apply_poly_transforms (scop))
4691debfc3dSmrg continue;
4701debfc3dSmrg
471a2dc1f3fSmrg changed = true;
472c0a68be4Smrg if (graphite_regenerate_ast_isl (scop)
473c0a68be4Smrg && dump_enabled_p ())
474a2dc1f3fSmrg {
475c0a68be4Smrg dump_user_location_t loc = find_loop_location
476a2dc1f3fSmrg (scops[i]->scop_info->region.entry->dest->loop_father);
4771debfc3dSmrg dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
4781debfc3dSmrg "loop nest optimized\n");
4791debfc3dSmrg }
480a2dc1f3fSmrg }
481a2dc1f3fSmrg
482c0a68be4Smrg delete seir_cache;
483c0a68be4Smrg seir_cache = NULL;
484c0a68be4Smrg
485a2dc1f3fSmrg if (changed)
486a2dc1f3fSmrg {
487a2dc1f3fSmrg mark_virtual_operands_for_renaming (cfun);
488a2dc1f3fSmrg update_ssa (TODO_update_ssa);
489a2dc1f3fSmrg checking_verify_ssa (true, true);
490a2dc1f3fSmrg rewrite_into_loop_closed_ssa (NULL, 0);
491a2dc1f3fSmrg scev_reset ();
492a2dc1f3fSmrg checking_verify_loop_structure ();
493a2dc1f3fSmrg }
494a2dc1f3fSmrg
495a2dc1f3fSmrg if (dump_file && (dump_flags & TDF_DETAILS))
496a2dc1f3fSmrg {
497a2dc1f3fSmrg loop_p loop;
498a2dc1f3fSmrg int num_no_dependency = 0;
499a2dc1f3fSmrg
500a2dc1f3fSmrg FOR_EACH_LOOP (loop, 0)
501a2dc1f3fSmrg if (loop->can_be_parallel)
502a2dc1f3fSmrg num_no_dependency++;
503a2dc1f3fSmrg
504a2dc1f3fSmrg fprintf (dump_file, "%d loops carried no dependency.\n",
505a2dc1f3fSmrg num_no_dependency);
506a2dc1f3fSmrg }
5071debfc3dSmrg
5081debfc3dSmrg free_scops (scops);
5091debfc3dSmrg the_isl_ctx = NULL;
5101debfc3dSmrg isl_ctx_free (ctx);
511a2dc1f3fSmrg
512a2dc1f3fSmrg if (changed)
513a2dc1f3fSmrg {
514a2dc1f3fSmrg cleanup_tree_cfg ();
515a2dc1f3fSmrg profile_status_for_fn (cfun) = PROFILE_ABSENT;
516a2dc1f3fSmrg release_recorded_exits (cfun);
517a2dc1f3fSmrg tree_estimate_probability (false);
518a2dc1f3fSmrg }
5191debfc3dSmrg }
5201debfc3dSmrg
5211debfc3dSmrg #else /* If isl is not available: #ifndef HAVE_isl. */
5221debfc3dSmrg
5231debfc3dSmrg static void
graphite_transform_loops(void)5241debfc3dSmrg graphite_transform_loops (void)
5251debfc3dSmrg {
5261debfc3dSmrg sorry ("Graphite loop optimizations cannot be used (isl is not available).");
5271debfc3dSmrg }
5281debfc3dSmrg
5291debfc3dSmrg #endif
5301debfc3dSmrg
5311debfc3dSmrg
5321debfc3dSmrg static unsigned int
graphite_transforms(struct function * fun)5331debfc3dSmrg graphite_transforms (struct function *fun)
5341debfc3dSmrg {
5351debfc3dSmrg if (number_of_loops (fun) <= 1)
5361debfc3dSmrg return 0;
5371debfc3dSmrg
5381debfc3dSmrg graphite_transform_loops ();
5391debfc3dSmrg
5401debfc3dSmrg return 0;
5411debfc3dSmrg }
5421debfc3dSmrg
5431debfc3dSmrg static bool
gate_graphite_transforms(void)5441debfc3dSmrg gate_graphite_transforms (void)
5451debfc3dSmrg {
5461debfc3dSmrg /* Enable -fgraphite pass if any one of the graphite optimization flags
5471debfc3dSmrg is turned on. */
5481debfc3dSmrg if (flag_graphite_identity
5491debfc3dSmrg || flag_loop_parallelize_all
5501debfc3dSmrg || flag_loop_nest_optimize)
5511debfc3dSmrg flag_graphite = 1;
5521debfc3dSmrg
5531debfc3dSmrg return flag_graphite != 0;
5541debfc3dSmrg }
5551debfc3dSmrg
5561debfc3dSmrg namespace {
5571debfc3dSmrg
5581debfc3dSmrg const pass_data pass_data_graphite =
5591debfc3dSmrg {
5601debfc3dSmrg GIMPLE_PASS, /* type */
5611debfc3dSmrg "graphite0", /* name */
5621debfc3dSmrg OPTGROUP_LOOP, /* optinfo_flags */
5631debfc3dSmrg TV_GRAPHITE, /* tv_id */
5641debfc3dSmrg ( PROP_cfg | PROP_ssa ), /* properties_required */
5651debfc3dSmrg 0, /* properties_provided */
5661debfc3dSmrg 0, /* properties_destroyed */
5671debfc3dSmrg 0, /* todo_flags_start */
5681debfc3dSmrg 0, /* todo_flags_finish */
5691debfc3dSmrg };
5701debfc3dSmrg
5711debfc3dSmrg class pass_graphite : public gimple_opt_pass
5721debfc3dSmrg {
5731debfc3dSmrg public:
pass_graphite(gcc::context * ctxt)5741debfc3dSmrg pass_graphite (gcc::context *ctxt)
5751debfc3dSmrg : gimple_opt_pass (pass_data_graphite, ctxt)
5761debfc3dSmrg {}
5771debfc3dSmrg
5781debfc3dSmrg /* opt_pass methods: */
gate(function *)5791debfc3dSmrg virtual bool gate (function *) { return gate_graphite_transforms (); }
5801debfc3dSmrg
5811debfc3dSmrg }; // class pass_graphite
5821debfc3dSmrg
5831debfc3dSmrg } // anon namespace
5841debfc3dSmrg
5851debfc3dSmrg gimple_opt_pass *
make_pass_graphite(gcc::context * ctxt)5861debfc3dSmrg make_pass_graphite (gcc::context *ctxt)
5871debfc3dSmrg {
5881debfc3dSmrg return new pass_graphite (ctxt);
5891debfc3dSmrg }
5901debfc3dSmrg
5911debfc3dSmrg namespace {
5921debfc3dSmrg
5931debfc3dSmrg const pass_data pass_data_graphite_transforms =
5941debfc3dSmrg {
5951debfc3dSmrg GIMPLE_PASS, /* type */
5961debfc3dSmrg "graphite", /* name */
5971debfc3dSmrg OPTGROUP_LOOP, /* optinfo_flags */
5981debfc3dSmrg TV_GRAPHITE_TRANSFORMS, /* tv_id */
5991debfc3dSmrg ( PROP_cfg | PROP_ssa ), /* properties_required */
6001debfc3dSmrg 0, /* properties_provided */
6011debfc3dSmrg 0, /* properties_destroyed */
6021debfc3dSmrg 0, /* todo_flags_start */
6031debfc3dSmrg 0, /* todo_flags_finish */
6041debfc3dSmrg };
6051debfc3dSmrg
6061debfc3dSmrg class pass_graphite_transforms : public gimple_opt_pass
6071debfc3dSmrg {
6081debfc3dSmrg public:
pass_graphite_transforms(gcc::context * ctxt)6091debfc3dSmrg pass_graphite_transforms (gcc::context *ctxt)
6101debfc3dSmrg : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
6111debfc3dSmrg {}
6121debfc3dSmrg
6131debfc3dSmrg /* opt_pass methods: */
gate(function *)6141debfc3dSmrg virtual bool gate (function *) { return gate_graphite_transforms (); }
execute(function * fun)6151debfc3dSmrg virtual unsigned int execute (function *fun) { return graphite_transforms (fun); }
6161debfc3dSmrg
6171debfc3dSmrg }; // class pass_graphite_transforms
6181debfc3dSmrg
6191debfc3dSmrg } // anon namespace
6201debfc3dSmrg
6211debfc3dSmrg gimple_opt_pass *
make_pass_graphite_transforms(gcc::context * ctxt)6221debfc3dSmrg make_pass_graphite_transforms (gcc::context *ctxt)
6231debfc3dSmrg {
6241debfc3dSmrg return new pass_graphite_transforms (ctxt);
6251debfc3dSmrg }
6261debfc3dSmrg
6271debfc3dSmrg
628