diff options
author | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-09-12 22:55:23 +0000 |
---|---|---|
committer | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-09-12 22:55:23 +0000 |
commit | 76b340dbd7165cfaaa427c88c58e61197134e144 (patch) | |
tree | 1509936ba3ec5d5f89573c2cd6bccac4844793e1 /gcc | |
parent | 26b84749b164d326329431d96fcf33e9e8f7d97e (diff) | |
download | gcc-76b340dbd7165cfaaa427c88c58e61197134e144.tar.gz |
2008-09-12 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-opt/37377
* ira-build.c (common_loop_tree_node_dominator): Remove.
(copy_live_ranges_to_removed_store_destinations): New function.
(regno_top_level_allocno_map): Move to top level from ...
(ira_flattening): ... here. Use
copy_live_ranges_to_removed_store_destinations.
* ira-emit.c (generate_edge_moves): Fix a comment.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@140325 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/ira-build.c | 122 | ||||
-rw-r--r-- | gcc/ira-emit.c | 8 |
3 files changed, 77 insertions, 65 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0528f17e532..5fd70a744c2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2008-09-12 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-opt/37377 + + * ira-build.c (common_loop_tree_node_dominator): Remove. + (copy_live_ranges_to_removed_store_destinations): New function. + (regno_top_level_allocno_map): Move to top level from ... + (ira_flattening): ... here. Use + copy_live_ranges_to_removed_store_destinations. + + * ira-emit.c (generate_edge_moves): Fix a comment. + 2008-09-12 Anatoly Sokolov <aesok@post.ru> PR target/37466 diff --git a/gcc/ira-build.c b/gcc/ira-build.c index 3535214cac6..fa0a39c192a 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -2037,21 +2037,59 @@ create_caps (void) the IR for one region but we don't do it because it takes a lot of time. */ -/* This recursive function returns immediate common dominator of two - loop tree nodes N1 and N2. */ -static ira_loop_tree_node_t -common_loop_tree_node_dominator (ira_loop_tree_node_t n1, - ira_loop_tree_node_t n2) -{ - ira_assert (n1 != NULL && n2 != NULL); - if (n1 == n2) - return n1; - if (n1->level < n2->level) - return common_loop_tree_node_dominator (n1, n2->parent); - else if (n1->level > n2->level) - return common_loop_tree_node_dominator (n1->parent, n2); - else - return common_loop_tree_node_dominator (n1->parent, n2->parent); +/* Map: regno -> allocnos which will finally represent the regno for + IR with one region. */ +static ira_allocno_t *regno_top_level_allocno_map; + +/* Process all allocnos originated from pseudo REGNO and copy live + ranges from low level allocnos to final allocnos which are + destinations of removed stores at a loop exit. Return true if we + copied live ranges. */ +static bool +copy_live_ranges_to_removed_store_destinations (int regno) +{ + ira_allocno_t a, parent_a; + ira_loop_tree_node_t parent; + allocno_live_range_t r; + bool merged_p; + + merged_p = false; + for (a = ira_regno_allocno_map[regno]; + a != NULL; + a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) + { + if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))]) + /* This allocno will be removed. */ + continue; + /* Caps will be removed. */ + ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL); + for (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent; + parent != NULL; + parent = parent->parent) + if ((parent_a = parent->regno_allocno_map[regno]) == NULL + || (parent_a == regno_top_level_allocno_map[REGNO (ALLOCNO_REG + (parent_a))] + && ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a))) + break; + if (parent == NULL || parent_a == NULL) + continue; + if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL) + { + fprintf + (ira_dump_file, + " Coping ranges of a%dr%d to a%dr%d: ", + ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)), + ALLOCNO_NUM (parent_a), REGNO (ALLOCNO_REG (parent_a))); + ira_print_live_range_list (ira_dump_file, + ALLOCNO_LIVE_RANGES (a)); + } + r = copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a)); + change_allocno_in_range_list (r, parent_a); + ALLOCNO_LIVE_RANGES (parent_a) + = merge_ranges (r, ALLOCNO_LIVE_RANGES (parent_a)); + merged_p = true; + } + return merged_p; } /* Flatten the IR. In other words, this function transforms IR as if @@ -2066,20 +2104,16 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) int i, j, num; bool propagate_p, stop_p, keep_p; int hard_regs_num; - bool new_pseudos_p, merged_p; + bool new_pseudos_p, merged_p, mem_dest_p; unsigned int n; enum reg_class cover_class; ira_allocno_t a, parent_a, first, second, node_first, node_second; - ira_allocno_t dominator_a; ira_copy_t cp; - ira_loop_tree_node_t parent, node, dominator; + ira_loop_tree_node_t parent, node; allocno_live_range_t r; ira_allocno_iterator ai; ira_copy_iterator ci; sparseset allocnos_live; - /* Map: regno -> allocnos which will finally represent the regno for - IR with one region. */ - ira_allocno_t *regno_top_level_allocno_map; bool *allocno_propagated_p; regno_top_level_allocno_map @@ -2093,7 +2127,7 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) /* Fix final allocno attributes. */ for (i = max_regno_before_emit - 1; i >= FIRST_PSEUDO_REGISTER; i--) { - propagate_p = false; + mem_dest_p = propagate_p = false; for (a = ira_regno_allocno_map[i]; a != NULL; a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) @@ -2111,6 +2145,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) continue; } ira_assert (ALLOCNO_CAP_MEMBER (parent_a) == NULL); + if (ALLOCNO_MEM_OPTIMIZED_DEST (a) != NULL) + mem_dest_p = true; if (propagate_p) { if (!allocno_propagated_p [ALLOCNO_NUM (parent_a)]) @@ -2198,49 +2234,11 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) [ALLOCNO_REGNO (parent_a)])) == NULL) break; } - if (first != NULL) - { - parent_a = ALLOCNO_MEM_OPTIMIZED_DEST (first); - dominator = common_loop_tree_node_dominator - (ALLOCNO_LOOP_TREE_NODE (parent_a), - ALLOCNO_LOOP_TREE_NODE (first)); - dominator_a = dominator->regno_allocno_map[ALLOCNO_REGNO (a)]; - ira_assert (parent_a != NULL); - stop_p = first != a; - /* Remember that exit can be to a grandparent (not only - to a parent) or a child of the grandparent. */ - for (first = a;;) - { - if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL) - { - fprintf - (ira_dump_file, - " Coping ranges of a%dr%d to a%dr%d: ", - ALLOCNO_NUM (first), REGNO (ALLOCNO_REG (first)), - ALLOCNO_NUM (parent_a), - REGNO (ALLOCNO_REG (parent_a))); - ira_print_live_range_list (ira_dump_file, - ALLOCNO_LIVE_RANGES (first)); - } - r = copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES - (first)); - change_allocno_in_range_list (r, parent_a); - ALLOCNO_LIVE_RANGES (parent_a) - = merge_ranges (r, ALLOCNO_LIVE_RANGES (parent_a)); - merged_p = true; - if (stop_p) - break; - parent = ALLOCNO_LOOP_TREE_NODE (first)->parent; - ira_assert (parent != NULL); - first = parent->regno_allocno_map[ALLOCNO_REGNO (a)]; - ira_assert (first != NULL); - if (first == dominator_a) - break; - } - } ALLOCNO_COPIES (a) = NULL; regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))] = a; } + if (mem_dest_p && copy_live_ranges_to_removed_store_destinations (i)) + merged_p = true; } ira_free (allocno_propagated_p); ira_assert (new_pseudos_p || ira_max_point_before_emit == ira_max_point); diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c index 11199237d48..7fdaefb52e5 100644 --- a/gcc/ira-emit.c +++ b/gcc/ira-emit.c @@ -311,9 +311,11 @@ generate_edge_moves (edge e) if (REGNO (ALLOCNO_REG (src_allocno)) == REGNO (ALLOCNO_REG (dest_allocno))) continue; - /* Actually it is not a optimization we need this code because - the memory (remember about equivalent memory) might be ROM - (or placed in read only section). */ + /* Remove unnecessary stores at the region exit. We should do + this for readonly memory for sure and this is guaranteed by + that we never generate moves on region borders (see + checking ira_reg_equiv_invariant_p in function + change_loop). */ if (ALLOCNO_HARD_REGNO (dest_allocno) < 0 && ALLOCNO_HARD_REGNO (src_allocno) >= 0 && not_modified_p (src_allocno, dest_allocno)) |