xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/graphite.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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 &region, 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