OSDN Git Service

2009-01-05 Vladimir Makarov <vmakarov@redhat.com>
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Jan 2009 03:50:07 +0000 (03:50 +0000)
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Jan 2009 03:50:07 +0000 (03:50 +0000)
PR rtl-optimization/38583
* params.h (IRA_MAX_CONFLICT_TABLE_SIZE): New macro.

* params.def (ira-max-conflict-table-size): New.

* doc/invoke.texi (ira-max-conflict-table-size): Decribe.

* ira.h (ira_conflicts_p): New external definition.

* ira-conflicts.c (build_conflict_bit_table): Do not build too big
table.  Report this.  Return result of building.
(ira_build_conflicts): Use ira_conflicts_p.  Check result of
building conflict table.

* ira-color.c (fast_allocation): Use num instead of
ira_allocnos_num.
(ira_color): Use ira_conflicts_p.

* global.c: Include ira.h.
(pseudo_for_reload_consideration_p, build_insn_chain): Use
ira_conflicts_p.

* Makefile.in (global.o): Add ira.h.

* ira-build.c (mark_all_loops_for_removal,
propagate_some_info_from_allocno): New.
(remove_unnecessary_allocnos): Call
propagate_some_info_from_allocno.
(remove_low_level_allocnos): New.
(remove_unnecessary_regions): Add parameter.  Call
mark_all_loops_for_removal and remove_low_level_allocnos.  Pass
parameter to remove_unnecessary_regions.
(ira_build): Remove all regions but root if the conflict table was
not built.  Update conflict hard regs for allocnos crossing calls.

* ira.c (ira_conflicts_p): New global.
(ira): Define and use ira_conflicts_p.

* reload1.c (compute_use_by_pseudos, reload, count_pseudo,
count_spilled_pseudo, find_reg, alter_reg, finish_spills,
emit_input_reload_insns, delete_output_reload): Use
ira_conflicts_p.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@143112 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/doc/invoke.texi
gcc/global.c
gcc/ira-build.c
gcc/ira-color.c
gcc/ira-conflicts.c
gcc/ira.c
gcc/ira.h
gcc/params.def
gcc/params.h
gcc/reload1.c

index 5853ca8..0fda2b4 100644 (file)
@@ -1,3 +1,48 @@
+2009-01-05  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/38583
+       * params.h (IRA_MAX_CONFLICT_TABLE_SIZE): New macro.
+
+       * params.def (ira-max-conflict-table-size): New.
+
+       * doc/invoke.texi (ira-max-conflict-table-size): Decribe.
+       
+       * ira.h (ira_conflicts_p): New external definition.
+       
+       * ira-conflicts.c (build_conflict_bit_table): Do not build too big
+       table.  Report this.  Return result of building.
+       (ira_build_conflicts): Use ira_conflicts_p.  Check result of
+       building conflict table.
+
+       * ira-color.c (fast_allocation): Use num instead of
+       ira_allocnos_num.
+       (ira_color): Use ira_conflicts_p.
+       
+       * global.c: Include ira.h.
+       (pseudo_for_reload_consideration_p, build_insn_chain): Use
+       ira_conflicts_p.
+
+       * Makefile.in (global.o): Add ira.h.
+       
+       * ira-build.c (mark_all_loops_for_removal,
+       propagate_some_info_from_allocno): New.
+       (remove_unnecessary_allocnos): Call
+       propagate_some_info_from_allocno.
+       (remove_low_level_allocnos): New.
+       (remove_unnecessary_regions): Add parameter.  Call
+       mark_all_loops_for_removal and remove_low_level_allocnos.  Pass
+       parameter to remove_unnecessary_regions.
+       (ira_build): Remove all regions but root if the conflict table was
+       not built.  Update conflict hard regs for allocnos crossing calls.
+
+       * ira.c (ira_conflicts_p): New global.
+       (ira): Define and use ira_conflicts_p.
+
+       * reload1.c (compute_use_by_pseudos, reload, count_pseudo,
+       count_spilled_pseudo, find_reg, alter_reg, finish_spills,
+       emit_input_reload_insns, delete_output_reload): Use
+       ira_conflicts_p.
+       
 2009-01-06  Ben Elliston  <bje@au.ibm.com>
 
        * gengtype-lex.l (YY_NO_INPUT): Define.
