Dot refined regions.
[official-gcc/graphite-test-results.git] / gcc / refined-regions.c
blobef37533f534e64e89fba592993ef484845fdf92d
1 /* Refined Regions
2 Copyright (C) 2010 Free Software Foundation, Inc.
3 Contributed by Tobias Grosser <grosser@fim.uni-passau.de>.
4 Antoniu Pop <antoniu.pop@gmail.com>
6 This file is part of GCC.
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.
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.
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/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "basic-block.h"
27 #include "timevar.h"
28 #include "bitmap.h"
29 #include "domwalk.h"
30 #include "tree-pass.h"
31 #include "refined-regions.h"
33 /* Auxiliary function for qsort () that compares two basic blocks
34 according to the values of their indices. */
36 static int
37 bb_index_compare (const void *bbv1, const void *bbv2)
39 basic_block bb1 = *(const basic_block *)bbv1;
40 basic_block bb2 = *(const basic_block *)bbv2;
42 gcc_assert (bbv1 && bbv2);
44 if (bb1->index < bb2->index)
45 return -1;
46 else
47 return bb1->index > bb2->index;
50 /* Put all the basic blocks contained in REGION into BBLIST
51 The order in which BBs are put is not defined. */
53 void
54 get_bbs_in_region (refined_region_p region, VEC (basic_block, heap) **bblist)
56 basic_block bb_iter;
58 VEC (basic_block, heap) *bbstack = VEC_alloc (basic_block, heap, 3);
59 VEC_safe_push (basic_block, heap, bbstack, region->entry);
61 while (VEC_length (basic_block, bbstack) != 0)
63 basic_block bb = VEC_pop (basic_block, bbstack);
64 VEC_safe_push (basic_block, heap, *bblist, bb);
66 /* Push to stack all BB's successors. */
67 for (bb_iter = first_dom_son (CDI_DOMINATORS, bb);
68 bb_iter != NULL;
69 bb_iter = next_dom_son (CDI_DOMINATORS, bb_iter))
70 if (bb_iter != region->exit)
71 VEC_safe_push (basic_block, heap, bbstack, bb_iter);
74 VEC_free (basic_block, heap, bbstack);
77 /* Print all basic block indices of REGION into FILE. */
79 static void
80 print_bbs_in_region (FILE* file, refined_region_p region)
82 VEC (basic_block, heap) *bblist = VEC_alloc (basic_block, heap, 3);
83 int i;
84 basic_block bb_iter;
86 get_bbs_in_region (region, &bblist);
88 /* Sort all BBs in the region. */
89 qsort (VEC_address (basic_block, bblist), VEC_length (basic_block, bblist),
90 sizeof (basic_block), bb_index_compare);
92 for (i = 0; VEC_iterate (basic_block, bblist, i, bb_iter); i++)
93 if (i == 0)
94 fprintf (file, "[%d", bb_iter->index);
95 else
96 fprintf (file, ", %d", bb_iter->index);
98 fprintf (file, "]\n");
100 VEC_free (basic_block, heap, bblist);
103 /* Print REGION to F with indention level INDENT. */
105 void
106 print_refined_region (FILE *F, refined_region_p region, int indent, bool print_bbs)
108 int ix, i;
109 refined_region_p subregion;
111 for (i = 0; i < indent * 2; ++i)
112 fprintf (F, " ");
114 if (region->exit)
115 fprintf (F, "%d => %d ", region->entry->index, region->exit->index);
116 else
117 fprintf (F, "%d => End ", region->entry->index);
119 if (print_bbs == true)
120 print_bbs_in_region (F, region);
121 else
122 fprintf (F, "\n");
124 for (ix = 0; VEC_iterate (refined_region_p, region->children, ix, subregion);
125 ix++)
126 print_refined_region (F, subregion, indent + 1, print_bbs);
129 /* Print REGION and all its subregions to stderr. */
131 void
132 debug_refined_region (refined_region_p region)
134 fprintf (stderr, "\n");
135 print_refined_region (stderr, region, 0, true);
138 /* Check that BB is contained in REGION. */
140 bool
141 refined_region_contains_bb_p (refined_region_p region, basic_block bb)
143 return dominated_by_p (CDI_DOMINATORS, bb, region->entry)
144 && !(dominated_by_p (CDI_DOMINATORS, bb, region->exit)
145 && dominated_by_p (CDI_DOMINATORS, region->exit, region->entry));
148 /* Check that the INNER region is contained in the OUTER region. */
150 bool
151 refined_region_contains_region_p (refined_region_p outer,
152 refined_region_p inner)
154 return refined_region_contains_bb_p (outer, inner->entry)
155 && (refined_region_contains_bb_p (outer, inner->exit)
156 || outer->exit == inner->exit);
159 /* Check that BB is part of the dominance frontier of ENTRY, because it was
160 inherited from the dominance frontier of EXIT. */
162 static bool is_common_df (basic_block bb, basic_block entry, basic_block exit)
164 int i;
165 edge e;
167 for (i = 0; VEC_iterate (edge, bb->preds, i, e); i++)
168 if (dominated_by_p (CDI_DOMINATORS, e->src, entry)
169 && !dominated_by_p (CDI_DOMINATORS, e->src, exit))
170 return false;
172 return true;
175 /* Data needed to calculate the refined regions. */
177 struct find_regions_global_data {
179 /* The shortcut table keeps track of existing regions and saves shortcuts
180 from the beginning of each region to the end of the largest possible
181 region. Canonical regions are attached to represent the largest possible
182 region. */
183 htab_t shortcut;
185 /* A map from each basic block that is a region header to its surrounding
186 region. */
187 htab_t bbmap;
189 /* An array that contains for each basic block its dominance frontier. */
190 bitmap *dfs;
193 /* Check that ENTRY and EXIT form a refined region. DFS contains the dominance
194 frontier for all basic blocks. */
196 static bool
197 is_region (basic_block entry, basic_block exit, bitmap *dfs)
199 bitmap df_entry = BITMAP_ALLOC (NULL);
200 bitmap df_exit = BITMAP_ALLOC (NULL);
201 bitmap_iterator bi;
202 unsigned bit = 0;
204 bitmap_copy (df_entry, dfs[entry->index]);
206 bitmap_clear_bit (df_entry, entry->index);
207 bitmap_clear_bit (df_entry, exit->index);
209 if (entry == exit)
210 return false;
212 if (!dominated_by_p (CDI_POST_DOMINATORS, entry, exit))
213 return false;
215 if (!dominated_by_p (CDI_DOMINATORS, exit, entry))
216 return bitmap_count_bits (df_entry) == 0;
218 bitmap_copy (df_exit, dfs[exit->index]);
219 bitmap_clear_bit (df_exit, entry->index);
220 bitmap_clear_bit (df_exit, exit->index);
222 if (bitmap_intersect_compl_p (df_entry, df_exit))
223 return false;
225 EXECUTE_IF_SET_IN_BITMAP (df_entry, 0, bit, bi)
226 if (!is_common_df (BASIC_BLOCK (bit), entry, exit))
227 return false;
229 EXECUTE_IF_SET_IN_BITMAP (df_exit, 0, bit, bi)
230 if (dominated_by_p (CDI_DOMINATORS, BASIC_BLOCK (bit), entry))
231 return false;
233 bitmap_clear (df_entry);
234 bitmap_clear (df_exit);
236 return true;
239 /* Functions to map from one basic block to another. */
241 typedef struct bb_bb_def
243 basic_block key;
244 basic_block value;
245 } bb_bb_def;
247 /* Allocate a new bb->bb object mapping from KEY to VALUE. */
249 static bb_bb_def *
250 new_bb_bb_def (basic_block key, basic_block value)
252 bb_bb_def *bb_bb_p;
253 bb_bb_p = XNEW (bb_bb_def);
254 bb_bb_p->key = key;
255 bb_bb_p->value = value;
256 return bb_bb_p;
259 /* Calculate the hash code of the bb->bb object BB_BB. */
261 static inline hashval_t
262 bb_bb_map_hash (const void *bb_bb)
264 return (hashval_t)(((const bb_bb_def *)bb_bb)->key->index);
267 /* Check that two bb->bb objects BB_BB1 and BB_BB2 are equal. */
269 static inline int
270 eq_bb_bb_map (const void *bb_bb1, const void *bb_bb2)
272 const bb_bb_def *bb1 = (const bb_bb_def *) bb_bb1;
273 const bb_bb_def *bb2 = (const bb_bb_def *) bb_bb2;
274 return (bb1->key->index == bb2->key->index);
277 /* Find the value saved in BB_MAP at KEY. If key is not available return NULL.
280 static inline basic_block
281 find_new_bb (basic_block key, htab_t bb_map)
283 bb_bb_def tmp;
284 PTR *x;
286 tmp.key = key;
287 x = htab_find_slot (bb_map, &tmp, NO_INSERT);
288 if (!x || !*x)
289 return NULL;
291 return ((bb_bb_def *) (*x))->value;
294 /* Functions to map from a basic block to a region. */
296 typedef struct bb_reg_def
298 basic_block bb;
299 refined_region_p region;
300 } bb_reg_def;
302 /* Create a bb to region map object mapping from BB to REGION. */
304 static bb_reg_def *
305 new_bb_reg_def (basic_block bb, refined_region_p region)
307 bb_reg_def *bb_reg_p;
308 bb_reg_p = XNEW (bb_reg_def);
309 bb_reg_p->bb = bb;
310 bb_reg_p->region = region;
311 return bb_reg_p;
314 /* Calculate the hash value for BB_REG. */
316 static inline hashval_t
317 bb_reg_map_hash (const void *bb_reg)
319 return (hashval_t)(((const bb_reg_def *)bb_reg)->bb->index);
322 /* Check that BB_REG1 and BB_REG2 are equal. */
324 static inline int
325 eq_bb_reg_map (const void *bb_reg1, const void *bb_reg2)
327 const bb_reg_def *bb1 = (const bb_reg_def *) bb_reg1;
328 const bb_reg_def *bb2 = (const bb_reg_def *) bb_reg2;
329 return (bb1->bb->index == bb2->bb->index);
332 /* Search in BB_MAP for the region saved for BB. If available return the
333 region otherwise NULL. */
335 static inline refined_region_p
336 find_new_region (basic_block bb, htab_t bb_map)
338 bb_reg_def tmp;
339 PTR *x;
341 tmp.bb = bb;
342 x = htab_find_slot (bb_map, &tmp, NO_INSERT);
343 if (!x || !*x)
344 return NULL;
346 return ((bb_reg_def *) (*x))->region;
349 /* Insert an object mapping from BB to REG into REGMAP. Overwrite
350 the old value if the BB already exists. */
352 static inline void
353 insert_new_reg (basic_block bb, refined_region_p reg, htab_t regmap)
355 bb_reg_def tmp;
356 PTR *x;
358 tmp.bb = bb;
359 x = htab_find_slot (regmap, &tmp, INSERT);
360 if (x && !*x)
361 *x = new_bb_reg_def (bb, reg);
362 else if (x)
364 free (*x);
365 *x = new_bb_reg_def (bb, reg);
369 /* Insert an object mapping from basic block KEY to VALUE into REGMAP.
370 If KEY is already used overwrite the old value. */
372 static inline void
373 insert_new_bb (basic_block key, basic_block value, htab_t bb_map)
375 bb_bb_def tmp;
376 PTR *x;
378 tmp.key = key;
379 x = htab_find_slot (bb_map, &tmp, INSERT);
380 if (x && !*x)
381 *x = new_bb_bb_def (key, value);
382 else if (x)
383 *x = new_bb_bb_def (key, value);
386 /* Insert a shortcut from ENTRY to EXIT into SHORTCUT. If there is already
387 a shortcut starting at EXIT, extend the shortcut to point to the same
388 basic block EXIT is already pointing. */
390 static void
391 insert_shortcut (basic_block entry, basic_block exit, htab_t shortcut)
393 basic_block bb = find_new_bb (exit, shortcut);
395 if (!bb)
396 insert_new_bb (entry, exit, shortcut);
397 else
398 insert_new_bb (entry, bb, shortcut);
401 /* Get the next post dominator of BB, but skip all existing regions by looking
402 at SHORTCUT. */
404 static basic_block
405 get_next_postdom (basic_block bb, htab_t shortcut)
407 basic_block bb_shortcut = find_new_bb (bb, shortcut);
409 if (bb_shortcut)
410 bb = bb_shortcut;
412 return get_immediate_dominator (CDI_POST_DOMINATORS, bb);
415 /* Create a new region starting at ENTRY and finishing at EXIT. */
417 static refined_region_p
418 create_region (basic_block entry, basic_block exit)
420 refined_region_p r = XNEW (struct refined_region);
421 r->entry = entry;
422 r->exit = exit;
423 r->parent = 0;
424 r->children = VEC_alloc (refined_region_p, heap, 16);
426 return r;
429 /* Find all regions that start at ENTRY. DFS is an array containing
430 the dominance frontier for each basic block. GD the global dom walk data
431 storing some further information. */
433 static void
434 find_regions_with_entry (basic_block entry, struct find_regions_global_data *gd)
436 basic_block exit = entry;
437 refined_region_p last_region = 0;
438 basic_block last_exit = entry;
440 while ((exit = get_next_postdom (exit, gd->shortcut)))
443 if (is_region (entry, exit, gd->dfs))
445 refined_region_p new_region = create_region (entry, exit);
447 /* new_region becomes the parent of last_region. */
448 if (last_region)
450 VEC_safe_push (refined_region_p, heap, new_region->children,
451 last_region);
452 last_region->parent = new_region;
454 else
455 insert_new_reg (entry, new_region, gd->bbmap);
457 last_region = new_region;
458 last_exit = exit;
461 /* This can never be a region, so stop the search. */
462 if (!dominated_by_p (CDI_DOMINATORS, exit, entry))
463 break;
466 /* Tried to create regions from entry to last_exit. Next time take a
467 shortcut from entry to last_exit. */
468 if (last_exit != entry)
469 insert_shortcut (entry, last_exit, gd->shortcut);
472 /* Execute this code after each element that was visited by the
473 dominance tree walk. It will find the regions starting
474 at this element (BB), while taking into account the global
475 dom walk data DWD. */
477 static void
478 find_regions_adc (struct dom_walk_data *dwd, basic_block bb)
480 struct find_regions_global_data *gd =
481 (struct find_regions_global_data *) dwd->global_data;
482 find_regions_with_entry (bb, gd);
485 /* Find all regions in the current function. DFS is an array
486 containing the dominance frontiers of all basic blocks. BBMAP will contain
487 the surrounding regions for all region header basic blocks. */
489 static void
490 find_regions (bitmap *dfs, htab_t bbmap)
492 struct dom_walk_data dwd;
493 struct find_regions_global_data gd;
494 gd.shortcut = htab_create (32, &bb_bb_map_hash, &eq_bb_bb_map, free);
495 gd.bbmap = bbmap;
496 gd.dfs = dfs;
498 /* Initialize the domtree walk. */
499 dwd.dom_direction = CDI_DOMINATORS;
500 dwd.block_local_data_size = 0;
501 dwd.global_data = &gd;
502 dwd.after_dom_children = find_regions_adc;
503 dwd.before_dom_children = 0;
504 dwd.initialize_block_local_data = 0;
505 init_walk_dominator_tree (&dwd);
507 /* To only get canonical regions we walk the dominator tree post order and
508 skip already built regions using the shortcut map. */
509 walk_dominator_tree (&dwd, ENTRY_BLOCK_PTR);
510 htab_delete (gd.shortcut);
513 /* Get the topmost parent region of REGION. */
515 static refined_region_p
516 get_topmost_parent (refined_region_p region)
518 if (!region)
519 return NULL;
521 while (region->parent)
522 region = region->parent;
524 return region;
527 /* Initialize the parent/child relations of the regions. Starting at BB
528 that is surrounded by OUTER_REGION. BBMAP contains the surrounding regions
529 for all basic blocks that are region headers. */
531 static void
532 build_regions_tree (basic_block bb, refined_region_p outer_region, htab_t bbmap)
534 int ix;
535 basic_block child_bb;
536 refined_region_p region;
537 VEC (basic_block, heap) *dominated_bbs = get_dominated_by (CDI_DOMINATORS,
538 bb);
539 /* Passed region exit. */
540 while (bb == outer_region->exit)
541 outer_region = outer_region->parent;
543 region = find_new_region (bb, bbmap);
545 if (region)
547 refined_region_p topmost_parent = get_topmost_parent (region);
548 VEC_safe_push (refined_region_p, heap, outer_region->children,
549 topmost_parent);
550 topmost_parent->parent = outer_region;
551 outer_region = region;
554 for (ix = 0; VEC_iterate (basic_block, dominated_bbs, ix, child_bb); ix++)
555 build_regions_tree (child_bb, outer_region, bbmap);
557 VEC_free (basic_block, heap, dominated_bbs);
560 /* Calculate the refined region tree and return the root of the region
561 tree. */
563 refined_region_p
564 calculate_region_tree (void)
566 bitmap *dfs;
567 basic_block bb;
568 refined_region_p outermost_region;
569 htab_t bbmap = htab_create (32, &bb_reg_map_hash, &eq_bb_reg_map, free);
570 bool dom_available, postdom_available;
572 timevar_push (TV_REFINED_REGIONS);
574 /* Initialize dominance frontier. */
575 dfs = XNEWVEC (bitmap, last_basic_block);
576 FOR_EACH_BB (bb)
577 dfs[bb->index] = BITMAP_ALLOC (NULL);
579 /* Required analysis */
580 dom_available = dom_info_available_p (CDI_DOMINATORS);
581 postdom_available = dom_info_available_p (CDI_POST_DOMINATORS);
583 calculate_dominance_info (CDI_DOMINATORS);
584 calculate_dominance_info (CDI_POST_DOMINATORS);
585 compute_dominance_frontiers (dfs);
587 find_regions (dfs, bbmap);
588 outermost_region = create_region (ENTRY_BLOCK_PTR, 0);
589 build_regions_tree (ENTRY_BLOCK_PTR, outermost_region, bbmap);
591 /* Free dominance frontier */
592 FOR_EACH_BB (bb)
593 BITMAP_FREE (dfs[bb->index]);
594 free (dfs);
596 if (!dom_available)
597 free_dominance_info (CDI_DOMINATORS);
599 if (!postdom_available)
600 free_dominance_info (CDI_POST_DOMINATORS);
602 htab_delete (bbmap);
604 timevar_pop (TV_REFINED_REGIONS);
605 return outermost_region;
608 /* Free REGION and all its subregions. */
610 void
611 free_region_tree (refined_region_p region)
613 int ix;
614 refined_region_p subregion;
616 for (ix = 0; VEC_iterate (refined_region_p, region->children, ix, subregion);
617 ix++)
618 free_region_tree (subregion);
620 VEC_free (refined_region_p, heap, region->children);
621 free (region);
624 /* Pretty print to FILE all the REGIONS in DOT format and mark them with
625 different colors. The behavior is the same as in dot_all_scops_1. */
627 static void
628 dot_regions_1 (FILE *file, VEC (refined_region_p, heap) *regions)
630 basic_block bb;
631 edge e;
632 edge_iterator ei;
633 refined_region_p region;
634 const char* color;
635 int i;
637 /* Disable debugging while printing graph. */
638 int tmp_dump_flags = dump_flags;
639 dump_flags = 0;
641 fprintf (file, "digraph all {\n");
643 FOR_ALL_BB (bb)
645 int part_of_scop = false;
647 /* Use HTML for every bb label. So we are able to print bbs
648 which are part of two different SCoPs, with two different
649 background colors. */
650 fprintf (file, "%d [label=<\n <TABLE BORDER=\"0\" CELLBORDER=\"1\" ",
651 bb->index);
652 fprintf (file, "CELLSPACING=\"0\">\n");
654 /* Select color for SCoP. */
655 for (i = 0; VEC_iterate (refined_region_p, regions, i, region); i++)
657 if (refined_region_contains_bb_p (region, bb)
658 || (region->exit == bb)
659 || (region->entry == bb))
661 switch (i % 17)
663 case 0: /* red */
664 color = "#e41a1c";
665 break;
666 case 1: /* blue */
667 color = "#377eb8";
668 break;
669 case 2: /* green */
670 color = "#4daf4a";
671 break;
672 case 3: /* purple */
673 color = "#984ea3";
674 break;
675 case 4: /* orange */
676 color = "#ff7f00";
677 break;
678 case 5: /* yellow */
679 color = "#ffff33";
680 break;
681 case 6: /* brown */
682 color = "#a65628";
683 break;
684 case 7: /* rose */
685 color = "#f781bf";
686 break;
687 case 8:
688 color = "#8dd3c7";
689 break;
690 case 9:
691 color = "#ffffb3";
692 break;
693 case 10:
694 color = "#bebada";
695 break;
696 case 11:
697 color = "#fb8072";
698 break;
699 case 12:
700 color = "#80b1d3";
701 break;
702 case 13:
703 color = "#fdb462";
704 break;
705 case 14:
706 color = "#b3de69";
707 break;
708 case 15:
709 color = "#fccde5";
710 break;
711 case 16:
712 color = "#bc80bd";
713 break;
714 default: /* gray */
715 color = "#999999";
718 fprintf (file, " <TR><TD WIDTH=\"50\" BGCOLOR=\"%s\">", color);
720 if (!refined_region_contains_bb_p (region, bb))
721 fprintf (file, " (");
723 if (bb == region->entry
724 && bb == region->exit)
725 fprintf (file, " %d*# ", bb->index);
726 else if (bb == region->entry)
727 fprintf (file, " %d* ", bb->index);
728 else if (bb == region->exit)
729 fprintf (file, " %d# ", bb->index);
730 else
731 fprintf (file, " %d ", bb->index);
733 if (!refined_region_contains_bb_p (region, bb))
734 fprintf (file, ")");
736 fprintf (file, "</TD></TR>\n");
737 part_of_scop = true;
741 if (!part_of_scop)
743 fprintf (file, " <TR><TD WIDTH=\"50\" BGCOLOR=\"#ffffff\">");
744 fprintf (file, " %d </TD></TR>\n", bb->index);
746 fprintf (file, " </TABLE>>, shape=box, style=\"setlinewidth(0)\"]\n");
749 FOR_ALL_BB (bb)
751 FOR_EACH_EDGE (e, ei, bb->succs)
752 fprintf (file, "%d -> %d;\n", bb->index, e->dest->index);
755 fputs ("}\n\n", file);
757 /* Enable debugging again. */
758 dump_flags = tmp_dump_flags;
761 /* Display refined REGIONS using dotty. */
763 void
764 dot_regions (VEC (refined_region_p, heap) *regions)
766 /* When debugging, enable the following code. This cannot be used
767 in production compilers because it calls "system". */
768 #if 1
769 FILE *stream = fopen ("/tmp/regions.dot", "w");
770 gcc_assert (stream);
772 dot_regions_1 (stream, regions);
773 fclose (stream);
775 system ("dotty /tmp/regions.dot &");
776 #else
777 dot_all_scops_1 (stderr, regions);
778 #endif