aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/ira-build.c28
-rw-r--r--gcc/ira-color.c19
-rw-r--r--gcc/ira-emit.c91
-rw-r--r--gcc/ira-int.h5
5 files changed, 135 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eacb5e0..b21a632 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,26 @@
-2008-11-15 Vladimir Makarov <vmakarov@redhat.com>
+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.
+
+2008-11-19 Vladimir Makarov <vmakarov@redhat.com>
PR bootstrap/37790
* ira-int.h (ira_copy_allocno_live_range_list,
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index af1d174..e4ed601 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -2193,6 +2193,11 @@ copy_info_to_removed_store_destinations (int regno)
if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true;
#endif
+ ALLOCNO_CALL_FREQ (parent_a) += ALLOCNO_CALL_FREQ (a);
+ ALLOCNO_CALLS_CROSSED_NUM (parent_a)
+ += ALLOCNO_CALLS_CROSSED_NUM (a);
+ ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
+ += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
merged_p = true;
}
return merged_p;
@@ -2208,7 +2213,7 @@ void
ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
{
int i, j, num;
- bool stop_p, keep_p;
+ bool keep_p;
int hard_regs_num;
bool new_pseudos_p, merged_p, mem_dest_p;
unsigned int n;
@@ -2293,26 +2298,15 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
continue;
}
new_pseudos_p = true;
- first = ALLOCNO_MEM_OPTIMIZED_DEST (a) == NULL ? NULL : a;
- stop_p = false;
for (;;)
{
- if (first == NULL
- && ALLOCNO_MEM_OPTIMIZED_DEST (parent_a) != NULL)
- first = parent_a;
ALLOCNO_NREFS (parent_a) -= ALLOCNO_NREFS (a);
ALLOCNO_FREQ (parent_a) -= ALLOCNO_FREQ (a);
- if (first != NULL
- && ALLOCNO_MEM_OPTIMIZED_DEST (first) == parent_a)
- stop_p = true;
- else if (!stop_p)
- {
- ALLOCNO_CALL_FREQ (parent_a) -= ALLOCNO_CALL_FREQ (a);
- ALLOCNO_CALLS_CROSSED_NUM (parent_a)
- -= ALLOCNO_CALLS_CROSSED_NUM (a);
- ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
- -= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
- }
+ ALLOCNO_CALL_FREQ (parent_a) -= ALLOCNO_CALL_FREQ (a);
+ ALLOCNO_CALLS_CROSSED_NUM (parent_a)
+ -= ALLOCNO_CALLS_CROSSED_NUM (a);
+ ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
+ -= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
ira_assert (ALLOCNO_CALLS_CROSSED_NUM (parent_a) >= 0
&& ALLOCNO_NREFS (parent_a) >= 0
&& ALLOCNO_FREQ (parent_a) >= 0);
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index 7343e0c..c3b63cc 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -1703,15 +1703,32 @@ print_loop_title (ira_loop_tree_node_t loop_tree_node)
{
unsigned int j;
bitmap_iterator bi;
+ ira_loop_tree_node_t subloop_node, dest_loop_node;
+ edge e;
+ edge_iterator ei;
ira_assert (loop_tree_node->loop != NULL);
fprintf (ira_dump_file,
- "\n Loop %d (parent %d, header bb%d, depth %d)\n all:",
+ "\n Loop %d (parent %d, header bb%d, depth %d)\n bbs:",
loop_tree_node->loop->num,
(loop_tree_node->parent == NULL
? -1 : loop_tree_node->parent->loop->num),
loop_tree_node->loop->header->index,
loop_depth (loop_tree_node->loop));
+ for (subloop_node = loop_tree_node->children;
+ subloop_node != NULL;
+ subloop_node = subloop_node->next)
+ if (subloop_node->bb != NULL)
+ {
+ fprintf (ira_dump_file, " %d", subloop_node->bb->index);
+ FOR_EACH_EDGE (e, ei, subloop_node->bb->succs)
+ if (e->dest != EXIT_BLOCK_PTR
+ && ((dest_loop_node = IRA_BB_NODE (e->dest)->parent)
+ != loop_tree_node))
+ fprintf (ira_dump_file, "(->%d:l%d)",
+ e->dest->index, dest_loop_node->loop->num);
+ }
+ fprintf (ira_dump_file, "\n all:");
EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->all_allocnos, 0, j, bi)
fprintf (ira_dump_file, " %dr%d", j, ALLOCNO_REGNO (ira_allocnos[j]));
fprintf (ira_dump_file, "\n modified regnos:");
diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c
index 63c866b..29f3fdf 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;
diff --git a/gcc/ira-int.h b/gcc/ira-int.h
index 7f5479b..659c1ee 100644
--- a/gcc/ira-int.h
+++ b/gcc/ira-int.h
@@ -107,6 +107,11 @@ struct ira_loop_tree_node
one cap with the same regno in a region). */
ira_allocno_t *regno_allocno_map;
+ /* True if there is an entry to given loop not from its parent (or
+ grandparent) basic block. For example, it is possible for two
+ adjacent loops inside another loop. */
+ bool entered_from_non_parent_p;
+
/* Maximal register pressure inside loop for given register class
(defined only for the cover classes). */
int reg_pressure[N_REG_CLASSES];