index 1b89c0d..83c5036 100644 (file)
@@ -2860,7 +2860,7 @@ bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H)  coretypes.h $(TM_H) $(RTL_H) \
 global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(FLAGS_H) reload.h $(FUNCTION_H) $(RECOG_H) $(REGS_H) hard-reg-set.h \
    insn-config.h output.h $(TOPLEV_H) $(TM_P_H) $(MACHMODE_H) tree-pass.h \
-   $(TIMEVAR_H) vecprim.h $(DF_H) $(DBGCNT_H) $(RA_H)
+   $(TIMEVAR_H) vecprim.h $(DF_H) $(DBGCNT_H) $(RA_H) ira.h
 ra-conflict.o : ra-conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(FLAGS_H) reload.h $(FUNCTION_H) $(RECOG_H) $(REGS_H) hard-reg-set.h \
    insn-config.h output.h $(TOPLEV_H) $(TM_P_H) $(MACHMODE_H) tree-pass.h \
index 12a3cab..47e718b 100644 (file)
@@ -7617,6 +7617,15 @@ given number of the most frequently executed loops will form regions
 for the regional register allocation.  The default value of the
 parameter is 100.
 
+@item ira-max-conflict-table-size
+Although IRA uses a sophisticated algorithm of compression conflict
+table, the table can be still big for huge functions.  If the conflict
+table for a function could be more than size in MB given by the
+parameter, the conflict table is not built and faster, simpler, and
+lower quality register allocation algorithm will be used.  The
+algorithm do not use pseudo-register conflicts.  The default value of
+the parameter is 2000.
+
 @end table
 @end table
 
index 824fcf0..abf070d 100644 (file)
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "vecprim.h"
 #include "dbgcnt.h"
 #include "ra.h"
+#include "ira.h"
 
 /* This pass of the compiler performs global register allocation.
    It assigns hard register numbers to all the pseudo registers
@@ -1394,7 +1395,7 @@ pseudo_for_reload_consideration_p (int regno)
   /* Consider spilled pseudos too for IRA because they still have a
      chance to get hard-registers in the reload when IRA is used.  */
   return (reg_renumber[regno] >= 0
-         || (flag_ira && optimize && flag_ira_share_spill_slots));
+         || (flag_ira && ira_conflicts_p && flag_ira_share_spill_slots));
 }
 
 /* Walk the insns of the current function and build reload_insn_chain,
@@ -1483,7 +1484,7 @@ build_insn_chain (void)
 
                    if ((regno < FIRST_PSEUDO_REGISTER
                         || reg_renumber[regno] >= 0
-                        || (flag_ira && optimize))
+                        || (flag_ira && ira_conflicts_p))
                        && (!DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)))
                      {
                        rtx reg = DF_REF_REG (def);
index 9e47333..00df69c 100644 (file)
@@ -1751,6 +1751,33 @@ mark_loops_for_removal (void)
   ira_free (sorted_loops);
 }
 
+/* Mark all loops but root for removing.  */
+static void
+mark_all_loops_for_removal (void)
+{
+  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)
+      {
+       if (ira_loop_nodes[i].parent == NULL)
+         {
+           /* Don't remove the root.  */
+           ira_loop_nodes[i].to_remove_p = false;
+           continue;
+         }
+       ira_loop_nodes[i].to_remove_p = true;
+       if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
+         fprintf
+           (ira_dump_file,
+            "  Mark loop %d (header %d, freq %d, depth %d) for removal\n",
+            ira_loop_nodes[i].loop->num,
+            ira_loop_nodes[i].loop->header->index,
+            ira_loop_nodes[i].loop->header->frequency,
+            loop_depth (ira_loop_nodes[i].loop));
+      }
+}
 
 /* Definition of vector of loop tree nodes.  */
 DEF_VEC_P(ira_loop_tree_node_t);
@@ -1856,6 +1883,43 @@ ira_rebuild_regno_allocno_list (int regno)
     fprintf (ira_dump_file, " Rebuilding regno allocno list for %d\n", regno);
 }
 
