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