OSDN Git Service

PR middle-end/42068
[pf3gnuchains/gcc-fork.git] / gcc / ira-emit.c
index 29f3fdf..9d66bfe 100644 (file)
@@ -1,5 +1,5 @@
 /* Integrated Register Allocator.  Changing code and generating moves.
-   Copyright (C) 2006, 2007, 2008
+   Copyright (C) 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
@@ -109,7 +109,7 @@ static void
 free_move_list (move_t head)
 {
   move_t next;
-  
+
   for (; head != NULL; head = next)
     {
       next = head->next;
@@ -129,6 +129,26 @@ eq_move_lists_p (move_t list1, move_t list2)
   return list1 == list2;
 }
 
+/* Print move list LIST into file F.  */
+static void
+print_move_list (FILE *f, move_t list)
+{
+  for (; list != NULL; list = list->next)
+    fprintf (f, " a%dr%d->a%dr%d",
+            ALLOCNO_NUM (list->from), ALLOCNO_REGNO (list->from),
+            ALLOCNO_NUM (list->to), ALLOCNO_REGNO (list->to));
+  fprintf (f, "\n");
+}
+
+extern void ira_debug_move_list (move_t list);
+
+/* Print move list LIST into stderr.  */
+void
+ira_debug_move_list (move_t list)
+{
+  print_move_list (stderr, list);
+}
+
 /* This recursive function changes pseudo-registers in *LOC if it is
    necessary.  The function returns TRUE if a change was done.  */
 static bool
@@ -430,7 +450,7 @@ change_loop (ira_loop_tree_node_t node)
 
   if (node != ira_loop_tree_root)
     {
-      
+
       if (node->bb != NULL)
        {
          FOR_BB_INSNS (node->bb, insn)
@@ -441,12 +461,12 @@ change_loop (ira_loop_tree_node_t node)
              }
          return;
        }
-      
+
       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
        fprintf (ira_dump_file,
                 "      Changing RTL for loop %d (header bb%d)\n",
                 node->loop->num, node->loop->header->index);
-      
+
       parent = ira_curr_loop_tree_node->parent;
       map = parent->regno_allocno_map;
       EXECUTE_IF_SET_IN_REG_SET (ira_curr_loop_tree_node->border_allocnos,
@@ -792,7 +812,8 @@ emit_move_list (move_t list, int freq)
        }
       else
        {
-         cost = ira_register_move_cost[mode][cover_class][cover_class] * freq;
+         cost = (ira_get_register_move_cost (mode, cover_class, cover_class)
+                 * freq);
          ira_shuffle_cost += cost;
        }
       ira_overall_cost += cost;
@@ -945,7 +966,14 @@ add_range_and_copies_from_move_list (move_t list, ira_loop_tree_node_t node,
                     REGNO (ALLOCNO_REG (from)));
        }
       else
-       r->finish = ira_max_point;
+       {
+         r->finish = ira_max_point;
+         if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
+           fprintf (ira_dump_file,
+                    "    Adding range [%d..%d] to allocno a%dr%d\n",
+                    r->start, ira_max_point, ALLOCNO_NUM (from),
+                    REGNO (ALLOCNO_REG (from)));
+       }
       ira_max_point++;
       ALLOCNO_LIVE_RANGES (to)
        = ira_create_allocno_live_range (to, ira_max_point, -1,
@@ -968,18 +996,18 @@ add_range_and_copies_from_move_list (move_t list, ira_loop_tree_node_t node,
   EXECUTE_IF_SET_IN_BITMAP (live_through, FIRST_PSEUDO_REGISTER, regno, bi)
     {
       a = node->regno_allocno_map[regno];
-      if (ALLOCNO_MEM_OPTIMIZED_DEST (a) == NULL)
-       {
-         ALLOCNO_LIVE_RANGES (a)
-           = ira_create_allocno_live_range (a, start, ira_max_point - 1,
-                                            ALLOCNO_LIVE_RANGES (a));
-         if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
-           fprintf
-             (ira_dump_file,
-              "    Adding range [%d..%d] to live through allocno a%dr%d\n",
-              start, ira_max_point - 1, ALLOCNO_NUM (a),
-              REGNO (ALLOCNO_REG (a)));
-       }
+      if ((to = ALLOCNO_MEM_OPTIMIZED_DEST (a)) != NULL)
+       a = to;
+      ALLOCNO_LIVE_RANGES (a)
+       = ira_create_allocno_live_range (a, start, ira_max_point - 1,
+                                        ALLOCNO_LIVE_RANGES (a));
+      if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
+       fprintf
+         (ira_dump_file,
+          "    Adding range [%d..%d] to live through %s allocno a%dr%d\n",
+          start, ira_max_point - 1,
+          to != NULL ? "upper level" : "",
+          ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)));
     }
 }
 
@@ -1025,6 +1053,7 @@ void
 ira_emit (bool loops_p)
 {
   basic_block bb;
+  rtx insn;
   edge_iterator ei;
   edge e;
   ira_allocno_t a;
@@ -1085,6 +1114,14 @@ ira_emit (bool loops_p)
   ira_free (allocno_last_set_check);
   ira_free (allocno_last_set);
   commit_edge_insertions ();
+  /* Fix insn codes.  It is necessary to do it before reload because
+     reload assumes initial insn codes defined.  The insn codes can be
+     invalidated by CFG infrastructure for example in jump
+     redirection.  */
+  FOR_EACH_BB (bb)
+    FOR_BB_INSNS_REVERSE (bb, insn)
+      if (INSN_P (insn))
+       recog_memoized (insn);
   ira_free (at_bb_end);
   ira_free (at_bb_start);
 }