+/* Propagate info from allocno FROM_A to allocno A.  */
+static void
+propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a)
+{
+  enum reg_class cover_class;
+
+  IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
+                   ALLOCNO_CONFLICT_HARD_REGS (from_a));
+#ifdef STACK_REGS
+  if (ALLOCNO_NO_STACK_REG_P (from_a))
+    ALLOCNO_NO_STACK_REG_P (a) = true;
+#endif
+  ALLOCNO_NREFS (a) += ALLOCNO_NREFS (from_a);
+  ALLOCNO_FREQ (a) += ALLOCNO_FREQ (from_a);
+  ALLOCNO_CALL_FREQ (a) += ALLOCNO_CALL_FREQ (from_a);
+  IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
+                   ALLOCNO_TOTAL_CONFLICT_HARD_REGS (from_a));
+  ALLOCNO_CALLS_CROSSED_NUM (a) += ALLOCNO_CALLS_CROSSED_NUM (from_a);
+  ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
+    += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a);
+  if (! ALLOCNO_BAD_SPILL_P (from_a))
+    ALLOCNO_BAD_SPILL_P (a) = false;
+#ifdef STACK_REGS
+  if (ALLOCNO_TOTAL_NO_STACK_REG_P (from_a))
+    ALLOCNO_TOTAL_NO_STACK_REG_P (a) = true;
+#endif
+  cover_class = ALLOCNO_COVER_CLASS (from_a);
+  ira_assert (cover_class == ALLOCNO_COVER_CLASS (a));
+  ira_allocate_and_accumulate_costs (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
+                                    ALLOCNO_HARD_REG_COSTS (from_a));
+  ira_allocate_and_accumulate_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
+                                    cover_class,
+                                    ALLOCNO_CONFLICT_HARD_REG_COSTS (from_a));
+  ALLOCNO_COVER_CLASS_COST (a) += ALLOCNO_COVER_CLASS_COST (from_a);
+  ALLOCNO_MEMORY_COST (a) += ALLOCNO_MEMORY_COST (from_a);
+}
+
 /* Remove allocnos from loops removed from the allocation
    consideration.  */
 static void
@@ -1863,7 +1927,6 @@ remove_unnecessary_allocnos (void)
 {
   int regno;
   bool merged_p, rebuild_p;
-  enum reg_class cover_class;
   ira_allocno_t a, prev_a, next_a, parent_a;
   ira_loop_tree_node_t a_node, parent;
   allocno_live_range_t r;
@@ -1890,9 +1953,9 @@ remove_unnecessary_allocnos (void)
                ;
              if (parent_a == NULL)
                {
-               /* There are no allocnos with the same regno in upper
-                  region -- just move the allocno to the upper
-                  region.  */
+                 /* There are no allocnos with the same regno in
+                    upper region -- just move the allocno to the
+                    upper region.  */
                  prev_a = a;
                  ALLOCNO_LOOP_TREE_NODE (a) = parent;
                  parent->regno_allocno_map[regno] = a;
@@ -1911,43 +1974,10 @@ remove_unnecessary_allocnos (void)
                  change_allocno_in_range_list (r, parent_a);
                  ALLOCNO_LIVE_RANGES (parent_a)
                    = ira_merge_allocno_live_ranges
-                   (r, ALLOCNO_LIVE_RANGES (parent_a));
+                     (r, ALLOCNO_LIVE_RANGES (parent_a));
                  merged_p = true;
                  ALLOCNO_LIVE_RANGES (a) = NULL;
-                 IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (parent_a),
-                                   ALLOCNO_CONFLICT_HARD_REGS (a));
-#ifdef STACK_REGS
-                 if (ALLOCNO_NO_STACK_REG_P (a))
-                   ALLOCNO_NO_STACK_REG_P (parent_a) = true;
-#endif
-                 ALLOCNO_NREFS (parent_a) += ALLOCNO_NREFS (a);
-                 ALLOCNO_FREQ (parent_a) += ALLOCNO_FREQ (a);
-                 ALLOCNO_CALL_FREQ (parent_a) += ALLOCNO_CALL_FREQ (a);
-                 IOR_HARD_REG_SET
-                   (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a),
-                    ALLOCNO_TOTAL_CONFLICT_HARD_REGS (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);
-                 if (! ALLOCNO_BAD_SPILL_P (a))
-                   ALLOCNO_BAD_SPILL_P (parent_a) = false;
-#ifdef STACK_REGS
-                 if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
-                   ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true;
-#endif
-                 cover_class = ALLOCNO_COVER_CLASS (a);
-                 ira_assert (cover_class == ALLOCNO_COVER_CLASS (parent_a));
-                 ira_allocate_and_accumulate_costs
-                   (&ALLOCNO_HARD_REG_COSTS (parent_a), cover_class,
-                    ALLOCNO_HARD_REG_COSTS (a));
-                 ira_allocate_and_accumulate_costs
-                   (&ALLOCNO_CONFLICT_HARD_REG_COSTS (parent_a),
-                    cover_class,
-                    ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
-                 ALLOCNO_COVER_CLASS_COST (parent_a)
-                   += ALLOCNO_COVER_CLASS_COST (a);
-                 ALLOCNO_MEMORY_COST (parent_a) += ALLOCNO_MEMORY_COST (a);
+                 propagate_some_info_from_allocno (parent_a, a);
                  finish_allocno (a);
                }
            }
