xref: /dflybsd-src/contrib/gcc-4.7/gcc/graphite-scop-detection.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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, &regions, 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 (&regions, 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 (&regions, 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, &regions, 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, &regions,
558*e4b17023SJohn Marino 			       loop_outer (e->dest->loop_father));
559*e4b17023SJohn Marino 	      else
560*e4b17023SJohn Marino 		build_scops_1 (e->dest, outermost_loop, &regions,
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 (&regions, 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, &regions, 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, &regions,
687*e4b17023SJohn Marino 				     loop_outer (loop));
688*e4b17023SJohn Marino 	    else
689*e4b17023SJohn Marino 	      sinfo = build_scops_1 (dom_bb, outermost_loop, &regions, 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 (&regions, 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 		 &regions, 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