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 ®ion, 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