graphite-scop-detection.c (stmt_simple_memref_p): Removed.
[gcc.git] / gcc / graphite-scop-detection.c
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
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along 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
56 typedef 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
71 static gbb_type
72 get_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
128 typedef 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
139 DEF_VEC_O(sd_region);
140 DEF_VEC_ALLOC_O(sd_region, heap);
141
142
143 /* Moves the scops from SOURCE to TARGET and clean up SOURCE. */
144
145 static void
146 move_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
160 static bool
161 graphite_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
208 static bool
209 graphite_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
241 static bool
242 graphite_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
252 /* Return true if the data references of STMT can be represented by
253 Graphite. */
254
255 static bool
256 stmt_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
280 /* Return false if the TREE_CODE of the operand OP or any of its operands
281 is a COMPONENT_REF. */
282
283 static bool
284 exclude_component_ref (tree op)
285 {
286 int i;
287 int len;
288
289 if (!op)
290 return true;
291
292 if (TREE_CODE (op) == COMPONENT_REF)
293 return false;
294
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;
301 }
302
303 /* Return true if the operand OP used in STMT is simple in regards to
304 OUTERMOST_LOOP. */
305
306 static inline bool
307 is_simple_operand (tree op)
308 {
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);
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
321 static bool
322 stmt_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
338 if (is_gimple_debug (stmt))
339 return true;
340
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:
385 return (is_simple_operand (gimple_assign_lhs (stmt))
386 && is_simple_operand (gimple_assign_rhs1 (stmt)));
387
388 case GIMPLE_BINARY_RHS:
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)));
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
405 if (lhs && !is_simple_operand (lhs))
406 return false;
407
408 for (i = 0; i < n; i++)
409 if (!is_simple_operand (gimple_call_arg (stmt, i)))
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
429 static gimple
430 harmful_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
445 static bool
446 graphite_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
464 struct 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
480 static 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
486 static struct scopdet_info
487 scopdet_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
776 static struct scopdet_info
777 build_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
835 static bool
836 bb_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
843 static edge
844 find_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
868 static edge
869 find_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
893 static void
894 create_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
965 static bool
966 sd_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
978 static void
979 create_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
1037 static void
1038 unmark_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
1054 static void
1055 mark_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
1070 static void
1071 create_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
1097 static void
1098 build_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
1127 static bool
1128 contains_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
1141 static void
1142 print_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
1200 static void
1201 print_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
1210 /* Version of free_scops special cased for limit_scops. */
1211
1212 static void
1213 free_scops_1 (VEC (scop_p, heap) **scops)
1214 {
1215 int i;
1216 scop_p scop;
1217
1218 for (i = 0; VEC_iterate (scop_p, *scops, i, scop); i++)
1219 {
1220 sese region = SCOP_REGION (scop);
1221 free (SESE_PARAMS_NAMES (region));
1222 SESE_PARAMS_NAMES (region) = 0;
1223 }
1224
1225 free_scops (*scops);
1226 }
1227
1228 /* We limit all SCoPs to SCoPs, that are completely surrounded by a loop.
1229
1230 Example:
1231
1232 for (i |
1233 { |
1234 for (j | SCoP 1
1235 for (k |
1236 } |
1237
1238 * SCoP frontier, as this line is not surrounded by any loop. *
1239
1240 for (l | SCoP 2
1241
1242 This is necessary as scalar evolution and parameter detection need a
1243 outermost loop to initialize parameters correctly.
1244
1245 TODO: FIX scalar evolution and parameter detection to allow more flexible
1246 SCoP frontiers. */
1247
1248 static void
1249 limit_scops (VEC (scop_p, heap) **scops)
1250 {
1251 VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
1252
1253 int i;
1254 scop_p scop;
1255
1256 for (i = 0; VEC_iterate (scop_p, *scops, i, scop); i++)
1257 {
1258 int j;
1259 loop_p loop;
1260 sese region = SCOP_REGION (scop);
1261 build_scop_bbs (scop);
1262 build_sese_loop_nests (region);
1263
1264 for (j = 0; VEC_iterate (loop_p, SESE_LOOP_NEST (region), j, loop); j++)
1265 if (!loop_in_sese_p (loop_outer (loop), region)
1266 && single_exit (loop))
1267 {
1268 sd_region open_scop;
1269 open_scop.entry = loop->header;
1270 open_scop.exit = single_exit (loop)->dest;
1271
1272 /* This is a hack on top of the limit_scops hack. The
1273 limit_scops hack should disappear all together. */
1274 if (single_succ_p (open_scop.exit)
1275 && contains_only_close_phi_nodes (open_scop.exit))
1276 open_scop.exit = single_succ_edge (open_scop.exit)->dest;
1277
1278 VEC_safe_push (sd_region, heap, regions, &open_scop);
1279 }
1280 }
1281
1282 free_scops_1 (scops);
1283 *scops = VEC_alloc (scop_p, heap, 3);
1284
1285 create_sese_edges (regions);
1286 build_graphite_scops (regions, scops);
1287 VEC_free (sd_region, heap, regions);
1288 }
1289
1290 /* Transforms LOOP to the canonical loop closed SSA form. */
1291
1292 static void
1293 canonicalize_loop_closed_ssa (loop_p loop)
1294 {
1295 edge e = single_exit (loop);
1296 basic_block bb;
1297
1298 if (!e || e->flags & EDGE_ABNORMAL)
1299 return;
1300
1301 bb = e->dest;
1302
1303 if (VEC_length (edge, bb->preds) == 1)
1304 split_block_after_labels (bb);
1305 else
1306 {
1307 gimple_stmt_iterator psi;
1308 basic_block close = split_edge (e);
1309
1310 e = single_succ_edge (close);
1311
1312 for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
1313 {
1314 gimple phi = gsi_stmt (psi);
1315 unsigned i;
1316
1317 for (i = 0; i < gimple_phi_num_args (phi); i++)
1318 if (gimple_phi_arg_edge (phi, i) == e)
1319 {
1320 tree res, arg = gimple_phi_arg_def (phi, i);
1321 use_operand_p use_p;
1322 gimple close_phi;
1323
1324 if (TREE_CODE (arg) != SSA_NAME)
1325 continue;
1326
1327 close_phi = create_phi_node (arg, close);
1328 res = create_new_def_for (gimple_phi_result (close_phi),
1329 close_phi,
1330 gimple_phi_result_ptr (close_phi));
1331 add_phi_arg (close_phi, arg,
1332 gimple_phi_arg_edge (close_phi, 0),
1333 UNKNOWN_LOCATION);
1334 use_p = gimple_phi_arg_imm_use_ptr (phi, i);
1335 replace_exp (use_p, res);
1336 update_stmt (phi);
1337 }
1338 }
1339 }
1340 }
1341
1342 /* Converts the current loop closed SSA form to a canonical form
1343 expected by the Graphite code generation.
1344
1345 The loop closed SSA form has the following invariant: a variable
1346 defined in a loop that is used outside the loop appears only in the
1347 phi nodes in the destination of the loop exit. These phi nodes are
1348 called close phi nodes.
1349
1350 The canonical loop closed SSA form contains the extra invariants:
1351
1352 - when the loop contains only one exit, the close phi nodes contain
1353 only one argument. That implies that the basic block that contains
1354 the close phi nodes has only one predecessor, that is a basic block
1355 in the loop.
1356
1357 - the basic block containing the close phi nodes does not contain
1358 other statements.
1359 */
1360
1361 static void
1362 canonicalize_loop_closed_ssa_form (void)
1363 {
1364 loop_iterator li;
1365 loop_p loop;
1366
1367 #ifdef ENABLE_CHECKING
1368 verify_loop_closed_ssa ();
1369 #endif
1370
1371 FOR_EACH_LOOP (li, loop, 0)
1372 canonicalize_loop_closed_ssa (loop);
1373
1374 rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
1375 update_ssa (TODO_update_ssa);
1376
1377 #ifdef ENABLE_CHECKING
1378 verify_loop_closed_ssa ();
1379 #endif
1380 }
1381
1382 /* Find Static Control Parts (SCoP) in the current function and pushes
1383 them to SCOPS. */
1384
1385 void
1386 build_scops (VEC (scop_p, heap) **scops)
1387 {
1388 struct loop *loop = current_loops->tree_root;
1389 VEC (sd_region, heap) *regions = VEC_alloc (sd_region, heap, 3);
1390
1391 canonicalize_loop_closed_ssa_form ();
1392 build_scops_1 (single_succ (ENTRY_BLOCK_PTR), ENTRY_BLOCK_PTR->loop_father,
1393 &regions, loop);
1394 create_sese_edges (regions);
1395 build_graphite_scops (regions, scops);
1396
1397 if (dump_file && (dump_flags & TDF_DETAILS))
1398 print_graphite_statistics (dump_file, *scops);
1399
1400 limit_scops (scops);
1401 VEC_free (sd_region, heap, regions);
1402
1403 if (dump_file && (dump_flags & TDF_DETAILS))
1404 fprintf (dump_file, "\nnumber of SCoPs: %d\n",
1405 VEC_length (scop_p, *scops));
1406 }
1407
1408 /* Pretty print to FILE all the SCoPs in DOT format and mark them with
1409 different colors. If there are not enough colors, paint the
1410 remaining SCoPs in gray.
1411
1412 Special nodes:
1413 - "*" after the node number denotes the entry of a SCoP,
1414 - "#" after the node number denotes the exit of a SCoP,
1415 - "()" around the node number denotes the entry or the
1416 exit nodes of the SCOP. These are not part of SCoP. */
1417
1418 static void
1419 dot_all_scops_1 (FILE *file, VEC (scop_p, heap) *scops)
1420 {
1421 basic_block bb;
1422 edge e;
1423 edge_iterator ei;
1424 scop_p scop;
1425 const char* color;
1426 int i;
1427
1428 /* Disable debugging while printing graph. */
1429 int tmp_dump_flags = dump_flags;
1430 dump_flags = 0;
1431
1432 fprintf (file, "digraph all {\n");
1433
1434 FOR_ALL_BB (bb)
1435 {
1436 int part_of_scop = false;
1437
1438 /* Use HTML for every bb label. So we are able to print bbs
1439 which are part of two different SCoPs, with two different
1440 background colors. */
1441 fprintf (file, "%d [label=<\n <TABLE BORDER=\"0\" CELLBORDER=\"1\" ",
1442 bb->index);
1443 fprintf (file, "CELLSPACING=\"0\">\n");
1444
1445 /* Select color for SCoP. */
1446 for (i = 0; VEC_iterate (scop_p, scops, i, scop); i++)
1447 {
1448 sese region = SCOP_REGION (scop);
1449 if (bb_in_sese_p (bb, region)
1450 || (SESE_EXIT_BB (region) == bb)
1451 || (SESE_ENTRY_BB (region) == bb))
1452 {
1453 switch (i % 17)
1454 {
1455 case 0: /* red */
1456 color = "#e41a1c";
1457 break;
1458 case 1: /* blue */
1459 color = "#377eb8";
1460 break;
1461 case 2: /* green */
1462 color = "#4daf4a";
1463 break;
1464 case 3: /* purple */
1465 color = "#984ea3";
1466 break;
1467 case 4: /* orange */
1468 color = "#ff7f00";
1469 break;
1470 case 5: /* yellow */
1471 color = "#ffff33";
1472 break;
1473 case 6: /* brown */
1474 color = "#a65628";
1475 break;
1476 case 7: /* rose */
1477 color = "#f781bf";
1478 break;
1479 case 8:
1480 color = "#8dd3c7";
1481 break;
1482 case 9:
1483 color = "#ffffb3";
1484 break;
1485 case 10:
1486 color = "#bebada";
1487 break;
1488 case 11:
1489 color = "#fb8072";
1490 break;
1491 case 12:
1492 color = "#80b1d3";
1493 break;
1494 case 13:
1495 color = "#fdb462";
1496 break;
1497 case 14:
1498 color = "#b3de69";
1499 break;
1500 case 15:
1501 color = "#fccde5";
1502 break;
1503 case 16:
1504 color = "#bc80bd";
1505 break;
1506 default: /* gray */
1507 color = "#999999";
1508 }
1509
1510 fprintf (file, " <TR><TD WIDTH=\"50\" BGCOLOR=\"%s\">", color);
1511
1512 if (!bb_in_sese_p (bb, region))
1513 fprintf (file, " (");
1514
1515 if (bb == SESE_ENTRY_BB (region)
1516 && bb == SESE_EXIT_BB (region))
1517 fprintf (file, " %d*# ", bb->index);
1518 else if (bb == SESE_ENTRY_BB (region))
1519 fprintf (file, " %d* ", bb->index);
1520 else if (bb == SESE_EXIT_BB (region))
1521 fprintf (file, " %d# ", bb->index);
1522 else
1523 fprintf (file, " %d ", bb->index);
1524
1525 if (!bb_in_sese_p (bb,region))
1526 fprintf (file, ")");
1527
1528 fprintf (file, "</TD></TR>\n");
1529 part_of_scop = true;
1530 }
1531 }
1532
1533 if (!part_of_scop)
1534 {
1535 fprintf (file, " <TR><TD WIDTH=\"50\" BGCOLOR=\"#ffffff\">");
1536 fprintf (file, " %d </TD></TR>\n", bb->index);
1537 }
1538 fprintf (file, " </TABLE>>, shape=box, style=\"setlinewidth(0)\"]\n");
1539 }
1540
1541 FOR_ALL_BB (bb)
1542 {
1543 FOR_EACH_EDGE (e, ei, bb->succs)
1544 fprintf (file, "%d -> %d;\n", bb->index, e->dest->index);
1545 }
1546
1547 fputs ("}\n\n", file);
1548
1549 /* Enable debugging again. */
1550 dump_flags = tmp_dump_flags;
1551 }
1552
1553 /* Display all SCoPs using dotty. */
1554
1555 void
1556 dot_all_scops (VEC (scop_p, heap) *scops)
1557 {
1558 /* When debugging, enable the following code. This cannot be used
1559 in production compilers because it calls "system". */
1560 #if 0
1561 int x;
1562 FILE *stream = fopen ("/tmp/allscops.dot", "w");
1563 gcc_assert (stream);
1564
1565 dot_all_scops_1 (stream, scops);
1566 fclose (stream);
1567
1568 x = system ("dotty /tmp/allscops.dot");
1569 #else
1570 dot_all_scops_1 (stderr, scops);
1571 #endif
1572 }
1573
1574 /* Display all SCoPs using dotty. */
1575
1576 void
1577 dot_scop (scop_p scop)
1578 {
1579 VEC (scop_p, heap) *scops = NULL;
1580
1581 if (scop)
1582 VEC_safe_push (scop_p, heap, scops, scop);
1583
1584 /* When debugging, enable the following code. This cannot be used
1585 in production compilers because it calls "system". */
1586 #if 0
1587 {
1588 int x;
1589 FILE *stream = fopen ("/tmp/allscops.dot", "w");
1590 gcc_assert (stream);
1591
1592 dot_all_scops_1 (stream, scops);
1593 fclose (stream);
1594 x = system ("dotty /tmp/allscops.dot");
1595 }
1596 #else
1597 dot_all_scops_1 (stderr, scops);
1598 #endif
1599
1600 VEC_free (scop_p, heap, scops);
1601 }
1602
1603 #endif