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