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