@@ -1968,15 +1998,88 @@ remove_unnecessary_allocnos (void)
     ira_free (regno_allocnos);
 }
 
-/* Remove loops from consideration.  We remove loops for which a
-   separate allocation will not improve the result.  We have to do
-   this after allocno creation and their costs and cover class
-   evaluation because only after that the register pressure can be
-   known and is calculated.  */
+/* Remove allocnos from all loops but the root.  */
 static void
-remove_unnecessary_regions (void)
+remove_low_level_allocnos (void)
 {
-  mark_loops_for_removal ();
+  int regno;
+  bool merged_p, propagate_p;
+  ira_allocno_t a, top_a;
+  ira_loop_tree_node_t a_node, parent;
+  allocno_live_range_t r;
+  ira_allocno_iterator ai;
+
+  merged_p = false;
+  FOR_EACH_ALLOCNO (a, ai)
+    {
+      a_node = ALLOCNO_LOOP_TREE_NODE (a);
+      if (a_node == ira_loop_tree_root || ALLOCNO_CAP_MEMBER (a) != NULL)
+       continue;
+      regno = ALLOCNO_REGNO (a);
+      if ((top_a = ira_loop_tree_root->regno_allocno_map[regno]) == NULL)
+       {
+         ALLOCNO_LOOP_TREE_NODE (a) = ira_loop_tree_root;
+         ira_loop_tree_root->regno_allocno_map[regno] = a;
+         continue;
+       }
+      propagate_p = a_node->parent->regno_allocno_map[regno] == NULL;
+      /* Remove the allocno and update info of allocno in the upper
+        region.  */
+      r = ALLOCNO_LIVE_RANGES (a);
+      change_allocno_in_range_list (r, top_a);
+      ALLOCNO_LIVE_RANGES (top_a)
+       = ira_merge_allocno_live_ranges (r, ALLOCNO_LIVE_RANGES (top_a));
+      merged_p = true;
+      ALLOCNO_LIVE_RANGES (a) = NULL;
+      if (propagate_p)
+       propagate_some_info_from_allocno (top_a, a);
+    }
+  FOR_EACH_ALLOCNO (a, ai)
+    {
+      a_node = ALLOCNO_LOOP_TREE_NODE (a);
+      if (a_node == ira_loop_tree_root)
+       continue;
+      parent = a_node->parent;
+      regno = ALLOCNO_REGNO (a);
+      if (ALLOCNO_CAP_MEMBER (a) != NULL)
+       ira_assert (ALLOCNO_CAP (a) != NULL);
+      else if (ALLOCNO_CAP (a) == NULL)
+       ira_assert (parent->regno_allocno_map[regno] != NULL);
+    }
+  FOR_EACH_ALLOCNO (a, ai)
+    {
+      regno = ALLOCNO_REGNO (a);
+      if (ira_loop_tree_root->regno_allocno_map[regno] == a)
+       {
+         ira_regno_allocno_map[regno] = a;
+         ALLOCNO_NEXT_REGNO_ALLOCNO (a) = NULL;
+         ALLOCNO_CAP_MEMBER (a) = NULL;
+         COPY_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
+                            ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+#ifdef STACK_REGS
+         if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
+           ALLOCNO_NO_STACK_REG_P (a) = true;
+#endif
+       }
+      else
+       finish_allocno (a);
+    }
+  if (merged_p)
+    ira_rebuild_start_finish_chains ();
+}
+
+/* Remove loops from consideration.  We remove all loops except for
+   root if ALL_P or loops for which a separate allocation will not
+   improve the result.  We have to do this after allocno creation and
+   their costs and cover class evaluation because only after that the
+   register pressure can be known and is calculated.  */
+static void
+remove_unnecessary_regions (bool all_p)
+{
+  if (all_p)
+    mark_all_loops_for_removal ();
+  else
+    mark_loops_for_removal ();
   children_vec
     = VEC_alloc (ira_loop_tree_node_t, heap,
                 last_basic_block + VEC_length (loop_p, ira_loops.larray));
@@ -1985,7 +2088,10 @@ remove_unnecessary_regions (void)
                 last_basic_block + VEC_length (loop_p, ira_loops.larray));
   remove_uneccesary_loop_nodes_from_loop_tree (ira_loop_tree_root) ;
   VEC_free (ira_loop_tree_node_t, heap, children_vec);
