summaryrefslogtreecommitdiff
path: root/gcc/ira-emit.c
diff options
context:
space:
mode:
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2008-11-19 21:25:00 +0000
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2008-11-19 21:25:00 +0000
commit0b1329df44f1534a74db0fa0c4f134fbdac5bbc7 (patch)
treeabbc12ec53d3e488d10d9e7e19b31568683777b9 /gcc/ira-emit.c
parent69f8e08094a3f6e518c08f323bc2687ffe696c9e (diff)
downloadgcc-0b1329df44f1534a74db0fa0c4f134fbdac5bbc7.tar.gz
2008-11-19 Vladimir Makarov <vmakarov@redhat.com>
PR bootstrap/37859 * ira-int.h (struct ira_loop_tree_node): New member entered_from_non_parent_p. * ira-color.c (print_loop_title): Print loop bbs. * ira-emit.c (entered_from_non_parent_p, setup_entered_from_non_parent_p): New functions. (not_modified_p): Rename to store_can_be_removed_p. Check there is no side entries. (generate_edge_moves): Use store_can_be_removed_p instead of not_modified_p. (ira_emit): Call setup_entered_from_non_parent_p. * ira-build.c (copy_info_to_removed_store_destinations): Accumulate CALL_FREQ, CALL_CROSSED_NUM, and ALLOCNO_EXCESS_PRESSURE_POINTS_NUM. (ira_flattening): Don't CHECK MEM_OPTIMIZED_DEST[_P], always update all accumulated attributes. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142018 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ira-emit.c')
-rw-r--r--gcc/ira-emit.c91
1 files changed, 78 insertions, 13 deletions
diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c
index 63c866b641a..29f3fdf6fa7 100644
--- a/gcc/ira-emit.c
+++ b/gcc/ira-emit.c
@@ -260,12 +260,63 @@ set_allocno_reg (ira_allocno_t allocno, rtx reg)
}
}
-/* Return TRUE if move of SRC_ALLOCNO to DEST_ALLOCNO does not change
- value of the destination. One possible reason for this is the
- situation when SRC_ALLOCNO is not modified in the corresponding
- loop. */
+/* Return true if there is an entry to given loop not from its parent
+ (or grandparent) block. For example, it is possible for two
+ adjacent loops inside another loop. */
static bool
-not_modified_p (ira_allocno_t src_allocno, ira_allocno_t dest_allocno)
+entered_from_non_parent_p (ira_loop_tree_node_t loop_node)
+{
+ ira_loop_tree_node_t bb_node, src_loop_node, parent;
+ edge e;
+ edge_iterator ei;
+
+ for (bb_node = loop_node->children; bb_node != NULL; bb_node = bb_node->next)
+ if (bb_node->bb != NULL)
+ {
+ FOR_EACH_EDGE (e, ei, bb_node->bb->preds)
+ if (e->src != ENTRY_BLOCK_PTR
+ && (src_loop_node = IRA_BB_NODE (e->src)->parent) != loop_node)
+ {
+ for (parent = src_loop_node->parent;
+ parent != NULL;
+ parent = parent->parent)
+ if (parent == loop_node)
+ break;
+ if (parent != NULL)
+ /* That is an exit from a nested loop -- skip it. */
+ continue;
+ for (parent = loop_node->parent;
+ parent != NULL;
+ parent = parent->parent)
+ if (src_loop_node == parent)
+ break;
+ if (parent == NULL)
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Set up ENTERED_FROM_NON_PARENT_P for each loop region. */
+static void
+setup_entered_from_non_parent_p (void)
+{
+ unsigned int i;
+ loop_p loop;
+
+ for (i = 0; VEC_iterate (loop_p, ira_loops.larray, i, loop); i++)
+ if (ira_loop_nodes[i].regno_allocno_map != NULL)
+ ira_loop_nodes[i].entered_from_non_parent_p
+ = entered_from_non_parent_p (&ira_loop_nodes[i]);
+}
+
+/* Return TRUE if move of SRC_ALLOCNO (assigned to hard register) to
+ DEST_ALLOCNO (assigned to memory) can be removed beacuse it does
+ not change value of the destination. One possible reason for this
+ is the situation when SRC_ALLOCNO is not modified in the
+ corresponding loop. */
+static bool
+store_can_be_removed_p (ira_allocno_t src_allocno, ira_allocno_t dest_allocno)
{
int regno, orig_regno;
ira_allocno_t a;
@@ -278,13 +329,26 @@ not_modified_p (ira_allocno_t src_allocno, ira_allocno_t dest_allocno)
for (node = ALLOCNO_LOOP_TREE_NODE (src_allocno);
node != NULL;
node = node->parent)
- if ((a = node->regno_allocno_map[orig_regno]) == NULL)
- break;
- else if (REGNO (ALLOCNO_REG (a)) == (unsigned) regno)
- return true;
- else if (bitmap_bit_p (node->modified_regnos, orig_regno))
- return false;
- return node != NULL;
+ {
+ a = node->regno_allocno_map[orig_regno];
+ ira_assert (a != NULL);
+ if (REGNO (ALLOCNO_REG (a)) == (unsigned) regno)
+ /* We achieved the destination and everything is ok. */
+ return true;
+ else if (bitmap_bit_p (node->modified_regnos, orig_regno))
+ return false;
+ else if (node->entered_from_non_parent_p)
+ /* If there is a path from a destination loop block to the
+ source loop header containing basic blocks of non-parents
+ (grandparents) of the source loop, we should have checked
+ modifications of the pseudo on this path too to decide
+ about possibility to remove the store. It could be done by
+ solving a data-flow problem. Unfortunately such global
+ solution would complicate IR flattening. Therefore we just
+ prohibit removal of the store in such complicated case. */
+ return false;
+ }
+ gcc_unreachable ();
}
/* Generate and attach moves to the edge E. This looks at the final
@@ -322,7 +386,7 @@ generate_edge_moves (edge e)
change_loop). */
if (ALLOCNO_HARD_REGNO (dest_allocno) < 0
&& ALLOCNO_HARD_REGNO (src_allocno) >= 0
- && not_modified_p (src_allocno, dest_allocno))
+ && store_can_be_removed_p (src_allocno, dest_allocno))
{
ALLOCNO_MEM_OPTIMIZED_DEST (src_allocno) = dest_allocno;
ALLOCNO_MEM_OPTIMIZED_DEST_P (dest_allocno) = true;
@@ -983,6 +1047,7 @@ ira_emit (bool loops_p)
ira_free_bitmap (used_regno_bitmap);
ira_free_bitmap (renamed_regno_bitmap);
ira_free_bitmap (local_allocno_bitmap);
+ setup_entered_from_non_parent_p ();
FOR_EACH_BB (bb)
{
at_bb_start[bb->index] = NULL;