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)
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/>. */
24 #include "coretypes.h"
26 #include "basic-block.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. */
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
)
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. */
54 get_bbs_in_region (refined_region_p region
, VEC (basic_block
, heap
) **bblist
)
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
);
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. */
80 print_bbs_in_region (FILE* file
, refined_region_p region
)
82 VEC (basic_block
, heap
) *bblist
= VEC_alloc (basic_block
, heap
, 3);
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
++)
94 fprintf (file
, "[%d", bb_iter
->index
);
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. */
106 print_refined_region (FILE *F
, refined_region_p region
, int indent
, bool print_bbs
)
109 refined_region_p subregion
;
111 for (i
= 0; i
< indent
* 2; ++i
)
115 fprintf (F
, "%d => %d ", region
->entry
->index
, region
->exit
->index
);
117 fprintf (F
, "%d => End ", region
->entry
->index
);
119 if (print_bbs
== true)
120 print_bbs_in_region (F
, region
);
124 for (ix
= 0; VEC_iterate (refined_region_p
, region
->children
, ix
, subregion
);
126 print_refined_region (F
, subregion
, indent
+ 1, print_bbs
);
129 /* Print REGION and all its subregions to stderr. */
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. */
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. */
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
)
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
))
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
185 /* A map from each basic block that is a region header to its surrounding
189 /* An array that contains for each basic block its dominance frontier. */
193 /* Check that ENTRY and EXIT form a refined region. DFS contains the dominance
194 frontier for all basic blocks. */
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
);
204 bitmap_copy (df_entry
, dfs
[entry
->index
]);
206 bitmap_clear_bit (df_entry
, entry
->index
);
207 bitmap_clear_bit (df_entry
, exit
->index
);
212 if (!dominated_by_p (CDI_POST_DOMINATORS
, entry
, exit
))
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
))
225 EXECUTE_IF_SET_IN_BITMAP (df_entry
, 0, bit
, bi
)
226 if (!is_common_df (BASIC_BLOCK (bit
), entry
, exit
))
229 EXECUTE_IF_SET_IN_BITMAP (df_exit
, 0, bit
, bi
)
230 if (dominated_by_p (CDI_DOMINATORS
, BASIC_BLOCK (bit
), entry
))
233 bitmap_clear (df_entry
);
234 bitmap_clear (df_exit
);
239 /* Functions to map from one basic block to another. */
241 typedef struct bb_bb_def
247 /* Allocate a new bb->bb object mapping from KEY to VALUE. */
250 new_bb_bb_def (basic_block key
, basic_block value
)
253 bb_bb_p
= XNEW (bb_bb_def
);
255 bb_bb_p
->value
= value
;
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. */
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
)
287 x
= htab_find_slot (bb_map
, &tmp
, NO_INSERT
);
291 return ((bb_bb_def
*) (*x
))->value
;
294 /* Functions to map from a basic block to a region. */
296 typedef struct bb_reg_def
299 refined_region_p region
;
302 /* Create a bb to region map object mapping from BB to REGION. */
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
);
310 bb_reg_p
->region
= region
;
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. */
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
)
342 x
= htab_find_slot (bb_map
, &tmp
, NO_INSERT
);
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. */
353 insert_new_reg (basic_block bb
, refined_region_p reg
, htab_t regmap
)
359 x
= htab_find_slot (regmap
, &tmp
, INSERT
);
361 *x
= new_bb_reg_def (bb
, reg
);
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. */
373 insert_new_bb (basic_block key
, basic_block value
, htab_t bb_map
)
379 x
= htab_find_slot (bb_map
, &tmp
, INSERT
);
381 *x
= new_bb_bb_def (key
, value
);
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. */
391 insert_shortcut (basic_block entry
, basic_block exit
, htab_t shortcut
)
393 basic_block bb
= find_new_bb (exit
, shortcut
);
396 insert_new_bb (entry
, exit
, shortcut
);
398 insert_new_bb (entry
, bb
, shortcut
);
401 /* Get the next post dominator of BB, but skip all existing regions by looking
405 get_next_postdom (basic_block bb
, htab_t shortcut
)
407 basic_block bb_shortcut
= find_new_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
);
424 r
->children
= VEC_alloc (refined_region_p
, heap
, 16);
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. */
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. */
450 VEC_safe_push (refined_region_p
, heap
, new_region
->children
,
452 last_region
->parent
= new_region
;
455 insert_new_reg (entry
, new_region
, gd
->bbmap
);
457 last_region
= new_region
;
461 /* This can never be a region, so stop the search. */
462 if (!dominated_by_p (CDI_DOMINATORS
, exit
, entry
))
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. */
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. */
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
);
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
)
521 while (region
->parent
)
522 region
= region
->parent
;
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. */
532 build_regions_tree (basic_block bb
, refined_region_p outer_region
, htab_t bbmap
)
535 basic_block child_bb
;
536 refined_region_p region
;
537 VEC (basic_block
, heap
) *dominated_bbs
= get_dominated_by (CDI_DOMINATORS
,
539 /* Passed region exit. */
540 while (bb
== outer_region
->exit
)
541 outer_region
= outer_region
->parent
;
543 region
= find_new_region (bb
, bbmap
);
547 refined_region_p topmost_parent
= get_topmost_parent (region
);
548 VEC_safe_push (refined_region_p
, heap
, outer_region
->children
,
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
564 calculate_region_tree (void)
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
);
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 */
593 BITMAP_FREE (dfs
[bb
->index
]);
597 free_dominance_info (CDI_DOMINATORS
);
599 if (!postdom_available
)
600 free_dominance_info (CDI_POST_DOMINATORS
);
604 timevar_pop (TV_REFINED_REGIONS
);
605 return outermost_region
;
608 /* Free REGION and all its subregions. */
611 free_region_tree (refined_region_p region
)
614 refined_region_p subregion
;
616 for (ix
= 0; VEC_iterate (refined_region_p
, region
->children
, ix
, subregion
);
618 free_region_tree (subregion
);
620 VEC_free (refined_region_p
, heap
, region
->children
);
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. */
628 dot_regions_1 (FILE *file
, VEC (refined_region_p
, heap
) *regions
)
633 refined_region_p region
;
637 /* Disable debugging while printing graph. */
638 int tmp_dump_flags
= dump_flags
;
641 fprintf (file
, "digraph all {\n");
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\" ",
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
))
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
);
731 fprintf (file
, " %d ", bb
->index
);
733 if (!refined_region_contains_bb_p (region
, bb
))
736 fprintf (file
, "</TD></TR>\n");
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");
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. */
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". */
769 FILE *stream
= fopen ("/tmp/regions.dot", "w");
772 dot_regions_1 (stream
, regions
);
775 system ("dotty /tmp/regions.dot &");
777 dot_all_scops_1 (stderr
, regions
);