-  remove_unnecessary_allocnos ();
+  if (all_p)
+    remove_low_level_allocnos ();
+  else
+    remove_unnecessary_allocnos ();
   while (VEC_length (ira_loop_tree_node_t, removed_loop_vec) > 0)
     finish_loop_tree_node (VEC_pop (ira_loop_tree_node_t, removed_loop_vec));
   VEC_free (ira_loop_tree_node_t, heap, removed_loop_vec);
@@ -2668,7 +2774,7 @@ ira_build (bool loops_p)
   create_allocnos ();
   ira_costs ();
   ira_create_allocno_live_ranges ();
-  remove_unnecessary_regions ();
+  remove_unnecessary_regions (false);
   ira_compress_allocno_live_ranges ();
   update_bad_spill_attribute ();
   loops_p = more_one_region_p ();
@@ -2685,6 +2791,29 @@ ira_build (bool loops_p)
   sort_conflict_id_allocno_map ();
   setup_min_max_conflict_allocno_ids ();
   ira_build_conflicts ();
+  if (! ira_conflicts_p)
+    {
+      ira_allocno_t a;
+      ira_allocno_iterator ai;
+
+      /* Remove all regions but root one.  */
+      if (loops_p)
+       {
+         remove_unnecessary_regions (true);
+         loops_p = false;
+       }
+      /* We don't save hard registers around calls for fast allocation
+        -- add caller clobbered registers as conflicting ones to
+        allocno crossing calls.  */
+      FOR_EACH_ALLOCNO (a, ai)
+       if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
+         {
+           IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
+                             call_used_reg_set);
+           IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
+                             call_used_reg_set);
+         }
+    }
   if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
     print_copies (ira_dump_file);
   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
index c9cb184..c7c600b 100644 (file)
@@ -3267,7 +3267,7 @@ fast_allocation (void)
                                                  * ira_max_point);
   for (i = 0; i < ira_max_point; i++)
     CLEAR_HARD_REG_SET (used_hard_regs[i]);
-  qsort (sorted_allocnos, ira_allocnos_num, sizeof (ira_allocno_t), 
+  qsort (sorted_allocnos, num, sizeof (ira_allocno_t),
         allocno_priority_compare_func);
   for (i = 0; i < num; i++)
     {
@@ -3329,7 +3329,7 @@ ira_color (void)
       ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a);
       ALLOCNO_UPDATED_COVER_CLASS_COST (a) = ALLOCNO_COVER_CLASS_COST (a);
     }
-  if (optimize)
+  if (ira_conflicts_p)
     color ();
   else
     fast_allocation ();
index ff116b5..244d3bc 100644 (file)
@@ -60,8 +60,10 @@ static IRA_INT_TYPE **conflicts;
 
 \f
 
-/* Build allocno conflict table by processing allocno live ranges.  */
-static void
+/* Build allocno conflict table by processing allocno live ranges.
+   Return true if the table was built.  The table is not built if it
+   is too big.  */
+static bool
 build_conflict_bit_table (void)
 {
   int i, num, id, allocated_words_num, conflict_bit_vec_words_num;
@@ -74,6 +76,26 @@ build_conflict_bit_table (void)
   int allocno_set_words;
 
   allocno_set_words = (ira_allocnos_num + IRA_INT_BITS - 1) / IRA_INT_BITS;
+  allocated_words_num = 0;
+  FOR_EACH_ALLOCNO (allocno, ai)
+    {
+      if (ALLOCNO_MAX (allocno) < ALLOCNO_MIN (allocno))
+         continue;
+      conflict_bit_vec_words_num
+       = ((ALLOCNO_MAX (allocno) - ALLOCNO_MIN (allocno) + IRA_INT_BITS)
+          / IRA_INT_BITS);
+      allocated_words_num += conflict_bit_vec_words_num;
+      if ((unsigned long long) allocated_words_num * sizeof (IRA_INT_TYPE)
+         > (unsigned long long) IRA_MAX_CONFLICT_TABLE_SIZE * 1024 * 1024)
+       {
+         if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
+           fprintf
+             (ira_dump_file,
+              "+++Conflict table will be too big(>%dMB) -- don't use it\n",
+              IRA_MAX_CONFLICT_TABLE_SIZE);
+         return false;
+       }
+    }
   allocnos_live = sparseset_alloc (ira_allocnos_num);
   conflicts = (IRA_INT_TYPE **) ira_allocate (sizeof (IRA_INT_TYPE *)
                                              * ira_allocnos_num);
@@ -134,6 +156,7 @@ build_conflict_bit_table (void)
        sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (r->allocno));
     }
   sparseset_free (allocnos_live);
