1*e4b17023SJohn Marino /* Detection of Static Control Parts (SCoP) for Graphite.
2*e4b17023SJohn Marino Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3*e4b17023SJohn Marino Contributed by Sebastian Pop <sebastian.pop@amd.com> and
4*e4b17023SJohn Marino Tobias Grosser <grosser@fim.uni-passau.de>.
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
9*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
10*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
11*e4b17023SJohn Marino any later version.
12*e4b17023SJohn Marino
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
14*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*e4b17023SJohn Marino GNU General Public License for more details.
17*e4b17023SJohn Marino
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21*e4b17023SJohn Marino
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tree-flow.h"
26*e4b17023SJohn Marino #include "cfgloop.h"
27*e4b17023SJohn Marino #include "tree-chrec.h"
28*e4b17023SJohn Marino #include "tree-data-ref.h"
29*e4b17023SJohn Marino #include "tree-scalar-evolution.h"
30*e4b17023SJohn Marino #include "tree-pass.h"
31*e4b17023SJohn Marino #include "sese.h"
32*e4b17023SJohn Marino
33*e4b17023SJohn Marino #ifdef HAVE_cloog
34*e4b17023SJohn Marino #include "ppl_c.h"
35*e4b17023SJohn Marino #include "graphite-ppl.h"
36*e4b17023SJohn Marino #include "graphite-poly.h"
37*e4b17023SJohn Marino #include "graphite-scop-detection.h"
38*e4b17023SJohn Marino
39*e4b17023SJohn Marino /* Forward declarations. */
40*e4b17023SJohn Marino static void make_close_phi_nodes_unique (basic_block);
41*e4b17023SJohn Marino
42*e4b17023SJohn Marino /* The type of the analyzed basic block. */
43*e4b17023SJohn Marino
44*e4b17023SJohn Marino typedef enum gbb_type {
45*e4b17023SJohn Marino GBB_UNKNOWN,
46*e4b17023SJohn Marino GBB_LOOP_SING_EXIT_HEADER,
47*e4b17023SJohn Marino GBB_LOOP_MULT_EXIT_HEADER,
48*e4b17023SJohn Marino GBB_LOOP_EXIT,
49*e4b17023SJohn Marino GBB_COND_HEADER,
50*e4b17023SJohn Marino GBB_SIMPLE,
51*e4b17023SJohn Marino GBB_LAST
52*e4b17023SJohn Marino } gbb_type;
53*e4b17023SJohn Marino
54*e4b17023SJohn Marino /* Detect the type of BB. Loop headers are only marked, if they are
55*e4b17023SJohn Marino new. This means their loop_father is different to LAST_LOOP.
56*e4b17023SJohn Marino Otherwise they are treated like any other bb and their type can be
57*e4b17023SJohn Marino any other type. */
58*e4b17023SJohn Marino
59*e4b17023SJohn Marino static gbb_type
get_bb_type(basic_block bb,struct loop * last_loop)60*e4b17023SJohn Marino get_bb_type (basic_block bb, struct loop *last_loop)
61*e4b17023SJohn Marino {
62*e4b17023SJohn Marino VEC (basic_block, heap) *dom;
63*e4b17023SJohn Marino int nb_dom, nb_suc;
64*e4b17023SJohn Marino struct loop *loop = bb->loop_father;
65*e4b17023SJohn Marino
66*e4b17023SJohn Marino /* Check, if we entry into a new loop. */
67*e4b17023SJohn Marino if (loop != last_loop)
68*e4b17023SJohn Marino {
69*e4b17023SJohn Marino if (single_exit (loop) != NULL)
70*e4b17023SJohn Marino return GBB_LOOP_SING_EXIT_HEADER;
71*e4b17023SJohn Marino else if (loop->num != 0)
72*e4b17023SJohn Marino return GBB_LOOP_MULT_EXIT_HEADER;
73*e4b17023SJohn Marino else
74*e4b17023SJohn Marino return GBB_COND_HEADER;
75*e4b17023SJohn Marino }
76*e4b17023SJohn Marino
77*e4b17023SJohn Marino dom = get_dominated_by (CDI_DOMINATORS, bb);
78*e4b17023SJohn Marino nb_dom = VEC_length (basic_block, dom);
79*e4b17023SJohn Marino VEC_free (basic_block, heap, dom);
80*e4b17023SJohn Marino
81*e4b17023SJohn Marino if (nb_dom == 0)
82*e4b17023SJohn Marino return GBB_LAST;
83*e4b17023SJohn Marino
84*e4b17023SJohn Marino nb_suc = VEC_length (edge, bb->succs);
85*e4b17023SJohn Marino
86*e4b17023SJohn Marino if (nb_dom == 1 && nb_suc == 1)
87*e4b17023SJohn Marino return GBB_SIMPLE;
88*e4b17023SJohn Marino
89*e4b17023SJohn Marino return GBB_COND_HEADER;
90*e4b17023SJohn Marino }
91*e4b17023SJohn Marino
92*e4b17023SJohn Marino /* A SCoP detection region, defined using bbs as borders.
93*e4b17023SJohn Marino
94*e4b17023SJohn Marino All control flow touching this region, comes in passing basic_block
95*e4b17023SJohn Marino ENTRY and leaves passing basic_block EXIT. By using bbs instead of
96*e4b17023SJohn Marino edges for the borders we are able to represent also regions that do
97*e4b17023SJohn Marino not have a single entry or exit edge.
98*e4b17023SJohn Marino
99*e4b17023SJohn Marino But as they have a single entry basic_block and a single exit
100*e4b17023SJohn Marino basic_block, we are able to generate for every sd_region a single
101*e4b17023SJohn Marino entry and exit edge.
102*e4b17023SJohn Marino
103*e4b17023SJohn Marino 1 2
104*e4b17023SJohn Marino \ /
105*e4b17023SJohn Marino 3 <- entry
106*e4b17023SJohn Marino |
107*e4b17023SJohn Marino 4
108*e4b17023SJohn Marino / \ This region contains: {3, 4, 5, 6, 7, 8}
109*e4b17023SJohn Marino 5 6
110*e4b17023SJohn Marino | |
111*e4b17023SJohn Marino 7 8
112*e4b17023SJohn Marino \ /
113*e4b17023SJohn Marino 9 <- exit */
114*e4b17023SJohn Marino
115*e4b17023SJohn Marino
116*e4b17023SJohn Marino typedef struct sd_region_p
117*e4b17023SJohn Marino {
118*e4b17023SJohn Marino /* The entry bb dominates all bbs in the sd_region. It is part of
119*e4b17023SJohn Marino the region. */
120*e4b17023SJohn Marino basic_block entry;
121*e4b17023SJohn Marino
122*e4b17023SJohn Marino /* The exit bb postdominates all bbs in the sd_region, but is not
123*e4b17023SJohn Marino part of the region. */
124*e4b17023SJohn Marino basic_block exit;
125*e4b17023SJohn Marino } sd_region;
126*e4b17023SJohn Marino
127*e4b17023SJohn Marino DEF_VEC_O(sd_region);
128*e4b17023SJohn Marino DEF_VEC_ALLOC_O(sd_region, heap);
129*e4b17023SJohn Marino
130*e4b17023SJohn Marino
131*e4b17023SJohn Marino /* Moves the scops from SOURCE to TARGET and clean up SOURCE. */
132*e4b17023SJohn Marino
133*e4b17023SJohn Marino static void
move_sd_regions(VEC (sd_region,heap)** source,VEC (sd_region,heap)** target)134*e4b17023SJohn Marino move_sd_regions (VEC (sd_region, heap) **source,
135*e4b17023SJohn Marino VEC (sd_region, heap) **target)
136*e4b17023SJohn Marino {
137*e4b17023SJohn Marino sd_region *s;
138*e4b17023SJohn Marino int i;
139*e4b17023SJohn Marino
140*e4b17023SJohn Marino FOR_EACH_VEC_ELT (sd_region, *source, i, s)
141*e4b17023SJohn Marino VEC_safe_push (sd_region, heap, *target, s);
142*e4b17023SJohn Marino
143*e4b17023SJohn Marino VEC_free (sd_region, heap, *source);
144*e4b17023SJohn Marino }
145*e4b17023SJohn Marino
146*e4b17023SJohn Marino /* Something like "n * m" is not allowed. */
147*e4b17023SJohn Marino
148*e4b17023SJohn Marino static bool
graphite_can_represent_init(tree e)149*e4b17023SJohn Marino graphite_can_represent_init (tree e)
150*e4b17023SJohn Marino {
151*e4b17023SJohn Marino switch (TREE_CODE (e))
152*e4b17023SJohn Marino {
153*e4b17023SJohn Marino case POLYNOMIAL_CHREC:
154*e4b17023SJohn Marino return graphite_can_represent_init (CHREC_LEFT (e))
155*e4b17023SJohn Marino && graphite_can_represent_init (CHREC_RIGHT (e));
156*e4b17023SJohn Marino
157*e4b17023SJohn Marino case MULT_EXPR:
158*e4b17023SJohn Marino if (chrec_contains_symbols (TREE_OPERAND (e, 0)))
159*e4b17023SJohn Marino return graphite_can_represent_init (TREE_OPERAND (e, 0))
160*e4b17023SJohn Marino && host_integerp (TREE_OPERAND (e, 1), 0);
161*e4b17023SJohn Marino else
162*e4b17023SJohn Marino return graphite_can_represent_init (TREE_OPERAND (e, 1))
163*e4b17023SJohn Marino && host_integerp (TREE_OPERAND (e, 0), 0);
164*e4b17023SJohn Marino
165*e4b17023SJohn Marino case PLUS_EXPR:
166*e4b17023SJohn Marino case POINTER_PLUS_EXPR:
167*e4b17023SJohn Marino case MINUS_EXPR:
168*e4b17023SJohn Marino return graphite_can_represent_init (TREE_OPERAND (e, 0))
169*e4b17023SJohn Marino && graphite_can_represent_init (TREE_OPERAND (e, 1));
170*e4b17023SJohn Marino
171*e4b17023SJohn Marino case NEGATE_EXPR:
172*e4b17023SJohn Marino case BIT_NOT_EXPR:
173*e4b17023SJohn Marino CASE_CONVERT:
174*e4b17023SJohn Marino case NON_LVALUE_EXPR:
175*e4b17023SJohn Marino return graphite_can_represent_init (TREE_OPERAND (e, 0));
176*e4b17023SJohn Marino
177*e4b17023SJohn Marino default:
178*e4b17023SJohn Marino break;
179*e4b17023SJohn Marino }
180*e4b17023SJohn Marino
181*e4b17023SJohn Marino return true;
182*e4b17023SJohn Marino }
183*e4b17023SJohn Marino
184*e4b17023SJohn Marino /* Return true when SCEV can be represented in the polyhedral model.
185*e4b17023SJohn Marino
186*e4b17023SJohn Marino An expression can be represented, if it can be expressed as an
187*e4b17023SJohn Marino affine expression. For loops (i, j) and parameters (m, n) all
188*e4b17023SJohn Marino affine expressions are of the form:
189*e4b17023SJohn Marino
190*e4b17023SJohn Marino x1 * i + x2 * j + x3 * m + x4 * n + x5 * 1 where x1..x5 element of Z
191*e4b17023SJohn Marino
192*e4b17023SJohn Marino 1 i + 20 j + (-2) m + 25
193*e4b17023SJohn Marino
194*e4b17023SJohn Marino Something like "i * n" or "n * m" is not allowed. */
195*e4b17023SJohn Marino
196*e4b17023SJohn Marino static bool
graphite_can_represent_scev(tree scev)197*e4b17023SJohn Marino graphite_can_represent_scev (tree scev)
198*e4b17023SJohn Marino {
199*e4b17023SJohn Marino if (chrec_contains_undetermined (scev))
200*e4b17023SJohn Marino return false;
201*e4b17023SJohn Marino
202*e4b17023SJohn Marino switch (TREE_CODE (scev))
203*e4b17023SJohn Marino {
204*e4b17023SJohn Marino case PLUS_EXPR:
205*e4b17023SJohn Marino case MINUS_EXPR:
206*e4b17023SJohn Marino return graphite_can_represent_scev (TREE_OPERAND (scev, 0))
207*e4b17023SJohn Marino && graphite_can_represent_scev (TREE_OPERAND (scev, 1));
208*e4b17023SJohn Marino
209*e4b17023SJohn Marino case MULT_EXPR:
210*e4b17023SJohn Marino return !CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (scev, 0)))
211*e4b17023SJohn Marino && !CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (scev, 1)))
212*e4b17023SJohn Marino && !(chrec_contains_symbols (TREE_OPERAND (scev, 0))
213*e4b17023SJohn Marino && chrec_contains_symbols (TREE_OPERAND (scev, 1)))
214*e4b17023SJohn Marino && graphite_can_represent_init (scev)
215*e4b17023SJohn Marino && graphite_can_represent_scev (TREE_OPERAND (scev, 0))
216*e4b17023SJohn Marino && graphite_can_represent_scev (TREE_OPERAND (scev, 1));
217*e4b17023SJohn Marino
218*e4b17023SJohn Marino case POLYNOMIAL_CHREC:
219*e4b17023SJohn Marino /* Check for constant strides. With a non constant stride of
220*e4b17023SJohn Marino 'n' we would have a value of 'iv * n'. Also check that the
221*e4b17023SJohn Marino initial value can represented: for example 'n * m' cannot be
222*e4b17023SJohn Marino represented. */
223*e4b17023SJohn Marino if (!evolution_function_right_is_integer_cst (scev)
224*e4b17023SJohn Marino || !graphite_can_represent_init (scev))
225*e4b17023SJohn Marino return false;
226*e4b17023SJohn Marino
227*e4b17023SJohn Marino default:
228*e4b17023SJohn Marino break;
229*e4b17023SJohn Marino }
230*e4b17023SJohn Marino
231*e4b17023SJohn Marino /* Only affine functions can be represented. */
232*e4b17023SJohn Marino if (!scev_is_linear_expression (scev))
233*e4b17023SJohn Marino return false;
234*e4b17023SJohn Marino
235*e4b17023SJohn Marino return true;
236*e4b17023SJohn Marino }
237*e4b17023SJohn Marino
238*e4b17023SJohn Marino
239*e4b17023SJohn Marino /* Return true when EXPR can be represented in the polyhedral model.
240*e4b17023SJohn Marino
241*e4b17023SJohn Marino This means an expression can be represented, if it is linear with
242*e4b17023SJohn Marino respect to the loops and the strides are non parametric.
243*e4b17023SJohn Marino LOOP is the place where the expr will be evaluated. SCOP_ENTRY defines the
244*e4b17023SJohn Marino entry of the region we analyse. */
245*e4b17023SJohn Marino
246*e4b17023SJohn Marino static bool
graphite_can_represent_expr(basic_block scop_entry,loop_p loop,tree expr)247*e4b17023SJohn Marino graphite_can_represent_expr (basic_block scop_entry, loop_p loop,
248*e4b17023SJohn Marino tree expr)
249*e4b17023SJohn Marino {
250*e4b17023SJohn Marino tree scev = analyze_scalar_evolution (loop, expr);
251*e4b17023SJohn Marino
252*e4b17023SJohn Marino scev = instantiate_scev (scop_entry, loop, scev);
253*e4b17023SJohn Marino
254*e4b17023SJohn Marino return graphite_can_represent_scev (scev);
255*e4b17023SJohn Marino }
256*e4b17023SJohn Marino
257*e4b17023SJohn Marino /* Return true if the data references of STMT can be represented by
258*e4b17023SJohn Marino Graphite. */
259*e4b17023SJohn Marino
260*e4b17023SJohn Marino static bool
stmt_has_simple_data_refs_p(loop_p outermost_loop ATTRIBUTE_UNUSED,gimple stmt)261*e4b17023SJohn Marino stmt_has_simple_data_refs_p (loop_p outermost_loop ATTRIBUTE_UNUSED,
262*e4b17023SJohn Marino gimple stmt)
263*e4b17023SJohn Marino {
264*e4b17023SJohn Marino data_reference_p dr;
265*e4b17023SJohn Marino unsigned i;
266*e4b17023SJohn Marino int j;
267*e4b17023SJohn Marino bool res = true;
268*e4b17023SJohn Marino VEC (data_reference_p, heap) *drs = NULL;
269*e4b17023SJohn Marino loop_p outer;
270*e4b17023SJohn Marino
271*e4b17023SJohn Marino for (outer = loop_containing_stmt (stmt); outer; outer = loop_outer (outer))
272*e4b17023SJohn Marino {
273*e4b17023SJohn Marino graphite_find_data_references_in_stmt (outer,
274*e4b17023SJohn Marino loop_containing_stmt (stmt),
275*e4b17023SJohn Marino stmt, &drs);
276*e4b17023SJohn Marino
277*e4b17023SJohn Marino FOR_EACH_VEC_ELT (data_reference_p, drs, j, dr)
278*e4b17023SJohn Marino for (i = 0; i < DR_NUM_DIMENSIONS (dr); i++)
279*e4b17023SJohn Marino if (!graphite_can_represent_scev (DR_ACCESS_FN (dr, i)))
280*e4b17023SJohn Marino {
281*e4b17023SJohn Marino res = false;
282*e4b17023SJohn Marino goto done;
283*e4b17023SJohn Marino }
284*e4b17023SJohn Marino
285*e4b17023SJohn Marino free_data_refs (drs);
286*e4b17023SJohn Marino drs = NULL;
287*e4b17023SJohn Marino }
288*e4b17023SJohn Marino
289*e4b17023SJohn Marino done:
290*e4b17023SJohn Marino free_data_refs (drs);
291*e4b17023SJohn Marino return res;
292*e4b17023SJohn Marino }
293*e4b17023SJohn Marino
294*e4b17023SJohn Marino /* Return true only when STMT is simple enough for being handled by
295*e4b17023SJohn Marino Graphite. This depends on SCOP_ENTRY, as the parameters are
296*e4b17023SJohn Marino initialized relatively to this basic block, the linear functions
297*e4b17023SJohn Marino are initialized to OUTERMOST_LOOP and BB is the place where we try
298*e4b17023SJohn Marino to evaluate the STMT. */
299*e4b17023SJohn Marino
300*e4b17023SJohn Marino static bool
stmt_simple_for_scop_p(basic_block scop_entry,loop_p outermost_loop,gimple stmt,basic_block bb)301*e4b17023SJohn Marino stmt_simple_for_scop_p (basic_block scop_entry, loop_p outermost_loop,
302*e4b17023SJohn Marino gimple stmt, basic_block bb)
303*e4b17023SJohn Marino {
304*e4b17023SJohn Marino loop_p loop = bb->loop_father;
305*e4b17023SJohn Marino
306*e4b17023SJohn Marino gcc_assert (scop_entry);
307*e4b17023SJohn Marino
308*e4b17023SJohn Marino /* GIMPLE_ASM and GIMPLE_CALL may embed arbitrary side effects.
309*e4b17023SJohn Marino Calls have side-effects, except those to const or pure
310*e4b17023SJohn Marino functions. */
311*e4b17023SJohn Marino if (gimple_has_volatile_ops (stmt)
312*e4b17023SJohn Marino || (gimple_code (stmt) == GIMPLE_CALL
313*e4b17023SJohn Marino && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE)))
314*e4b17023SJohn Marino || (gimple_code (stmt) == GIMPLE_ASM))
315*e4b17023SJohn Marino return false;
316*e4b17023SJohn Marino
317*e4b17023SJohn Marino if (is_gimple_debug (stmt))
318*e4b17023SJohn Marino return true;
319*e4b17023SJohn Marino
320*e4b17023SJohn Marino if (!stmt_has_simple_data_refs_p (outermost_loop, stmt))
321*e4b17023SJohn Marino return false;
322*e4b17023SJohn Marino
323*e4b17023SJohn Marino switch (gimple_code (stmt))
324*e4b17023SJohn Marino {
325*e4b17023SJohn Marino case GIMPLE_RETURN:
326*e4b17023SJohn Marino case GIMPLE_LABEL:
327*e4b17023SJohn Marino return true;
328*e4b17023SJohn Marino
329*e4b17023SJohn Marino case GIMPLE_COND:
330*e4b17023SJohn Marino {
331*e4b17023SJohn Marino tree op;
332*e4b17023SJohn Marino ssa_op_iter op_iter;
333*e4b17023SJohn Marino enum tree_code code = gimple_cond_code (stmt);
334*e4b17023SJohn Marino
335*e4b17023SJohn Marino /* We can handle all binary comparisons. Inequalities are
336*e4b17023SJohn Marino also supported as they can be represented with union of
337*e4b17023SJohn Marino polyhedra. */
338*e4b17023SJohn Marino if (!(code == LT_EXPR
339*e4b17023SJohn Marino || code == GT_EXPR
340*e4b17023SJohn Marino || code == LE_EXPR
341*e4b17023SJohn Marino || code == GE_EXPR
342*e4b17023SJohn Marino || code == EQ_EXPR
343*e4b17023SJohn Marino || code == NE_EXPR))
344*e4b17023SJohn Marino return false;
345*e4b17023SJohn Marino
346*e4b17023SJohn Marino FOR_EACH_SSA_TREE_OPERAND (op, stmt, op_iter, SSA_OP_ALL_USES)
347*e4b17023SJohn Marino if (!graphite_can_represent_expr (scop_entry, loop, op)
348*e4b17023SJohn Marino /* We can not handle REAL_TYPE. Failed for pr39260. */
349*e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (op)) == REAL_TYPE)
350*e4b17023SJohn Marino return false;
351*e4b17023SJohn Marino
352*e4b17023SJohn Marino return true;
353*e4b17023SJohn Marino }
354*e4b17023SJohn Marino
355*e4b17023SJohn Marino case GIMPLE_ASSIGN:
356*e4b17023SJohn Marino case GIMPLE_CALL:
357*e4b17023SJohn Marino return true;
358*e4b17023SJohn Marino
359*e4b17023SJohn Marino default:
360*e4b17023SJohn Marino /* These nodes cut a new scope. */
361*e4b17023SJohn Marino return false;
362*e4b17023SJohn Marino }
363*e4b17023SJohn Marino
364*e4b17023SJohn Marino return false;
365*e4b17023SJohn Marino }
366*e4b17023SJohn Marino
367*e4b17023SJohn Marino /* Returns the statement of BB that contains a harmful operation: that
368*e4b17023SJohn Marino can be a function call with side effects, the induction variables
369*e4b17023SJohn Marino are not linear with respect to SCOP_ENTRY, etc. The current open
370*e4b17023SJohn Marino scop should end before this statement. The evaluation is limited using
371*e4b17023SJohn Marino OUTERMOST_LOOP as outermost loop that may change. */
372*e4b17023SJohn Marino
373*e4b17023SJohn Marino static gimple
harmful_stmt_in_bb(basic_block scop_entry,loop_p outer_loop,basic_block bb)374*e4b17023SJohn Marino harmful_stmt_in_bb (basic_block scop_entry, loop_p outer_loop, basic_block bb)
375*e4b17023SJohn Marino {
376*e4b17023SJohn Marino gimple_stmt_iterator gsi;
377*e4b17023SJohn Marino
378*e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
379*e4b17023SJohn Marino if (!stmt_simple_for_scop_p (scop_entry, outer_loop, gsi_stmt (gsi), bb))
380*e4b17023SJohn Marino return gsi_stmt (gsi);
381*e4b17023SJohn Marino
382*e4b17023SJohn Marino return NULL;
383*e4b17023SJohn Marino }
384*e4b17023SJohn Marino
385*e4b17023SJohn Marino /* Return true if LOOP can be represented in the polyhedral
386*e4b17023SJohn Marino representation. This is evaluated taking SCOP_ENTRY and
387*e4b17023SJohn Marino OUTERMOST_LOOP in mind. */
388*e4b17023SJohn Marino
389*e4b17023SJohn Marino static bool
graphite_can_represent_loop(basic_block scop_entry,loop_p loop)390*e4b17023SJohn Marino graphite_can_represent_loop (basic_block scop_entry, loop_p loop)
391*e4b17023SJohn Marino {
392*e4b17023SJohn Marino tree niter;
393*e4b17023SJohn Marino struct tree_niter_desc niter_desc;
394*e4b17023SJohn Marino
395*e4b17023SJohn Marino /* FIXME: For the moment, graphite cannot be used on loops that
396*e4b17023SJohn Marino iterate using induction variables that wrap. */
397*e4b17023SJohn Marino
398*e4b17023SJohn Marino return number_of_iterations_exit (loop, single_exit (loop), &niter_desc, false)
399*e4b17023SJohn Marino && niter_desc.control.no_overflow
400*e4b17023SJohn Marino && (niter = number_of_latch_executions (loop))
401*e4b17023SJohn Marino && !chrec_contains_undetermined (niter)
402*e4b17023SJohn Marino && graphite_can_represent_expr (scop_entry, loop, niter);
403*e4b17023SJohn Marino }
404*e4b17023SJohn Marino
405*e4b17023SJohn Marino /* Store information needed by scopdet_* functions. */
406*e4b17023SJohn Marino
407*e4b17023SJohn Marino struct scopdet_info
408*e4b17023SJohn Marino {
409*e4b17023SJohn Marino /* Exit of the open scop would stop if the current BB is harmful. */
410*e4b17023SJohn Marino basic_block exit;
411*e4b17023SJohn Marino
412*e4b17023SJohn Marino /* Where the next scop would start if the current BB is harmful. */
413*e4b17023SJohn Marino basic_block next;
414*e4b17023SJohn Marino
415*e4b17023SJohn Marino /* The bb or one of its children contains open loop exits. That means
416*e4b17023SJohn Marino loop exit nodes that are not surrounded by a loop dominated by bb. */
417*e4b17023SJohn Marino bool exits;
418*e4b17023SJohn Marino
419*e4b17023SJohn Marino /* The bb or one of its children contains only structures we can handle. */
420*e4b17023SJohn Marino bool difficult;
421*e4b17023SJohn Marino };
422*e4b17023SJohn Marino
423*e4b17023SJohn Marino static struct scopdet_info build_scops_1 (basic_block, loop_p,
424*e4b17023SJohn Marino VEC (sd_region, heap) **, loop_p);
425*e4b17023SJohn Marino
426*e4b17023SJohn Marino /* Calculates BB infos. If bb is difficult we add valid SCoPs dominated by BB
427*e4b17023SJohn Marino to SCOPS. TYPE is the gbb_type of BB. */
428*e4b17023SJohn Marino
429*e4b17023SJohn Marino static struct scopdet_info
scopdet_basic_block_info(basic_block bb,loop_p outermost_loop,VEC (sd_region,heap)** scops,gbb_type type)430*e4b17023SJohn Marino scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
431*e4b17023SJohn Marino VEC (sd_region, heap) **scops, gbb_type type)
432*e4b17023SJohn Marino {
433*e4b17023SJohn Marino loop_p loop = bb->loop_father;
434*e4b17023SJohn Marino struct scopdet_info result;
435*e4b17023SJohn Marino gimple stmt;
436*e4b17023SJohn Marino
437*e4b17023SJohn Marino /* XXX: ENTRY_BLOCK_PTR could be optimized in later steps. */
438*e4b17023SJohn Marino basic_block entry_block = ENTRY_BLOCK_PTR;
439*e4b17023SJohn Marino stmt = harmful_stmt_in_bb (entry_block, outermost_loop, bb);
440*e4b17023SJohn Marino result.difficult = (stmt != NULL);
441*e4b17023SJohn Marino result.exit = NULL;
442*e4b17023SJohn Marino
443*e4b17023SJohn Marino switch (type)
444*e4b17023SJohn Marino {
445*e4b17023SJohn Marino case GBB_LAST:
446*e4b17023SJohn Marino result.next = NULL;
447*e4b17023SJohn Marino result.exits = false;
448*e4b17023SJohn Marino
449*e4b17023SJohn Marino /* Mark bbs terminating a SESE region difficult, if they start
450*e4b17023SJohn Marino a condition. */
451*e4b17023SJohn Marino if (!single_succ_p (bb))
452*e4b17023SJohn Marino result.difficult = true;
453*e4b17023SJohn Marino else
454*e4b17023SJohn Marino result.exit = single_succ (bb);
455*e4b17023SJohn Marino
456*e4b17023SJohn Marino break;
457*e4b17023SJohn Marino
458*e4b17023SJohn Marino case GBB_SIMPLE:
459*e4b17023SJohn Marino result.next = single_succ (bb);
460*e4b17023SJohn Marino result.exits = false;
461*e4b17023SJohn Marino result.exit = single_succ (bb);
462*e4b17023SJohn Marino break;
463*e4b17023SJohn Marino
464*e4b17023SJohn Marino case GBB_LOOP_SING_EXIT_HEADER:
465*e4b17023SJohn Marino {
466*e4b17023SJohn Marino VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
467*e4b17023SJohn Marino struct scopdet_info sinfo;
468*e4b17023SJohn Marino edge exit_e = single_exit (loop);
469*e4b17023SJohn Marino
470*e4b17023SJohn Marino sinfo = build_scops_1 (bb, outermost_loop, ®ions, loop);
471*e4b17023SJohn Marino
472*e4b17023SJohn Marino if (!graphite_can_represent_loop (entry_block, loop))
473*e4b17023SJohn Marino result.difficult = true;
474*e4b17023SJohn Marino
475*e4b17023SJohn Marino result.difficult |= sinfo.difficult;
476*e4b17023SJohn Marino
477*e4b17023SJohn Marino /* Try again with another loop level. */
478*e4b17023SJohn Marino if (result.difficult
479*e4b17023SJohn Marino && loop_depth (outermost_loop) + 1 == loop_depth (loop))
480*e4b17023SJohn Marino {
481*e4b17023SJohn Marino outermost_loop = loop;
482*e4b17023SJohn Marino
483*e4b17023SJohn Marino VEC_free (sd_region, heap, regions);
484*e4b17023SJohn Marino regions = VEC_alloc (sd_region, heap, 3);
485*e4b17023SJohn Marino
486*e4b17023SJohn Marino sinfo = scopdet_basic_block_info (bb, outermost_loop, scops, type);
487*e4b17023SJohn Marino
488*e4b17023SJohn Marino result = sinfo;
489*e4b17023SJohn Marino result.difficult = true;
490*e4b17023SJohn Marino
491*e4b17023SJohn Marino if (sinfo.difficult)
492*e4b17023SJohn Marino move_sd_regions (®ions, scops);
493*e4b17023SJohn Marino else
494*e4b17023SJohn Marino {
495*e4b17023SJohn Marino sd_region open_scop;
496*e4b17023SJohn Marino open_scop.entry = bb;
497*e4b17023SJohn Marino open_scop.exit = exit_e->dest;
498*e4b17023SJohn Marino VEC_safe_push (sd_region, heap, *scops, &open_scop);
499*e4b17023SJohn Marino VEC_free (sd_region, heap, regions);
500*e4b17023SJohn Marino }
501*e4b17023SJohn Marino }
502*e4b17023SJohn Marino else
503*e4b17023SJohn Marino {
504*e4b17023SJohn Marino result.exit = exit_e->dest;
505*e4b17023SJohn Marino result.next = exit_e->dest;
506*e4b17023SJohn Marino
507*e4b17023SJohn Marino /* If we do not dominate result.next, remove it. It's either
508*e4b17023SJohn Marino the EXIT_BLOCK_PTR, or another bb dominates it and will
509*e4b17023SJohn Marino call the scop detection for this bb. */
510*e4b17023SJohn Marino if (!dominated_by_p (CDI_DOMINATORS, result.next, bb))
511*e4b17023SJohn Marino result.next = NULL;
512*e4b17023SJohn Marino
513*e4b17023SJohn Marino if (exit_e->src->loop_father != loop)
514*e4b17023SJohn Marino result.next = NULL;
515*e4b17023SJohn Marino
516*e4b17023SJohn Marino result.exits = false;
517*e4b17023SJohn Marino
518*e4b17023SJohn Marino if (result.difficult)
519*e4b17023SJohn Marino move_sd_regions (®ions, scops);
520*e4b17023SJohn Marino else
521*e4b17023SJohn Marino VEC_free (sd_region, heap, regions);
522*e4b17023SJohn Marino }
523*e4b17023SJohn Marino
524*e4b17023SJohn Marino break;
525*e4b17023SJohn Marino }
526*e4b17023SJohn Marino
527*e4b17023SJohn Marino case GBB_LOOP_MULT_EXIT_HEADER:
528*e4b17023SJohn Marino {
529*e4b17023SJohn Marino /* XXX: For now we just do not join loops with multiple exits. If the
530*e4b17023SJohn Marino exits lead to the same bb it may be possible to join the loop. */
531*e4b17023SJohn Marino VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
532*e4b17023SJohn Marino VEC (edge, heap) *exits = get_loop_exit_edges (loop);
533*e4b17023SJohn Marino edge e;
534*e4b17023SJohn Marino int i;
535*e4b17023SJohn Marino build_scops_1 (bb, loop, ®ions, loop);
536*e4b17023SJohn Marino
537*e4b17023SJohn Marino /* Scan the code dominated by this loop. This means all bbs, that are
538*e4b17023SJohn Marino are dominated by a bb in this loop, but are not part of this loop.
539*e4b17023SJohn Marino
540*e4b17023SJohn Marino The easiest case:
541*e4b17023SJohn Marino - The loop exit destination is dominated by the exit sources.
542*e4b17023SJohn Marino
543*e4b17023SJohn Marino TODO: We miss here the more complex cases:
544*e4b17023SJohn Marino - The exit destinations are dominated by another bb inside
545*e4b17023SJohn Marino the loop.
546*e4b17023SJohn Marino - The loop dominates bbs, that are not exit destinations. */
547*e4b17023SJohn Marino FOR_EACH_VEC_ELT (edge, exits, i, e)
548*e4b17023SJohn Marino if (e->src->loop_father == loop
549*e4b17023SJohn Marino && dominated_by_p (CDI_DOMINATORS, e->dest, e->src))
550*e4b17023SJohn Marino {
551*e4b17023SJohn Marino if (loop_outer (outermost_loop))
552*e4b17023SJohn Marino outermost_loop = loop_outer (outermost_loop);
553*e4b17023SJohn Marino
554*e4b17023SJohn Marino /* Pass loop_outer to recognize e->dest as loop header in
555*e4b17023SJohn Marino build_scops_1. */
556*e4b17023SJohn Marino if (e->dest->loop_father->header == e->dest)
557*e4b17023SJohn Marino build_scops_1 (e->dest, outermost_loop, ®ions,
558*e4b17023SJohn Marino loop_outer (e->dest->loop_father));
559*e4b17023SJohn Marino else
560*e4b17023SJohn Marino build_scops_1 (e->dest, outermost_loop, ®ions,
561*e4b17023SJohn Marino e->dest->loop_father);
562*e4b17023SJohn Marino }
563*e4b17023SJohn Marino
564*e4b17023SJohn Marino result.next = NULL;
565*e4b17023SJohn Marino result.exit = NULL;
566*e4b17023SJohn Marino result.difficult = true;
567*e4b17023SJohn Marino result.exits = false;
568*e4b17023SJohn Marino move_sd_regions (®ions, scops);
569*e4b17023SJohn Marino VEC_free (edge, heap, exits);
570*e4b17023SJohn Marino break;
571*e4b17023SJohn Marino }
572*e4b17023SJohn Marino case GBB_COND_HEADER:
573*e4b17023SJohn Marino {
574*e4b17023SJohn Marino VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
575*e4b17023SJohn Marino struct scopdet_info sinfo;
576*e4b17023SJohn Marino VEC (basic_block, heap) *dominated;
577*e4b17023SJohn Marino int i;
578*e4b17023SJohn Marino basic_block dom_bb;
579*e4b17023SJohn Marino basic_block last_exit = NULL;
580*e4b17023SJohn Marino edge e;
581*e4b17023SJohn Marino result.exits = false;
582*e4b17023SJohn Marino
583*e4b17023SJohn Marino /* First check the successors of BB, and check if it is
584*e4b17023SJohn Marino possible to join the different branches. */
585*e4b17023SJohn Marino FOR_EACH_VEC_ELT (edge, bb->succs, i, e)
586*e4b17023SJohn Marino {
587*e4b17023SJohn Marino /* Ignore loop exits. They will be handled after the loop
588*e4b17023SJohn Marino body. */
589*e4b17023SJohn Marino if (loop_exits_to_bb_p (loop, e->dest))
590*e4b17023SJohn Marino {
591*e4b17023SJohn Marino result.exits = true;
592*e4b17023SJohn Marino continue;
593*e4b17023SJohn Marino }
594*e4b17023SJohn Marino
595*e4b17023SJohn Marino /* Do not follow edges that lead to the end of the
596*e4b17023SJohn Marino conditions block. For example, in
597*e4b17023SJohn Marino
598*e4b17023SJohn Marino | 0
599*e4b17023SJohn Marino | /|\
600*e4b17023SJohn Marino | 1 2 |
601*e4b17023SJohn Marino | | | |
602*e4b17023SJohn Marino | 3 4 |
603*e4b17023SJohn Marino | \|/
604*e4b17023SJohn Marino | 6
605*e4b17023SJohn Marino
606*e4b17023SJohn Marino the edge from 0 => 6. Only check if all paths lead to
607*e4b17023SJohn Marino the same node 6. */
608*e4b17023SJohn Marino
609*e4b17023SJohn Marino if (!single_pred_p (e->dest))
610*e4b17023SJohn Marino {
611*e4b17023SJohn Marino /* Check, if edge leads directly to the end of this
612*e4b17023SJohn Marino condition. */
613*e4b17023SJohn Marino if (!last_exit)
614*e4b17023SJohn Marino last_exit = e->dest;
615*e4b17023SJohn Marino
616*e4b17023SJohn Marino if (e->dest != last_exit)
617*e4b17023SJohn Marino result.difficult = true;
618*e4b17023SJohn Marino
619*e4b17023SJohn Marino continue;
620*e4b17023SJohn Marino }
621*e4b17023SJohn Marino
622*e4b17023SJohn Marino if (!dominated_by_p (CDI_DOMINATORS, e->dest, bb))
623*e4b17023SJohn Marino {
624*e4b17023SJohn Marino result.difficult = true;
625*e4b17023SJohn Marino continue;
626*e4b17023SJohn Marino }
627*e4b17023SJohn Marino
628*e4b17023SJohn Marino sinfo = build_scops_1 (e->dest, outermost_loop, ®ions, loop);
629*e4b17023SJohn Marino
630*e4b17023SJohn Marino result.exits |= sinfo.exits;
631*e4b17023SJohn Marino result.difficult |= sinfo.difficult;
632*e4b17023SJohn Marino
633*e4b17023SJohn Marino /* Checks, if all branches end at the same point.
634*e4b17023SJohn Marino If that is true, the condition stays joinable.
635*e4b17023SJohn Marino Have a look at the example above. */
636*e4b17023SJohn Marino if (sinfo.exit)
637*e4b17023SJohn Marino {
638*e4b17023SJohn Marino if (!last_exit)
639*e4b17023SJohn Marino last_exit = sinfo.exit;
640*e4b17023SJohn Marino
641*e4b17023SJohn Marino if (sinfo.exit != last_exit)
642*e4b17023SJohn Marino result.difficult = true;
643*e4b17023SJohn Marino }
644*e4b17023SJohn Marino else
645*e4b17023SJohn Marino result.difficult = true;
646*e4b17023SJohn Marino }
647*e4b17023SJohn Marino
648*e4b17023SJohn Marino if (!last_exit)
649*e4b17023SJohn Marino result.difficult = true;
650*e4b17023SJohn Marino
651*e4b17023SJohn Marino /* Join the branches of the condition if possible. */
652*e4b17023SJohn Marino if (!result.exits && !result.difficult)
653*e4b17023SJohn Marino {
654*e4b17023SJohn Marino /* Only return a next pointer if we dominate this pointer.
655*e4b17023SJohn Marino Otherwise it will be handled by the bb dominating it. */
656*e4b17023SJohn Marino if (dominated_by_p (CDI_DOMINATORS, last_exit, bb)
657*e4b17023SJohn Marino && last_exit != bb)
658*e4b17023SJohn Marino result.next = last_exit;
659*e4b17023SJohn Marino else
660*e4b17023SJohn Marino result.next = NULL;
661*e4b17023SJohn Marino
662*e4b17023SJohn Marino result.exit = last_exit;
663*e4b17023SJohn Marino
664*e4b17023SJohn Marino VEC_free (sd_region, heap, regions);
665*e4b17023SJohn Marino break;
666*e4b17023SJohn Marino }
667*e4b17023SJohn Marino
668*e4b17023SJohn Marino /* Scan remaining bbs dominated by BB. */
669*e4b17023SJohn Marino dominated = get_dominated_by (CDI_DOMINATORS, bb);
670*e4b17023SJohn Marino
671*e4b17023SJohn Marino FOR_EACH_VEC_ELT (basic_block, dominated, i, dom_bb)
672*e4b17023SJohn Marino {
673*e4b17023SJohn Marino /* Ignore loop exits: they will be handled after the loop body. */
674*e4b17023SJohn Marino if (loop_depth (find_common_loop (loop, dom_bb->loop_father))
675*e4b17023SJohn Marino < loop_depth (loop))
676*e4b17023SJohn Marino {
677*e4b17023SJohn Marino result.exits = true;
678*e4b17023SJohn Marino continue;
679*e4b17023SJohn Marino }
680*e4b17023SJohn Marino
681*e4b17023SJohn Marino /* Ignore the bbs processed above. */
682*e4b17023SJohn Marino if (single_pred_p (dom_bb) && single_pred (dom_bb) == bb)
683*e4b17023SJohn Marino continue;
684*e4b17023SJohn Marino
685*e4b17023SJohn Marino if (loop_depth (loop) > loop_depth (dom_bb->loop_father))
686*e4b17023SJohn Marino sinfo = build_scops_1 (dom_bb, outermost_loop, ®ions,
687*e4b17023SJohn Marino loop_outer (loop));
688*e4b17023SJohn Marino else
689*e4b17023SJohn Marino sinfo = build_scops_1 (dom_bb, outermost_loop, ®ions, loop);
690*e4b17023SJohn Marino
691*e4b17023SJohn Marino result.exits |= sinfo.exits;
692*e4b17023SJohn Marino result.difficult = true;
693*e4b17023SJohn Marino result.exit = NULL;
694*e4b17023SJohn Marino }
695*e4b17023SJohn Marino
696*e4b17023SJohn Marino VEC_free (basic_block, heap, dominated);
697*e4b17023SJohn Marino
698*e4b17023SJohn Marino result.next = NULL;
699*e4b17023SJohn Marino move_sd_regions (®ions, scops);
700*e4b17023SJohn Marino
701*e4b17023SJohn Marino break;
702*e4b17023SJohn Marino }
703*e4b17023SJohn Marino
704*e4b17023SJohn Marino default:
705*e4b17023SJohn Marino gcc_unreachable ();
706*e4b17023SJohn Marino }
707*e4b17023SJohn Marino
708*e4b17023SJohn Marino return result;
709*e4b17023SJohn Marino }
710*e4b17023SJohn Marino
711*e4b17023SJohn Marino /* Starting from CURRENT we walk the dominance tree and add new sd_regions to
712*e4b17023SJohn Marino SCOPS. The analyse if a sd_region can be handled is based on the value
713*e4b17023SJohn Marino of OUTERMOST_LOOP. Only loops inside OUTERMOST loops may change. LOOP
714*e4b17023SJohn Marino is the loop in which CURRENT is handled.
715*e4b17023SJohn Marino
716*e4b17023SJohn Marino TODO: These functions got a little bit big. They definitely should be cleaned
717*e4b17023SJohn Marino up. */
718*e4b17023SJohn Marino
719*e4b17023SJohn Marino static struct scopdet_info
build_scops_1(basic_block current,loop_p outermost_loop,VEC (sd_region,heap)** scops,loop_p loop)720*e4b17023SJohn Marino build_scops_1 (basic_block current, loop_p outermost_loop,
721*e4b17023SJohn Marino VEC (sd_region, heap) **scops, loop_p loop)
722*e4b17023SJohn Marino {
723*e4b17023SJohn Marino bool in_scop = false;
724*e4b17023SJohn Marino sd_region open_scop;
725*e4b17023SJohn Marino struct scopdet_info sinfo;
726*e4b17023SJohn Marino
727*e4b17023SJohn Marino /* Initialize result. */
728*e4b17023SJohn Marino struct scopdet_info result;
729*e4b17023SJohn Marino result.exits = false;
730*e4b17023SJohn Marino result.difficult = false;
731*e4b17023SJohn Marino result.next = NULL;
732*e4b17023SJohn Marino result.exit = NULL;
733*e4b17023SJohn Marino open_scop.entry = NULL;
734*e4b17023SJohn Marino open_scop.exit = NULL;
735*e4b17023SJohn Marino sinfo.exit = NULL;
736*e4b17023SJohn Marino
737*e4b17023SJohn Marino /* Loop over the dominance tree. If we meet a difficult bb, close
738*e4b17023SJohn Marino the current SCoP. Loop and condition header start a new layer,
739*e4b17023SJohn Marino and can only be added if all bbs in deeper layers are simple. */
740*e4b17023SJohn Marino while (current != NULL)
741*e4b17023SJohn Marino {
742*e4b17023SJohn Marino sinfo = scopdet_basic_block_info (current, outermost_loop, scops,
743*e4b17023SJohn Marino get_bb_type (current, loop));
744*e4b17023SJohn Marino
745*e4b17023SJohn Marino if (!in_scop && !(sinfo.exits || sinfo.difficult))
746*e4b17023SJohn Marino {
747*e4b17023SJohn Marino open_scop.entry = current;
748*e4b17023SJohn Marino open_scop.exit = NULL;
749*e4b17023SJohn Marino in_scop = true;
750*e4b17023SJohn Marino }
751*e4b17023SJohn Marino else if (in_scop && (sinfo.exits || sinfo.difficult))
752*e4b17023SJohn Marino {
753*e4b17023SJohn Marino open_scop.exit = current;
754*e4b17023SJohn Marino VEC_safe_push (sd_region, heap, *scops, &open_scop);
755*e4b17023SJohn Marino in_scop = false;
756*e4b17023SJohn Marino }
757*e4b17023SJohn Marino
758*e4b17023SJohn Marino result.difficult |= sinfo.difficult;
759*e4b17023SJohn Marino result.exits |= sinfo.exits;
760*e4b17023SJohn Marino
761*e4b17023SJohn Marino current = sinfo.next;
762*e4b17023SJohn Marino }
763*e4b17023SJohn Marino
764*e4b17023SJohn Marino /* Try to close open_scop, if we are still in an open SCoP. */
765*e4b17023SJohn Marino if (in_scop)
766*e4b17023SJohn Marino {
767*e4b17023SJohn Marino open_scop.exit = sinfo.exit;
768*e4b17023SJohn Marino gcc_assert (open_scop.exit);
769*e4b17023SJohn Marino VEC_safe_push (sd_region, heap, *scops, &open_scop);
770*e4b17023SJohn Marino }
771*e4b17023SJohn Marino
772*e4b17023SJohn Marino result.exit = sinfo.exit;
773*e4b17023SJohn Marino return result;
774*e4b17023SJohn Marino }
775*e4b17023SJohn Marino
776*e4b17023SJohn Marino /* Checks if a bb is contained in REGION. */
777*e4b17023SJohn Marino
778*e4b17023SJohn Marino static bool
bb_in_sd_region(basic_block bb,sd_region * region)779*e4b17023SJohn Marino bb_in_sd_region (basic_block bb, sd_region *region)
780*e4b17023SJohn Marino {
781*e4b17023SJohn Marino return bb_in_region (bb, region->entry, region->exit);
782*e4b17023SJohn Marino }
783*e4b17023SJohn Marino
784*e4b17023SJohn Marino /* Returns the single entry edge of REGION, if it does not exits NULL. */
785*e4b17023SJohn Marino
786*e4b17023SJohn Marino static edge
find_single_entry_edge(sd_region * region)787*e4b17023SJohn Marino find_single_entry_edge (sd_region *region)
788*e4b17023SJohn Marino {
789*e4b17023SJohn Marino edge e;
790*e4b17023SJohn Marino edge_iterator ei;
791*e4b17023SJohn Marino edge entry = NULL;
792*e4b17023SJohn Marino
793*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, region->entry->preds)
794*e4b17023SJohn Marino if (!bb_in_sd_region (e->src, region))
795*e4b17023SJohn Marino {
796*e4b17023SJohn Marino if (entry)
797*e4b17023SJohn Marino {
798*e4b17023SJohn Marino entry = NULL;
799*e4b17023SJohn Marino break;
800*e4b17023SJohn Marino }
801*e4b17023SJohn Marino
802*e4b17023SJohn Marino else
803*e4b17023SJohn Marino entry = e;
804*e4b17023SJohn Marino }
805*e4b17023SJohn Marino
806*e4b17023SJohn Marino return entry;
807*e4b17023SJohn Marino }
808*e4b17023SJohn Marino
809*e4b17023SJohn Marino /* Returns the single exit edge of REGION, if it does not exits NULL. */
810*e4b17023SJohn Marino
811*e4b17023SJohn Marino static edge
find_single_exit_edge(sd_region * region)812*e4b17023SJohn Marino find_single_exit_edge (sd_region *region)
813*e4b17023SJohn Marino {
814*e4b17023SJohn Marino edge e;
815*e4b17023SJohn Marino edge_iterator ei;
816*e4b17023SJohn Marino edge exit = NULL;
817*e4b17023SJohn Marino
818*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, region->exit->preds)
819*e4b17023SJohn Marino if (bb_in_sd_region (e->src, region))
820*e4b17023SJohn Marino {
821*e4b17023SJohn Marino if (exit)
822*e4b17023SJohn Marino {
823*e4b17023SJohn Marino exit = NULL;
824*e4b17023SJohn Marino break;
825*e4b17023SJohn Marino }
826*e4b17023SJohn Marino
827*e4b17023SJohn Marino else
828*e4b17023SJohn Marino exit = e;
829*e4b17023SJohn Marino }
830*e4b17023SJohn Marino
831*e4b17023SJohn Marino return exit;
832*e4b17023SJohn Marino }
833*e4b17023SJohn Marino
834*e4b17023SJohn Marino /* Create a single entry edge for REGION. */
835*e4b17023SJohn Marino
836*e4b17023SJohn Marino static void
create_single_entry_edge(sd_region * region)837*e4b17023SJohn Marino create_single_entry_edge (sd_region *region)
838*e4b17023SJohn Marino {
839*e4b17023SJohn Marino if (find_single_entry_edge (region))
840*e4b17023SJohn Marino return;
841*e4b17023SJohn Marino
842*e4b17023SJohn Marino /* There are multiple predecessors for bb_3
843*e4b17023SJohn Marino
844*e4b17023SJohn Marino | 1 2
845*e4b17023SJohn Marino | | /
846*e4b17023SJohn Marino | |/
847*e4b17023SJohn Marino | 3 <- entry
848*e4b17023SJohn Marino | |\
849*e4b17023SJohn Marino | | |
850*e4b17023SJohn Marino | 4 ^
851*e4b17023SJohn Marino | | |
852*e4b17023SJohn Marino | |/
853*e4b17023SJohn Marino | 5
854*e4b17023SJohn Marino
855*e4b17023SJohn Marino There are two edges (1->3, 2->3), that point from outside into the region,
856*e4b17023SJohn Marino and another one (5->3), a loop latch, lead to bb_3.
857*e4b17023SJohn Marino
858*e4b17023SJohn Marino We split bb_3.
859*e4b17023SJohn Marino
860*e4b17023SJohn Marino | 1 2
861*e4b17023SJohn Marino | | /
862*e4b17023SJohn Marino | |/
863*e4b17023SJohn Marino |3.0
864*e4b17023SJohn Marino | |\ (3.0 -> 3.1) = single entry edge
865*e4b17023SJohn Marino |3.1 | <- entry
866*e4b17023SJohn Marino | | |
867*e4b17023SJohn Marino | | |
868*e4b17023SJohn Marino | 4 ^
869*e4b17023SJohn Marino | | |
870*e4b17023SJohn Marino | |/
871*e4b17023SJohn Marino | 5
872*e4b17023SJohn Marino
873*e4b17023SJohn Marino If the loop is part of the SCoP, we have to redirect the loop latches.
874*e4b17023SJohn Marino
875*e4b17023SJohn Marino | 1 2
876*e4b17023SJohn Marino | | /
877*e4b17023SJohn Marino | |/
878*e4b17023SJohn Marino |3.0
879*e4b17023SJohn Marino | | (3.0 -> 3.1) = entry edge
880*e4b17023SJohn Marino |3.1 <- entry
881*e4b17023SJohn Marino | |\
882*e4b17023SJohn Marino | | |
883*e4b17023SJohn Marino | 4 ^
884*e4b17023SJohn Marino | | |
885*e4b17023SJohn Marino | |/
886*e4b17023SJohn Marino | 5 */
887*e4b17023SJohn Marino
888*e4b17023SJohn Marino if (region->entry->loop_father->header != region->entry
889*e4b17023SJohn Marino || dominated_by_p (CDI_DOMINATORS,
890*e4b17023SJohn Marino loop_latch_edge (region->entry->loop_father)->src,
891*e4b17023SJohn Marino region->exit))
892*e4b17023SJohn Marino {
893*e4b17023SJohn Marino edge forwarder = split_block_after_labels (region->entry);
894*e4b17023SJohn Marino region->entry = forwarder->dest;
895*e4b17023SJohn Marino }
896*e4b17023SJohn Marino else
897*e4b17023SJohn Marino /* This case is never executed, as the loop headers seem always to have a
898*e4b17023SJohn Marino single edge pointing from outside into the loop. */
899*e4b17023SJohn Marino gcc_unreachable ();
900*e4b17023SJohn Marino
901*e4b17023SJohn Marino gcc_checking_assert (find_single_entry_edge (region));
902*e4b17023SJohn Marino }
903*e4b17023SJohn Marino
904*e4b17023SJohn Marino /* Check if the sd_region, mentioned in EDGE, has no exit bb. */
905*e4b17023SJohn Marino
906*e4b17023SJohn Marino static bool
sd_region_without_exit(edge e)907*e4b17023SJohn Marino sd_region_without_exit (edge e)
908*e4b17023SJohn Marino {
909*e4b17023SJohn Marino sd_region *r = (sd_region *) e->aux;
910*e4b17023SJohn Marino
911*e4b17023SJohn Marino if (r)
912*e4b17023SJohn Marino return r->exit == NULL;
913*e4b17023SJohn Marino else
914*e4b17023SJohn Marino return false;
915*e4b17023SJohn Marino }
916*e4b17023SJohn Marino
917*e4b17023SJohn Marino /* Create a single exit edge for REGION. */
918*e4b17023SJohn Marino
919*e4b17023SJohn Marino static void
create_single_exit_edge(sd_region * region)920*e4b17023SJohn Marino create_single_exit_edge (sd_region *region)
921*e4b17023SJohn Marino {
922*e4b17023SJohn Marino edge e;
923*e4b17023SJohn Marino edge_iterator ei;
924*e4b17023SJohn Marino edge forwarder = NULL;
925*e4b17023SJohn Marino basic_block exit;
926*e4b17023SJohn Marino
927*e4b17023SJohn Marino /* We create a forwarder bb (5) for all edges leaving this region
928*e4b17023SJohn Marino (3->5, 4->5). All other edges leading to the same bb, are moved
929*e4b17023SJohn Marino to a new bb (6). If these edges where part of another region (2->5)
930*e4b17023SJohn Marino we update the region->exit pointer, of this region.
931*e4b17023SJohn Marino
932*e4b17023SJohn Marino To identify which edge belongs to which region we depend on the e->aux
933*e4b17023SJohn Marino pointer in every edge. It points to the region of the edge or to NULL,
934*e4b17023SJohn Marino if the edge is not part of any region.
935*e4b17023SJohn Marino
936*e4b17023SJohn Marino 1 2 3 4 1->5 no region, 2->5 region->exit = 5,
937*e4b17023SJohn Marino \| |/ 3->5 region->exit = NULL, 4->5 region->exit = NULL
938*e4b17023SJohn Marino 5 <- exit
939*e4b17023SJohn Marino
940*e4b17023SJohn Marino changes to
941*e4b17023SJohn Marino
942*e4b17023SJohn Marino 1 2 3 4 1->6 no region, 2->6 region->exit = 6,
943*e4b17023SJohn Marino | | \/ 3->5 no region, 4->5 no region,
944*e4b17023SJohn Marino | | 5
945*e4b17023SJohn Marino \| / 5->6 region->exit = 6
946*e4b17023SJohn Marino 6
947*e4b17023SJohn Marino
948*e4b17023SJohn Marino Now there is only a single exit edge (5->6). */
949*e4b17023SJohn Marino exit = region->exit;
950*e4b17023SJohn Marino region->exit = NULL;
951*e4b17023SJohn Marino forwarder = make_forwarder_block (exit, &sd_region_without_exit, NULL);
952*e4b17023SJohn Marino
953*e4b17023SJohn Marino /* Unmark the edges, that are no longer exit edges. */
954*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, forwarder->src->preds)
955*e4b17023SJohn Marino if (e->aux)
956*e4b17023SJohn Marino e->aux = NULL;
957*e4b17023SJohn Marino
958*e4b17023SJohn Marino /* Mark the new exit edge. */
959*e4b17023SJohn Marino single_succ_edge (forwarder->src)->aux = region;
960*e4b17023SJohn Marino
961*e4b17023SJohn Marino /* Update the exit bb of all regions, where exit edges lead to
962*e4b17023SJohn Marino forwarder->dest. */
963*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, forwarder->dest->preds)
964*e4b17023SJohn Marino if (e->aux)
965*e4b17023SJohn Marino ((sd_region *) e->aux)->exit = forwarder->dest;
966*e4b17023SJohn Marino
967*e4b17023SJohn Marino gcc_checking_assert (find_single_exit_edge (region));
968*e4b17023SJohn Marino }
969*e4b17023SJohn Marino
970*e4b17023SJohn Marino /* Unmark the exit edges of all REGIONS.
971*e4b17023SJohn Marino See comment in "create_single_exit_edge". */
972*e4b17023SJohn Marino
973*e4b17023SJohn Marino static void
unmark_exit_edges(VEC (sd_region,heap)* regions)974*e4b17023SJohn Marino unmark_exit_edges (VEC (sd_region, heap) *regions)
975*e4b17023SJohn Marino {
976*e4b17023SJohn Marino int i;
977*e4b17023SJohn Marino sd_region *s;
978*e4b17023SJohn Marino edge e;
979*e4b17023SJohn Marino edge_iterator ei;
980*e4b17023SJohn Marino
981*e4b17023SJohn Marino FOR_EACH_VEC_ELT (sd_region, regions, i, s)
982*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, s->exit->preds)
983*e4b17023SJohn Marino e->aux = NULL;
984*e4b17023SJohn Marino }
985*e4b17023SJohn Marino
986*e4b17023SJohn Marino
987*e4b17023SJohn Marino /* Mark the exit edges of all REGIONS.
988*e4b17023SJohn Marino See comment in "create_single_exit_edge". */
989*e4b17023SJohn Marino
990*e4b17023SJohn Marino static void
mark_exit_edges(VEC (sd_region,heap)* regions)991*e4b17023SJohn Marino mark_exit_edges (VEC (sd_region, heap) *regions)
992*e4b17023SJohn Marino {
993*e4b17023SJohn Marino int i;
994*e4b17023SJohn Marino sd_region *s;
995*e4b17023SJohn Marino edge e;
996*e4b17023SJohn Marino edge_iterator ei;
997*e4b17023SJohn Marino
998*e4b17023SJohn Marino FOR_EACH_VEC_ELT (sd_region, regions, i, s)
999*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, s->exit->preds)
1000*e4b17023SJohn Marino if (bb_in_sd_region (e->src, s))
1001*e4b17023SJohn Marino e->aux = s;
1002*e4b17023SJohn Marino }
1003*e4b17023SJohn Marino
1004*e4b17023SJohn Marino /* Create for all scop regions a single entry and a single exit edge. */
1005*e4b17023SJohn Marino
1006*e4b17023SJohn Marino static void
create_sese_edges(VEC (sd_region,heap)* regions)1007*e4b17023SJohn Marino create_sese_edges (VEC (sd_region, heap) *regions)
1008*e4b17023SJohn Marino {
1009*e4b17023SJohn Marino int i;
1010*e4b17023SJohn Marino sd_region *s;
1011*e4b17023SJohn Marino
1012*e4b17023SJohn Marino FOR_EACH_VEC_ELT (sd_region, regions, i, s)
1013*e4b17023SJohn Marino create_single_entry_edge (s);
1014*e4b17023SJohn Marino
1015*e4b17023SJohn Marino mark_exit_edges (regions);
1016*e4b17023SJohn Marino
1017*e4b17023SJohn Marino FOR_EACH_VEC_ELT (sd_region, regions, i, s)
1018*e4b17023SJohn Marino /* Don't handle multiple edges exiting the function. */
1019*e4b17023SJohn Marino if (!find_single_exit_edge (s)
1020*e4b17023SJohn Marino && s->exit != EXIT_BLOCK_PTR)
1021*e4b17023SJohn Marino create_single_exit_edge (s);
1022*e4b17023SJohn Marino
1023*e4b17023SJohn Marino unmark_exit_edges (regions);
1024*e4b17023SJohn Marino
1025*e4b17023SJohn Marino fix_loop_structure (NULL);
1026*e4b17023SJohn Marino
1027*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1028*e4b17023SJohn Marino verify_loop_structure ();
1029*e4b17023SJohn Marino verify_dominators (CDI_DOMINATORS);
1030*e4b17023SJohn Marino verify_ssa (false);
1031*e4b17023SJohn Marino #endif
1032*e4b17023SJohn Marino }
1033*e4b17023SJohn Marino
1034*e4b17023SJohn Marino /* Create graphite SCoPs from an array of scop detection REGIONS. */
1035*e4b17023SJohn Marino
1036*e4b17023SJohn Marino static void
build_graphite_scops(VEC (sd_region,heap)* regions,VEC (scop_p,heap)** scops)1037*e4b17023SJohn Marino build_graphite_scops (VEC (sd_region, heap) *regions,
1038*e4b17023SJohn Marino VEC (scop_p, heap) **scops)
1039*e4b17023SJohn Marino {
1040*e4b17023SJohn Marino int i;
1041*e4b17023SJohn Marino sd_region *s;
1042*e4b17023SJohn Marino
1043*e4b17023SJohn Marino FOR_EACH_VEC_ELT (sd_region, regions, i, s)
1044*e4b17023SJohn Marino {
1045*e4b17023SJohn Marino edge entry = find_single_entry_edge (s);
1046*e4b17023SJohn Marino edge exit = find_single_exit_edge (s);
1047*e4b17023SJohn Marino scop_p scop;
1048*e4b17023SJohn Marino
1049*e4b17023SJohn Marino if (!exit)
1050*e4b17023SJohn Marino continue;
1051*e4b17023SJohn Marino
1052*e4b17023SJohn Marino scop = new_scop (new_sese (entry, exit));
1053*e4b17023SJohn Marino VEC_safe_push (scop_p, heap, *scops, scop);
1054*e4b17023SJohn Marino
1055*e4b17023SJohn Marino /* Are there overlapping SCoPs? */
1056*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1057*e4b17023SJohn Marino {
1058*e4b17023SJohn Marino int j;
1059*e4b17023SJohn Marino sd_region *s2;
1060*e4b17023SJohn Marino
1061*e4b17023SJohn Marino FOR_EACH_VEC_ELT (sd_region, regions, j, s2)
1062*e4b17023SJohn Marino if (s != s2)
1063*e4b17023SJohn Marino gcc_assert (!bb_in_sd_region (s->entry, s2));
1064*e4b17023SJohn Marino }
1065*e4b17023SJohn Marino #endif
1066*e4b17023SJohn Marino }
1067*e4b17023SJohn Marino }
1068*e4b17023SJohn Marino
1069*e4b17023SJohn Marino /* Returns true when BB contains only close phi nodes. */
1070*e4b17023SJohn Marino
1071*e4b17023SJohn Marino static bool
contains_only_close_phi_nodes(basic_block bb)1072*e4b17023SJohn Marino contains_only_close_phi_nodes (basic_block bb)
1073*e4b17023SJohn Marino {
1074*e4b17023SJohn Marino gimple_stmt_iterator gsi;
1075*e4b17023SJohn Marino
1076*e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1077*e4b17023SJohn Marino if (gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
1078*e4b17023SJohn Marino return false;
1079*e4b17023SJohn Marino
1080*e4b17023SJohn Marino return true;
1081*e4b17023SJohn Marino }
1082*e4b17023SJohn Marino
1083*e4b17023SJohn Marino /* Print statistics for SCOP to FILE. */
1084*e4b17023SJohn Marino
1085*e4b17023SJohn Marino static void
print_graphite_scop_statistics(FILE * file,scop_p scop)1086*e4b17023SJohn Marino print_graphite_scop_statistics (FILE* file, scop_p scop)
1087*e4b17023SJohn Marino {
1088*e4b17023SJohn Marino long n_bbs = 0;
1089*e4b17023SJohn Marino long n_loops = 0;
1090*e4b17023SJohn Marino long n_stmts = 0;
1091*e4b17023SJohn Marino long n_conditions = 0;
1092*e4b17023SJohn Marino long n_p_bbs = 0;
1093*e4b17023SJohn Marino long n_p_loops = 0;
1094*e4b17023SJohn Marino long n_p_stmts = 0;
1095*e4b17023SJohn Marino long n_p_conditions = 0;
1096*e4b17023SJohn Marino
1097*e4b17023SJohn Marino basic_block bb;
1098*e4b17023SJohn Marino
1099*e4b17023SJohn Marino FOR_ALL_BB (bb)
1100*e4b17023SJohn Marino {
1101*e4b17023SJohn Marino gimple_stmt_iterator psi;
1102*e4b17023SJohn Marino loop_p loop = bb->loop_father;
1103*e4b17023SJohn Marino
1104*e4b17023SJohn Marino if (!bb_in_sese_p (bb, SCOP_REGION (scop)))
1105*e4b17023SJohn Marino continue;
1106*e4b17023SJohn Marino
1107*e4b17023SJohn Marino n_bbs++;
1108*e4b17023SJohn Marino n_p_bbs += bb->count;
1109*e4b17023SJohn Marino
1110*e4b17023SJohn Marino if (VEC_length (edge, bb->succs) > 1)
1111*e4b17023SJohn Marino {
1112*e4b17023SJohn Marino n_conditions++;
1113*e4b17023SJohn Marino n_p_conditions += bb->count;
1114*e4b17023SJohn Marino }
1115*e4b17023SJohn Marino
1116*e4b17023SJohn Marino for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
1117*e4b17023SJohn Marino {
1118*e4b17023SJohn Marino n_stmts++;
1119*e4b17023SJohn Marino n_p_stmts += bb->count;
1120*e4b17023SJohn Marino }
1121*e4b17023SJohn Marino
1122*e4b17023SJohn Marino if (loop->header == bb && loop_in_sese_p (loop, SCOP_REGION (scop)))
1123*e4b17023SJohn Marino {
1124*e4b17023SJohn Marino n_loops++;
1125*e4b17023SJohn Marino n_p_loops += bb->count;
1126*e4b17023SJohn Marino }
1127*e4b17023SJohn Marino
1128*e4b17023SJohn Marino }
1129*e4b17023SJohn Marino
1130*e4b17023SJohn Marino fprintf (file, "\nBefore limit_scops SCoP statistics (");
1131*e4b17023SJohn Marino fprintf (file, "BBS:%ld, ", n_bbs);
1132*e4b17023SJohn Marino fprintf (file, "LOOPS:%ld, ", n_loops);
1133*e4b17023SJohn Marino fprintf (file, "CONDITIONS:%ld, ", n_conditions);
1134*e4b17023SJohn Marino fprintf (file, "STMTS:%ld)\n", n_stmts);
1135*e4b17023SJohn Marino fprintf (file, "\nBefore limit_scops SCoP profiling statistics (");
1136*e4b17023SJohn Marino fprintf (file, "BBS:%ld, ", n_p_bbs);
1137*e4b17023SJohn Marino fprintf (file, "LOOPS:%ld, ", n_p_loops);
1138*e4b17023SJohn Marino fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
1139*e4b17023SJohn Marino fprintf (file, "STMTS:%ld)\n", n_p_stmts);
1140*e4b17023SJohn Marino }
1141*e4b17023SJohn Marino
1142*e4b17023SJohn Marino /* Print statistics for SCOPS to FILE. */
1143*e4b17023SJohn Marino
1144*e4b17023SJohn Marino static void
print_graphite_statistics(FILE * file,VEC (scop_p,heap)* scops)1145*e4b17023SJohn Marino print_graphite_statistics (FILE* file, VEC (scop_p, heap) *scops)
1146*e4b17023SJohn Marino {
1147*e4b17023SJohn Marino int i;
1148*e4b17023SJohn Marino scop_p scop;
1149*e4b17023SJohn Marino
1150*e4b17023SJohn Marino FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
1151*e4b17023SJohn Marino print_graphite_scop_statistics (file, scop);
1152*e4b17023SJohn Marino }
1153*e4b17023SJohn Marino
1154*e4b17023SJohn Marino /* We limit all SCoPs to SCoPs, that are completely surrounded by a loop.
1155*e4b17023SJohn Marino
1156*e4b17023SJohn Marino Example:
1157*e4b17023SJohn Marino
1158*e4b17023SJohn Marino for (i |
1159*e4b17023SJohn Marino { |
1160*e4b17023SJohn Marino for (j | SCoP 1
1161*e4b17023SJohn Marino for (k |
1162*e4b17023SJohn Marino } |
1163*e4b17023SJohn Marino
1164*e4b17023SJohn Marino * SCoP frontier, as this line is not surrounded by any loop. *
1165*e4b17023SJohn Marino
1166*e4b17023SJohn Marino for (l | SCoP 2
1167*e4b17023SJohn Marino
1168*e4b17023SJohn Marino This is necessary as scalar evolution and parameter detection need a
1169*e4b17023SJohn Marino outermost loop to initialize parameters correctly.
1170*e4b17023SJohn Marino
1171*e4b17023SJohn Marino TODO: FIX scalar evolution and parameter detection to allow more flexible
1172*e4b17023SJohn Marino SCoP frontiers. */
1173*e4b17023SJohn Marino
1174*e4b17023SJohn Marino static void
limit_scops(VEC (scop_p,heap)** scops)1175*e4b17023SJohn Marino limit_scops (VEC (scop_p, heap) **scops)
1176*e4b17023SJohn Marino {
1177*e4b17023SJohn Marino VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
1178*e4b17023SJohn Marino
1179*e4b17023SJohn Marino int i;
1180*e4b17023SJohn Marino scop_p scop;
1181*e4b17023SJohn Marino
1182*e4b17023SJohn Marino FOR_EACH_VEC_ELT (scop_p, *scops, i, scop)
1183*e4b17023SJohn Marino {
1184*e4b17023SJohn Marino int j;
1185*e4b17023SJohn Marino loop_p loop;
1186*e4b17023SJohn Marino sese region = SCOP_REGION (scop);
1187*e4b17023SJohn Marino build_sese_loop_nests (region);
1188*e4b17023SJohn Marino
1189*e4b17023SJohn Marino FOR_EACH_VEC_ELT (loop_p, SESE_LOOP_NEST (region), j, loop)
1190*e4b17023SJohn Marino if (!loop_in_sese_p (loop_outer (loop), region)
1191*e4b17023SJohn Marino && single_exit (loop))
1192*e4b17023SJohn Marino {
1193*e4b17023SJohn Marino sd_region open_scop;
1194*e4b17023SJohn Marino open_scop.entry = loop->header;
1195*e4b17023SJohn Marino open_scop.exit = single_exit (loop)->dest;
1196*e4b17023SJohn Marino
1197*e4b17023SJohn Marino /* This is a hack on top of the limit_scops hack. The
1198*e4b17023SJohn Marino limit_scops hack should disappear all together. */
1199*e4b17023SJohn Marino if (single_succ_p (open_scop.exit)
1200*e4b17023SJohn Marino && contains_only_close_phi_nodes (open_scop.exit))
1201*e4b17023SJohn Marino open_scop.exit = single_succ_edge (open_scop.exit)->dest;
1202*e4b17023SJohn Marino
1203*e4b17023SJohn Marino VEC_safe_push (sd_region, heap, regions, &open_scop);
1204*e4b17023SJohn Marino }
1205*e4b17023SJohn Marino }
1206*e4b17023SJohn Marino
1207*e4b17023SJohn Marino free_scops (*scops);
1208*e4b17023SJohn Marino *scops = VEC_alloc (scop_p, heap, 3);
1209*e4b17023SJohn Marino
1210*e4b17023SJohn Marino create_sese_edges (regions);
1211*e4b17023SJohn Marino build_graphite_scops (regions, scops);
1212*e4b17023SJohn Marino VEC_free (sd_region, heap, regions);
1213*e4b17023SJohn Marino }
1214*e4b17023SJohn Marino
1215*e4b17023SJohn Marino /* Returns true when P1 and P2 are close phis with the same
1216*e4b17023SJohn Marino argument. */
1217*e4b17023SJohn Marino
1218*e4b17023SJohn Marino static inline bool
same_close_phi_node(gimple p1,gimple p2)1219*e4b17023SJohn Marino same_close_phi_node (gimple p1, gimple p2)
1220*e4b17023SJohn Marino {
1221*e4b17023SJohn Marino return operand_equal_p (gimple_phi_arg_def (p1, 0),
1222*e4b17023SJohn Marino gimple_phi_arg_def (p2, 0), 0);
1223*e4b17023SJohn Marino }
1224*e4b17023SJohn Marino
1225*e4b17023SJohn Marino /* Remove the close phi node at GSI and replace its rhs with the rhs
1226*e4b17023SJohn Marino of PHI. */
1227*e4b17023SJohn Marino
1228*e4b17023SJohn Marino static void
remove_duplicate_close_phi(gimple phi,gimple_stmt_iterator * gsi)1229*e4b17023SJohn Marino remove_duplicate_close_phi (gimple phi, gimple_stmt_iterator *gsi)
1230*e4b17023SJohn Marino {
1231*e4b17023SJohn Marino gimple use_stmt;
1232*e4b17023SJohn Marino use_operand_p use_p;
1233*e4b17023SJohn Marino imm_use_iterator imm_iter;
1234*e4b17023SJohn Marino tree res = gimple_phi_result (phi);
1235*e4b17023SJohn Marino tree def = gimple_phi_result (gsi_stmt (*gsi));
1236*e4b17023SJohn Marino
1237*e4b17023SJohn Marino gcc_assert (same_close_phi_node (phi, gsi_stmt (*gsi)));
1238*e4b17023SJohn Marino
1239*e4b17023SJohn Marino FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def)
1240*e4b17023SJohn Marino {
1241*e4b17023SJohn Marino FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
1242*e4b17023SJohn Marino SET_USE (use_p, res);
1243*e4b17023SJohn Marino
1244*e4b17023SJohn Marino update_stmt (use_stmt);
1245*e4b17023SJohn Marino
1246*e4b17023SJohn Marino /* It is possible that we just created a duplicate close-phi
1247*e4b17023SJohn Marino for an already-processed containing loop. Check for this
1248*e4b17023SJohn Marino case and clean it up. */
1249*e4b17023SJohn Marino if (gimple_code (use_stmt) == GIMPLE_PHI
1250*e4b17023SJohn Marino && gimple_phi_num_args (use_stmt) == 1)
1251*e4b17023SJohn Marino make_close_phi_nodes_unique (gimple_bb (use_stmt));
1252*e4b17023SJohn Marino }
1253*e4b17023SJohn Marino
1254*e4b17023SJohn Marino remove_phi_node (gsi, true);
1255*e4b17023SJohn Marino }
1256*e4b17023SJohn Marino
1257*e4b17023SJohn Marino /* Removes all the close phi duplicates from BB. */
1258*e4b17023SJohn Marino
1259*e4b17023SJohn Marino static void
make_close_phi_nodes_unique(basic_block bb)1260*e4b17023SJohn Marino make_close_phi_nodes_unique (basic_block bb)
1261*e4b17023SJohn Marino {
1262*e4b17023SJohn Marino gimple_stmt_iterator psi;
1263*e4b17023SJohn Marino
1264*e4b17023SJohn Marino for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
1265*e4b17023SJohn Marino {
1266*e4b17023SJohn Marino gimple_stmt_iterator gsi = psi;
1267*e4b17023SJohn Marino gimple phi = gsi_stmt (psi);
1268*e4b17023SJohn Marino
1269*e4b17023SJohn Marino /* At this point, PHI should be a close phi in normal form. */
1270*e4b17023SJohn Marino gcc_assert (gimple_phi_num_args (phi) == 1);
1271*e4b17023SJohn Marino
1272*e4b17023SJohn Marino /* Iterate over the next phis and remove duplicates. */
1273*e4b17023SJohn Marino gsi_next (&gsi);
1274*e4b17023SJohn Marino while (!gsi_end_p (gsi))
1275*e4b17023SJohn Marino if (same_close_phi_node (phi, gsi_stmt (gsi)))
1276*e4b17023SJohn Marino remove_duplicate_close_phi (phi, &gsi);
1277*e4b17023SJohn Marino else
1278*e4b17023SJohn Marino gsi_next (&gsi);
1279*e4b17023SJohn Marino }
1280*e4b17023SJohn Marino }
1281*e4b17023SJohn Marino
1282*e4b17023SJohn Marino /* Transforms LOOP to the canonical loop closed SSA form. */
1283*e4b17023SJohn Marino
1284*e4b17023SJohn Marino static void
canonicalize_loop_closed_ssa(loop_p loop)1285*e4b17023SJohn Marino canonicalize_loop_closed_ssa (loop_p loop)
1286*e4b17023SJohn Marino {
1287*e4b17023SJohn Marino edge e = single_exit (loop);
1288*e4b17023SJohn Marino basic_block bb;
1289*e4b17023SJohn Marino
1290*e4b17023SJohn Marino if (!e || e->flags & EDGE_ABNORMAL)
1291*e4b17023SJohn Marino return;
1292*e4b17023SJohn Marino
1293*e4b17023SJohn Marino bb = e->dest;
1294*e4b17023SJohn Marino
1295*e4b17023SJohn Marino if (VEC_length (edge, bb->preds) == 1)
1296*e4b17023SJohn Marino {
1297*e4b17023SJohn Marino e = split_block_after_labels (bb);
1298*e4b17023SJohn Marino make_close_phi_nodes_unique (e->src);
1299*e4b17023SJohn Marino }
1300*e4b17023SJohn Marino else
1301*e4b17023SJohn Marino {
1302*e4b17023SJohn Marino gimple_stmt_iterator psi;
1303*e4b17023SJohn Marino basic_block close = split_edge (e);
1304*e4b17023SJohn Marino
1305*e4b17023SJohn Marino e = single_succ_edge (close);
1306*e4b17023SJohn Marino
1307*e4b17023SJohn Marino for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
1308*e4b17023SJohn Marino {
1309*e4b17023SJohn Marino gimple phi = gsi_stmt (psi);
1310*e4b17023SJohn Marino unsigned i;
1311*e4b17023SJohn Marino
1312*e4b17023SJohn Marino for (i = 0; i < gimple_phi_num_args (phi); i++)
1313*e4b17023SJohn Marino if (gimple_phi_arg_edge (phi, i) == e)
1314*e4b17023SJohn Marino {
1315*e4b17023SJohn Marino tree res, arg = gimple_phi_arg_def (phi, i);
1316*e4b17023SJohn Marino use_operand_p use_p;
1317*e4b17023SJohn Marino gimple close_phi;
1318*e4b17023SJohn Marino
1319*e4b17023SJohn Marino if (TREE_CODE (arg) != SSA_NAME)
1320*e4b17023SJohn Marino continue;
1321*e4b17023SJohn Marino
1322*e4b17023SJohn Marino close_phi = create_phi_node (arg, close);
1323*e4b17023SJohn Marino res = create_new_def_for (gimple_phi_result (close_phi),
1324*e4b17023SJohn Marino close_phi,
1325*e4b17023SJohn Marino gimple_phi_result_ptr (close_phi));
1326*e4b17023SJohn Marino add_phi_arg (close_phi, arg,
1327*e4b17023SJohn Marino gimple_phi_arg_edge (close_phi, 0),
1328*e4b17023SJohn Marino UNKNOWN_LOCATION);
1329*e4b17023SJohn Marino use_p = gimple_phi_arg_imm_use_ptr (phi, i);
1330*e4b17023SJohn Marino replace_exp (use_p, res);
1331*e4b17023SJohn Marino update_stmt (phi);
1332*e4b17023SJohn Marino }
1333*e4b17023SJohn Marino }
1334*e4b17023SJohn Marino
1335*e4b17023SJohn Marino make_close_phi_nodes_unique (close);
1336*e4b17023SJohn Marino }
1337*e4b17023SJohn Marino
1338*e4b17023SJohn Marino /* The code above does not properly handle changes in the post dominance
1339*e4b17023SJohn Marino information (yet). */
1340*e4b17023SJohn Marino free_dominance_info (CDI_POST_DOMINATORS);
1341*e4b17023SJohn Marino }
1342*e4b17023SJohn Marino
1343*e4b17023SJohn Marino /* Converts the current loop closed SSA form to a canonical form
1344*e4b17023SJohn Marino expected by the Graphite code generation.
1345*e4b17023SJohn Marino
1346*e4b17023SJohn Marino The loop closed SSA form has the following invariant: a variable
1347*e4b17023SJohn Marino defined in a loop that is used outside the loop appears only in the
1348*e4b17023SJohn Marino phi nodes in the destination of the loop exit. These phi nodes are
1349*e4b17023SJohn Marino called close phi nodes.
1350*e4b17023SJohn Marino
1351*e4b17023SJohn Marino The canonical loop closed SSA form contains the extra invariants:
1352*e4b17023SJohn Marino
1353*e4b17023SJohn Marino - when the loop contains only one exit, the close phi nodes contain
1354*e4b17023SJohn Marino only one argument. That implies that the basic block that contains
1355*e4b17023SJohn Marino the close phi nodes has only one predecessor, that is a basic block
1356*e4b17023SJohn Marino in the loop.
1357*e4b17023SJohn Marino
1358*e4b17023SJohn Marino - the basic block containing the close phi nodes does not contain
1359*e4b17023SJohn Marino other statements.
1360*e4b17023SJohn Marino
1361*e4b17023SJohn Marino - there exist only one phi node per definition in the loop.
1362*e4b17023SJohn Marino */
1363*e4b17023SJohn Marino
1364*e4b17023SJohn Marino static void
canonicalize_loop_closed_ssa_form(void)1365*e4b17023SJohn Marino canonicalize_loop_closed_ssa_form (void)
1366*e4b17023SJohn Marino {
1367*e4b17023SJohn Marino loop_iterator li;
1368*e4b17023SJohn Marino loop_p loop;
1369*e4b17023SJohn Marino
1370*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1371*e4b17023SJohn Marino verify_loop_closed_ssa (true);
1372*e4b17023SJohn Marino #endif
1373*e4b17023SJohn Marino
1374*e4b17023SJohn Marino FOR_EACH_LOOP (li, loop, 0)
1375*e4b17023SJohn Marino canonicalize_loop_closed_ssa (loop);
1376*e4b17023SJohn Marino
1377*e4b17023SJohn Marino rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
1378*e4b17023SJohn Marino update_ssa (TODO_update_ssa);
1379*e4b17023SJohn Marino
1380*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1381*e4b17023SJohn Marino verify_loop_closed_ssa (true);
1382*e4b17023SJohn Marino #endif
1383*e4b17023SJohn Marino }
1384*e4b17023SJohn Marino
1385*e4b17023SJohn Marino /* Find Static Control Parts (SCoP) in the current function and pushes
1386*e4b17023SJohn Marino them to SCOPS. */
1387*e4b17023SJohn Marino
1388*e4b17023SJohn Marino void
build_scops(VEC (scop_p,heap)** scops)1389*e4b17023SJohn Marino build_scops (VEC (scop_p, heap) **scops)
1390*e4b17023SJohn Marino {
1391*e4b17023SJohn Marino struct loop *loop = current_loops->tree_root;
1392*e4b17023SJohn Marino VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
1393*e4b17023SJohn Marino
1394*e4b17023SJohn Marino canonicalize_loop_closed_ssa_form ();
1395*e4b17023SJohn Marino build_scops_1 (single_succ (ENTRY_BLOCK_PTR), ENTRY_BLOCK_PTR->loop_father,
1396*e4b17023SJohn Marino ®ions, loop);
1397*e4b17023SJohn Marino create_sese_edges (regions);
1398*e4b17023SJohn Marino build_graphite_scops (regions, scops);
1399*e4b17023SJohn Marino
1400*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1401*e4b17023SJohn Marino print_graphite_statistics (dump_file, *scops);
1402*e4b17023SJohn Marino
1403*e4b17023SJohn Marino limit_scops (scops);
1404*e4b17023SJohn Marino VEC_free (sd_region, heap, regions);
1405*e4b17023SJohn Marino
1406*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
1407*e4b17023SJohn Marino fprintf (dump_file, "\nnumber of SCoPs: %d\n",
1408*e4b17023SJohn Marino VEC_length (scop_p, *scops));
1409*e4b17023SJohn Marino }
1410*e4b17023SJohn Marino
1411*e4b17023SJohn Marino /* Pretty print to FILE all the SCoPs in DOT format and mark them with
1412*e4b17023SJohn Marino different colors. If there are not enough colors, paint the
1413*e4b17023SJohn Marino remaining SCoPs in gray.
1414*e4b17023SJohn Marino
1415*e4b17023SJohn Marino Special nodes:
1416*e4b17023SJohn Marino - "*" after the node number denotes the entry of a SCoP,
1417*e4b17023SJohn Marino - "#" after the node number denotes the exit of a SCoP,
1418*e4b17023SJohn Marino - "()" around the node number denotes the entry or the
1419*e4b17023SJohn Marino exit nodes of the SCOP. These are not part of SCoP. */
1420*e4b17023SJohn Marino
1421*e4b17023SJohn Marino static void
dot_all_scops_1(FILE * file,VEC (scop_p,heap)* scops)1422*e4b17023SJohn Marino dot_all_scops_1 (FILE *file, VEC (scop_p, heap) *scops)
1423*e4b17023SJohn Marino {
1424*e4b17023SJohn Marino basic_block bb;
1425*e4b17023SJohn Marino edge e;
1426*e4b17023SJohn Marino edge_iterator ei;
1427*e4b17023SJohn Marino scop_p scop;
1428*e4b17023SJohn Marino const char* color;
1429*e4b17023SJohn Marino int i;
1430*e4b17023SJohn Marino
1431*e4b17023SJohn Marino /* Disable debugging while printing graph. */
1432*e4b17023SJohn Marino int tmp_dump_flags = dump_flags;
1433*e4b17023SJohn Marino dump_flags = 0;
1434*e4b17023SJohn Marino
1435*e4b17023SJohn Marino fprintf (file, "digraph all {\n");
1436*e4b17023SJohn Marino
1437*e4b17023SJohn Marino FOR_ALL_BB (bb)
1438*e4b17023SJohn Marino {
1439*e4b17023SJohn Marino int part_of_scop = false;
1440*e4b17023SJohn Marino
1441*e4b17023SJohn Marino /* Use HTML for every bb label. So we are able to print bbs
1442*e4b17023SJohn Marino which are part of two different SCoPs, with two different
1443*e4b17023SJohn Marino background colors. */
1444*e4b17023SJohn Marino fprintf (file, "%d [label=<\n <TABLE BORDER=\"0\" CELLBORDER=\"1\" ",
1445*e4b17023SJohn Marino bb->index);
1446*e4b17023SJohn Marino fprintf (file, "CELLSPACING=\"0\">\n");
1447*e4b17023SJohn Marino
1448*e4b17023SJohn Marino /* Select color for SCoP. */
1449*e4b17023SJohn Marino FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
1450*e4b17023SJohn Marino {
1451*e4b17023SJohn Marino sese region = SCOP_REGION (scop);
1452*e4b17023SJohn Marino if (bb_in_sese_p (bb, region)
1453*e4b17023SJohn Marino || (SESE_EXIT_BB (region) == bb)
1454*e4b17023SJohn Marino || (SESE_ENTRY_BB (region) == bb))
1455*e4b17023SJohn Marino {
1456*e4b17023SJohn Marino switch (i % 17)
1457*e4b17023SJohn Marino {
1458*e4b17023SJohn Marino case 0: /* red */
1459*e4b17023SJohn Marino color = "#e41a1c";
1460*e4b17023SJohn Marino break;
1461*e4b17023SJohn Marino case 1: /* blue */
1462*e4b17023SJohn Marino color = "#377eb8";
1463*e4b17023SJohn Marino break;
1464*e4b17023SJohn Marino case 2: /* green */
1465*e4b17023SJohn Marino color = "#4daf4a";
1466*e4b17023SJohn Marino break;
1467*e4b17023SJohn Marino case 3: /* purple */
1468*e4b17023SJohn Marino color = "#984ea3";
1469*e4b17023SJohn Marino break;
1470*e4b17023SJohn Marino case 4: /* orange */
1471*e4b17023SJohn Marino color = "#ff7f00";
1472*e4b17023SJohn Marino break;
1473*e4b17023SJohn Marino case 5: /* yellow */
1474*e4b17023SJohn Marino color = "#ffff33";
1475*e4b17023SJohn Marino break;
1476*e4b17023SJohn Marino case 6: /* brown */
1477*e4b17023SJohn Marino color = "#a65628";
1478*e4b17023SJohn Marino break;
1479*e4b17023SJohn Marino case 7: /* rose */
1480*e4b17023SJohn Marino color = "#f781bf";
1481*e4b17023SJohn Marino break;
1482*e4b17023SJohn Marino case 8:
1483*e4b17023SJohn Marino color = "#8dd3c7";
1484*e4b17023SJohn Marino break;
1485*e4b17023SJohn Marino case 9:
1486*e4b17023SJohn Marino color = "#ffffb3";
1487*e4b17023SJohn Marino break;
1488*e4b17023SJohn Marino case 10:
1489*e4b17023SJohn Marino color = "#bebada";
1490*e4b17023SJohn Marino break;
1491*e4b17023SJohn Marino case 11:
1492*e4b17023SJohn Marino color = "#fb8072";
1493*e4b17023SJohn Marino break;
1494*e4b17023SJohn Marino case 12:
1495*e4b17023SJohn Marino color = "#80b1d3";
1496*e4b17023SJohn Marino break;
1497*e4b17023SJohn Marino case 13:
1498*e4b17023SJohn Marino color = "#fdb462";
1499*e4b17023SJohn Marino break;
1500*e4b17023SJohn Marino case 14:
1501*e4b17023SJohn Marino color = "#b3de69";
1502*e4b17023SJohn Marino break;
1503*e4b17023SJohn Marino case 15:
1504*e4b17023SJohn Marino color = "#fccde5";
1505*e4b17023SJohn Marino break;
1506*e4b17023SJohn Marino case 16:
1507*e4b17023SJohn Marino color = "#bc80bd";
1508*e4b17023SJohn Marino break;
1509*e4b17023SJohn Marino default: /* gray */
1510*e4b17023SJohn Marino color = "#999999";
1511*e4b17023SJohn Marino }
1512*e4b17023SJohn Marino
1513*e4b17023SJohn Marino fprintf (file, " <TR><TD WIDTH=\"50\" BGCOLOR=\"%s\">", color);
1514*e4b17023SJohn Marino
1515*e4b17023SJohn Marino if (!bb_in_sese_p (bb, region))
1516*e4b17023SJohn Marino fprintf (file, " (");
1517*e4b17023SJohn Marino
1518*e4b17023SJohn Marino if (bb == SESE_ENTRY_BB (region)
1519*e4b17023SJohn Marino && bb == SESE_EXIT_BB (region))
1520*e4b17023SJohn Marino fprintf (file, " %d*# ", bb->index);
1521*e4b17023SJohn Marino else if (bb == SESE_ENTRY_BB (region))
1522*e4b17023SJohn Marino fprintf (file, " %d* ", bb->index);
1523*e4b17023SJohn Marino else if (bb == SESE_EXIT_BB (region))
1524*e4b17023SJohn Marino fprintf (file, " %d# ", bb->index);
1525*e4b17023SJohn Marino else
1526*e4b17023SJohn Marino fprintf (file, " %d ", bb->index);
1527*e4b17023SJohn Marino
1528*e4b17023SJohn Marino if (!bb_in_sese_p (bb,region))
1529*e4b17023SJohn Marino fprintf (file, ")");
1530*e4b17023SJohn Marino
1531*e4b17023SJohn Marino fprintf (file, "</TD></TR>\n");
1532*e4b17023SJohn Marino part_of_scop = true;
1533*e4b17023SJohn Marino }
1534*e4b17023SJohn Marino }
1535*e4b17023SJohn Marino
1536*e4b17023SJohn Marino if (!part_of_scop)
1537*e4b17023SJohn Marino {
1538*e4b17023SJohn Marino fprintf (file, " <TR><TD WIDTH=\"50\" BGCOLOR=\"#ffffff\">");
1539*e4b17023SJohn Marino fprintf (file, " %d </TD></TR>\n", bb->index);
1540*e4b17023SJohn Marino }
1541*e4b17023SJohn Marino fprintf (file, " </TABLE>>, shape=box, style=\"setlinewidth(0)\"]\n");
1542*e4b17023SJohn Marino }
1543*e4b17023SJohn Marino
1544*e4b17023SJohn Marino FOR_ALL_BB (bb)
1545*e4b17023SJohn Marino {
1546*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
1547*e4b17023SJohn Marino fprintf (file, "%d -> %d;\n", bb->index, e->dest->index);
1548*e4b17023SJohn Marino }
1549*e4b17023SJohn Marino
1550*e4b17023SJohn Marino fputs ("}\n\n", file);
1551*e4b17023SJohn Marino
1552*e4b17023SJohn Marino /* Enable debugging again. */
1553*e4b17023SJohn Marino dump_flags = tmp_dump_flags;
1554*e4b17023SJohn Marino }
1555*e4b17023SJohn Marino
1556*e4b17023SJohn Marino /* Display all SCoPs using dotty. */
1557*e4b17023SJohn Marino
1558*e4b17023SJohn Marino DEBUG_FUNCTION void
dot_all_scops(VEC (scop_p,heap)* scops)1559*e4b17023SJohn Marino dot_all_scops (VEC (scop_p, heap) *scops)
1560*e4b17023SJohn Marino {
1561*e4b17023SJohn Marino /* When debugging, enable the following code. This cannot be used
1562*e4b17023SJohn Marino in production compilers because it calls "system". */
1563*e4b17023SJohn Marino #if 0
1564*e4b17023SJohn Marino int x;
1565*e4b17023SJohn Marino FILE *stream = fopen ("/tmp/allscops.dot", "w");
1566*e4b17023SJohn Marino gcc_assert (stream);
1567*e4b17023SJohn Marino
1568*e4b17023SJohn Marino dot_all_scops_1 (stream, scops);
1569*e4b17023SJohn Marino fclose (stream);
1570*e4b17023SJohn Marino
1571*e4b17023SJohn Marino x = system ("dotty /tmp/allscops.dot &");
1572*e4b17023SJohn Marino #else
1573*e4b17023SJohn Marino dot_all_scops_1 (stderr, scops);
1574*e4b17023SJohn Marino #endif
1575*e4b17023SJohn Marino }
1576*e4b17023SJohn Marino
1577*e4b17023SJohn Marino /* Display all SCoPs using dotty. */
1578*e4b17023SJohn Marino
1579*e4b17023SJohn Marino DEBUG_FUNCTION void
dot_scop(scop_p scop)1580*e4b17023SJohn Marino dot_scop (scop_p scop)
1581*e4b17023SJohn Marino {
1582*e4b17023SJohn Marino VEC (scop_p, heap) *scops = NULL;
1583*e4b17023SJohn Marino
1584*e4b17023SJohn Marino if (scop)
1585*e4b17023SJohn Marino VEC_safe_push (scop_p, heap, scops, scop);
1586*e4b17023SJohn Marino
1587*e4b17023SJohn Marino /* When debugging, enable the following code. This cannot be used
1588*e4b17023SJohn Marino in production compilers because it calls "system". */
1589*e4b17023SJohn Marino #if 0
1590*e4b17023SJohn Marino {
1591*e4b17023SJohn Marino int x;
1592*e4b17023SJohn Marino FILE *stream = fopen ("/tmp/allscops.dot", "w");
1593*e4b17023SJohn Marino gcc_assert (stream);
1594*e4b17023SJohn Marino
1595*e4b17023SJohn Marino dot_all_scops_1 (stream, scops);
1596*e4b17023SJohn Marino fclose (stream);
1597*e4b17023SJohn Marino x = system ("dotty /tmp/allscops.dot &");
1598*e4b17023SJohn Marino }
1599*e4b17023SJohn Marino #else
1600*e4b17023SJohn Marino dot_all_scops_1 (stderr, scops);
1601*e4b17023SJohn Marino #endif
1602*e4b17023SJohn Marino
1603*e4b17023SJohn Marino VEC_free (scop_p, heap, scops);
1604*e4b17023SJohn Marino }
1605*e4b17023SJohn Marino
1606*e4b17023SJohn Marino #endif
1607