+  return true;
 }
 
 \f
@@ -743,29 +766,34 @@ ira_build_conflicts (void)
   ira_allocno_iterator ai;
   HARD_REG_SET temp_hard_reg_set;
 
-  if (optimize)
+  if (ira_conflicts_p)
     {
-      build_conflict_bit_table ();
-      build_conflicts ();
-      ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, add_copies);
-      /* We need finished conflict table for the subsequent call.  */
-      if (flag_ira_region == IRA_REGION_ALL
-         || flag_ira_region == IRA_REGION_MIXED)
-       propagate_copies ();
-      /* Now we can free memory for the conflict table (see function
-        build_allocno_conflicts for details).  */
-      FOR_EACH_ALLOCNO (a, ai)
+      ira_conflicts_p = build_conflict_bit_table ();
+      if (ira_conflicts_p)
        {
-         if (ALLOCNO_CONFLICT_ALLOCNO_ARRAY (a) != conflicts[ALLOCNO_NUM (a)])
-           ira_free (conflicts[ALLOCNO_NUM (a)]);
+         build_conflicts ();
+         ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, add_copies);
+         /* We need finished conflict table for the subsequent call.  */
+         if (flag_ira_region == IRA_REGION_ALL
+             || flag_ira_region == IRA_REGION_MIXED)
+           propagate_copies ();
+         /* Now we can free memory for the conflict table (see function
+            build_allocno_conflicts for details).  */
+         FOR_EACH_ALLOCNO (a, ai)
+           {
+             if (ALLOCNO_CONFLICT_ALLOCNO_ARRAY (a)
+                 != conflicts[ALLOCNO_NUM (a)])
+               ira_free (conflicts[ALLOCNO_NUM (a)]);
+           }
+         ira_free (conflicts);
        }
-      ira_free (conflicts);
     }
   if (! CLASS_LIKELY_SPILLED_P (BASE_REG_CLASS))
     CLEAR_HARD_REG_SET (temp_hard_reg_set);
   else
     {
-      COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[BASE_REG_CLASS]);
+      COPY_HARD_REG_SET (temp_hard_reg_set,
+                        reg_class_contents[BASE_REG_CLASS]);
       AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs);
       AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set);
     }
@@ -796,6 +824,7 @@ ira_build_conflicts (void)
            }
        }
     }
-  if (optimize && internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
+  if (optimize && ira_conflicts_p
+      && internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
     print_conflicts (ira_dump_file, false);
 }
index 44f7032..2273512 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1827,6 +1827,10 @@ too_high_register_pressure_p (void)
 /* All natural loops.  */
 struct loops ira_loops;
 
+/* True if we have allocno conflicts.  It is false for non-optimized
+   mode or when the conflict table is too big.  */
+bool ira_conflicts_p;
+
 /* This is the main entry of IRA.  */
 static void
 ira (FILE *f)
@@ -1851,6 +1855,7 @@ ira (FILE *f)
       ira_dump_file = stderr;
     }
 
+  ira_conflicts_p = optimize > 0;
   setup_prohibited_mode_move_regs ();
 
   df_note_add_problem ();
@@ -1916,6 +1921,8 @@ ira (FILE *f)
   loops_p = ira_build (optimize
                       && (flag_ira_region == IRA_REGION_ALL
                           || flag_ira_region == IRA_REGION_MIXED));
+  
+  ira_assert (ira_conflicts_p || !loops_p);
 
   saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots;
   if (too_high_register_pressure_p ())
@@ -1929,7 +1936,7 @@ ira (FILE *f)
       
   ira_emit (loops_p);
   
-  if (optimize)
+  if (ira_conflicts_p)
     {
       max_regno = max_reg_num ();
       
@@ -1963,7 +1970,7 @@ ira (FILE *f)
   calculate_allocation_cost ();
   
 #ifdef ENABLE_IRA_CHECKING
-  if (optimize)
+  if (ira_conflicts_p)
     check_allocation ();
 #endif
       
@@ -1992,7 +1999,7 @@ ira (FILE *f)
   allocate_initial_values (reg_equiv_memory_loc);
 
   overall_cost_before = ira_overall_cost;
-  if (optimize)
+  if (ira_conflicts_p)
     {
       fix_reg_equiv_init ();
       
@@ -2015,13 +2022,13 @@ ira (FILE *f)
   df_set_flags (DF_NO_INSN_RESCAN);
   build_insn_chain ();
 
-  reload_completed = !reload (get_insns (), optimize > 0);
+  reload_completed = !reload (get_insns (), ira_conflicts_p);
 
   timevar_pop (TV_RELOAD);
 
   timevar_push (TV_IRA);
 
-  if (optimize)
+  if (ira_conflicts_p)
     {
       ira_free (ira_spilled_reg_stack_slots);
       
index 5f964c4..165274d 100644 (file)
--- a/gcc/ira.h
+++ b/gcc/ira.h
@@ -20,6 +20,10 @@ You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+/* True if we have allocno conflicts.  It is false for non-optimized
+   mode or when the conflict table is too big.  */
+extern bool ira_conflicts_p;
+
 extern void ira_init_once (void);
 extern void ira_init (void);
 extern void ira_finish_once (void);
index ea3015b..d09a858 100644 (file)
@@ -750,6 +750,11 @@ DEFPARAM (PARAM_IRA_MAX_LOOPS_NUM,
          "max loops number for regional RA",
          100, 0, 0)
 
+DEFPARAM (PARAM_IRA_MAX_CONFLICT_TABLE_SIZE,
+         "ira-max-conflict-table-size",
+         "max size of conflict table in MB",
+         2000, 0, 0)
+
 /* Switch initialization conversion will refuse to create arrays that are
    bigger than this parameter times the number of switch branches.  */
 
index 8147b60..501259c 100644 (file)
@@ -169,6 +169,8 @@ typedef enum compiler_param
   PARAM_VALUE (PARAM_USE_CANONICAL_TYPES)
 #define IRA_MAX_LOOPS_NUM \
   PARAM_VALUE (PARAM_IRA_MAX_LOOPS_NUM)
+#define IRA_MAX_CONFLICT_TABLE_SIZE \
+  PARAM_VALUE (PARAM_IRA_MAX_CONFLICT_TABLE_SIZE)
 #define SWITCH_CONVERSION_BRANCH_RATIO \
   PARAM_VALUE (PARAM_SWITCH_CONVERSION_BRANCH_RATIO)
 #endif /* ! GCC_PARAMS_H */
index ffde2bf..bbffad0 100644 (file)
@@ -557,7 +557,7 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from)
             which might still contain registers that have not
             actually been allocated since they have an
             equivalence.  */
-         gcc_assert ((flag_ira && optimize) || reload_completed);
+         gcc_assert ((flag_ira && ira_conflicts_p) || reload_completed);
        }
       else
        add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
@@ -901,7 +901,7 @@ reload (rtx first, int global)
   for (n = 0, i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
     temp_pseudo_reg_arr[n++] = i;
   
-  if (flag_ira && optimize)
+  if (flag_ira && ira_conflicts_p)
     /* Ask IRA to order pseudo-registers for better stack slot
        sharing.  */
     ira_sort_regnos_for_alter_reg (temp_pseudo_reg_arr, n, reg_max_ref_width);
@@ -1055,7 +1055,7 @@ reload (rtx first, int global)
 
       calculate_needs_all_insns (global);
 
-      if (! flag_ira || ! optimize)
+      if (! flag_ira || ! ira_conflicts_p)
        /* Don't do it for IRA.  We need this info because we don't
           change live_throughout and dead_or_set for chains when IRA
           is used.  */
@@ -1614,7 +1614,7 @@ calculate_needs_all_insns (int global)
                                       reg_equiv_memory_loc
                                       [REGNO (SET_DEST (set))]))))
                {
-                 if (flag_ira && optimize)
+                 if (flag_ira && ira_conflicts_p)
                    /* Inform IRA about the insn deletion.  */
                    ira_mark_memory_move_deletion (REGNO (SET_DEST (set)),
                                                   REGNO (SET_SRC (set)));
@@ -1723,7 +1723,7 @@ count_pseudo (int reg)
       || REGNO_REG_SET_P (&spilled_pseudos, reg)
       /* Ignore spilled pseudo-registers which can be here only if IRA
         is used.  */
-      || (flag_ira && optimize && r < 0))
+      || (flag_ira && ira_conflicts_p && r < 0))
     return;
 
   SET_REGNO_REG_SET (&pseudos_counted, reg);
@@ -1804,7 +1804,7 @@ count_spilled_pseudo (int spilled, int spilled_nregs, int reg)
 
   /* Ignore spilled pseudo-registers which can be here only if IRA is
      used.  */
-  if ((flag_ira && optimize && r < 0)
+  if ((flag_ira && ira_conflicts_p && r < 0)
       || REGNO_REG_SET_P (&spilled_pseudos, reg)
       || spilled + spilled_nregs <= r || r + nregs <= spilled)
     return;
@@ -1876,7 +1876,7 @@ find_reg (struct insn_chain *chain, int order)
          if (! ok)
            continue;
 
-         if (flag_ira && optimize)
+         if (flag_ira && ira_conflicts_p)
            {
              /* Ask IRA to find a better pseudo-register for
                 spilling.  */
@@ -2158,7 +2158,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
       unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT;
       int adjust = 0;
 
-      if (flag_ira && optimize)
+      if (flag_ira && ira_conflicts_p)
        {
          /* Mark the spill for IRA.  */
          SET_REGNO_REG_SET (&spilled_pseudos, i);
@@ -2177,7 +2177,8 @@ alter_reg (int i, int from_reg, bool dont_share_p)
         enough inherent space and enough total space.
         Otherwise, we allocate a new slot, making sure that it has no less
         inherent space, and no less total space, then the previous slot.  */
-      else if (from_reg == -1 || (!dont_share_p && flag_ira && optimize))
+      else if (from_reg == -1
+              || (!dont_share_p && flag_ira && ira_conflicts_p))
        {
          rtx stack_slot;
 
@@ -2202,7 +2203,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
                                       adjust);
            }
 
-         if (! dont_share_p && flag_ira && optimize)
+         if (! dont_share_p && flag_ira && ira_conflicts_p)
            /* Inform IRA about allocation a new stack slot.  */
            ira_mark_new_stack_slot (stack_slot, i, total_size);
        }
@@ -3904,7 +3905,7 @@ finish_spills (int global)
       spill_reg_order[i] = -1;
 
   EXECUTE_IF_SET_IN_REG_SET (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i, rsi)
-    if (! flag_ira || ! optimize || reg_renumber[i] >= 0)
+    if (! flag_ira || ! ira_conflicts_p || reg_renumber[i] >= 0)
       {
        /* Record the current hard register the pseudo is allocated to
           in pseudo_previous_regs so we avoid reallocating it to the
@@ -3914,7 +3915,7 @@ finish_spills (int global)
        SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
        /* Mark it as no longer having a hard register home.  */
        reg_renumber[i] = -1;
-       if (flag_ira && optimize)
+       if (flag_ira && ira_conflicts_p)
          /* Inform IRA about the change.  */
          ira_mark_allocation_change (i);
        /* We will need to scan everything again.  */
@@ -3944,7 +3945,7 @@ finish_spills (int global)
            }
        }
 
-      if (! flag_ira || ! optimize)
+      if (! flag_ira || ! ira_conflicts_p)
        {
          /* Retry allocating the spilled pseudos.  For each reg,
             merge the various reg sets that indicate which hard regs
@@ -3996,7 +3997,7 @@ finish_spills (int global)
       HARD_REG_SET used_by_pseudos;
       HARD_REG_SET used_by_pseudos2;
 
-      if (! flag_ira || ! optimize)
+      if (! flag_ira || ! ira_conflicts_p)
        {
          /* Don't do it for IRA because IRA and the reload still can
             assign hard registers to the spilled pseudos on next
@@ -6999,7 +7000,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                  && REG_N_SETS (REGNO (old)) == 1)
                {
                  reg_renumber[REGNO (old)] = REGNO (reloadreg);
-                 if (flag_ira && optimize)
+                 if (flag_ira && ira_conflicts_p)
                    /* Inform IRA about the change.  */
                    ira_mark_allocation_change (REGNO (old));
                  alter_reg (REGNO (old), -1, false);
@@ -8540,7 +8541,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
 
       /* For the debugging info, say the pseudo lives in this reload reg.  */
       reg_renumber[REGNO (reg)] = REGNO (new_reload_reg);
-      if (flag_ira && optimize)
+      if (flag_ira && ira_conflicts_p)
        /* Inform IRA about the change.  */
        ira_mark_allocation_change (REGNO (reg));
       alter_reg (REGNO (reg), -1, false);