This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: patch for PR37488


The following patch solves PR37488.  The details of the problem can
be found on

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37488

The patch was successfully bootstrapped and tested on x86 and x86_64. It was benchmarked on SPEC2000 on x86 with -O2 -march=i686 -mfpmath=sse -msse2. The average scores are practically the same.

Ok to commit?

2009-07-02 Vladimir Makarov <vmakarov@redhat.com>

   PR target/37488
   * ira-lives.c (bb_has_abnormal_call_pred): New function.
   (process_bb_node_lives): Use it.

   * ira.c (setup_cover_and_important_classes): Don't setup
   ira_important_class_nums.  Add cover classes to the end of
   important classes.
   (cover_class_order, comp_reg_classes_func,
   reorder_important_classes): New.
   (find_reg_class_closure): Use reorder_important_classes.

* config/i386/i386.h (IRA_COVER_CLASSES): Remove.

   * config/i386/i386.c (i386_ira_cover_classes): New function.
   (TARGET_IRA_COVER_CLASSES): Redefine.

* doc/tm.texi (TARGET_IRA_COVER_CLASSES): Add a comment about
importance of order of cover classes in the array.


Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 149057)
+++ gcc/doc/tm.texi	(working copy)
@@ -2905,6 +2905,10 @@ purposes.  If a move between two registe
 possible, it should be cheaper than a load or store of the registers.
 The array is terminated by a @code{LIM_REG_CLASSES} element.
 
+The order of cover classes in the array is important.  If two classes
+have the same cost of usage for a pseudo, the class occurred first in
+the array is chosen for the pseudo.
+
 This hook is called once at compiler startup, after the command-line
 options have been processed. It is then re-examined by every call to
 @code{target_reinit}.
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c	(revision 149057)
+++ gcc/ira-lives.c	(working copy)
@@ -814,6 +814,22 @@ process_single_reg_class_operands (bool 
     }
 }
 
+/* Return true when one of the predecessor edges of BB is marked with
+   EDGE_ABNORMAL_CALL or EDGE_EH.  */
+static bool
+bb_has_abnormal_call_pred (basic_block bb)
+{
+  edge e;
+  edge_iterator ei;
+  
+  FOR_EACH_EDGE (e, ei, bb->preds)
+    {
+      if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
+	return true;
+    }
+  return false;
+}
+
 /* Process insns of the basic block given by its LOOP_TREE_NODE to
    update allocno live ranges, allocno hard register conflicts,
    intersected calls, and register pressure info for allocnos for the
@@ -1062,7 +1078,7 @@ process_bb_node_lives (ira_loop_tree_nod
 	  /* No need to record conflicts for call clobbered regs if we
 	     have nonlocal labels around, as we don't ever try to
 	     allocate such regs in this case.  */
-	  if (!cfun->has_nonlocal_label)
+	  if (!cfun->has_nonlocal_label && bb_has_abnormal_call_pred (bb))
 	    for (px = 0; px < FIRST_PSEUDO_REGISTER; px++)
 	      if (call_used_regs[px])
 		make_regno_born (px);
Index: gcc/ira.c
===================================================================
--- gcc/ira.c	(revision 149057)
+++ gcc/ira.c	(working copy)
@@ -729,7 +729,7 @@ static void
 setup_cover_and_important_classes (void)
 {
   int i, j, n, cl;
-  bool set_p, eq_p;
+  bool set_p;
   const enum reg_class *cover_classes;
   HARD_REG_SET temp_hard_regset2;
   static enum reg_class classes[LIM_REG_CLASSES + 1];
@@ -802,7 +802,7 @@ setup_cover_and_important_classes (void)
       AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
       if (! hard_reg_set_empty_p (temp_hard_regset))
 	{
-	  set_p = eq_p = false;
+	  set_p = false;
 	  for (j = 0; j < ira_reg_class_cover_size; j++)
 	    {
 	      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
@@ -810,27 +810,22 @@ setup_cover_and_important_classes (void)
 	      COPY_HARD_REG_SET (temp_hard_regset2,
 				 reg_class_contents[ira_reg_class_cover[j]]);
 	      AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
-	      if ((enum reg_class) cl == ira_reg_class_cover[j])
-		{
-		  eq_p = false;
-		  set_p = true;
-		  break;
-		}
-	      else if (hard_reg_set_equal_p (temp_hard_regset,
-					     temp_hard_regset2))
-		eq_p = true;
+	      if ((enum reg_class) cl == ira_reg_class_cover[j]
+		  || hard_reg_set_equal_p (temp_hard_regset,
+					   temp_hard_regset2))
+		break;
 	      else if (hard_reg_set_subset_p (temp_hard_regset,
 					      temp_hard_regset2))
 		set_p = true;
 	    }
-	  if (set_p && ! eq_p)
-	    {
-	      ira_important_class_nums[cl] = ira_important_classes_num;
-	      ira_important_classes[ira_important_classes_num++] =
-		(enum reg_class) cl;
-	    }
+	  if (set_p && j >= ira_reg_class_cover_size)
+	    ira_important_classes[ira_important_classes_num++]
+	      = (enum reg_class) cl;
 	}
     }
+  for (j = 0; j < ira_reg_class_cover_size; j++)
+    ira_important_classes[ira_important_classes_num++]
+      = ira_reg_class_cover[j];
 }
 
 /* Map of all register classes to corresponding cover class containing
@@ -925,6 +920,43 @@ setup_class_translate (void)
     }
 }
 
+/* Order numbers of cover classes in original target cover class
+   array, -1 for non-cover classes.  */ 
+static int cover_class_order[N_REG_CLASSES];
+
+/* The function used to sort the important classes.  */
+static int
+comp_reg_classes_func (const void *v1p, const void *v2p)
+{
+  enum reg_class cl1 = *(const enum reg_class *) v1p;
+  enum reg_class cl2 = *(const enum reg_class *) v2p;
+  int diff;
+
+  cl1 = ira_class_translate[cl1];
+  cl2 = ira_class_translate[cl2];
+  if (cl1 != NO_REGS && cl2 != NO_REGS
+      && (diff = cover_class_order[cl1] - cover_class_order[cl2]) != 0)
+    return diff;
+  return (int) cl1 - (int) cl2;
+}
+
+/* Reorder important classes according to the order of their cover
+   classes.  Set up array ira_important_class_nums too.  */
+static void
+reorder_important_classes (void)
+{
+  int i;
+
+  for (i = 0; i < N_REG_CLASSES; i++)
+    cover_class_order[i] = -1;
+  for (i = 0; i < ira_reg_class_cover_size; i++)
+    cover_class_order[ira_reg_class_cover[i]] = i;
+  qsort (ira_important_classes, ira_important_classes_num,
+	 sizeof (enum reg_class), comp_reg_classes_func);
+  for (i = 0; i < ira_important_classes_num; i++)
+    ira_important_class_nums[ira_important_classes[i]] = i;
+}
+
 /* The biggest important reg_class inside of intersection of the two
    reg_classes (that is calculated taking only hard registers
    available for allocation into account).  If the both reg_classes
@@ -1089,6 +1121,7 @@ find_reg_class_closure (void)
   setup_reg_subclasses ();
   setup_cover_and_important_classes ();
   setup_class_translate ();
+  reorder_important_classes ();
   setup_reg_class_relations ();
 }
 
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	(revision 149057)
+++ gcc/config/i386/i386.h	(working copy)
@@ -1325,19 +1325,6 @@ enum reg_class
 { 0xffffffff,0x1fffff }							\
 }
 
-/* The following macro defines cover classes for Integrated Register
-   Allocator.  Cover classes is a set of non-intersected register
-   classes covering all hard registers used for register allocation
-   purpose.  Any move between two registers of a cover class should be
-   cheaper than load or store of the registers.  The macro value is
-   array of register classes with LIM_REG_CLASSES used as the end
-   marker.  */
-
-#define IRA_COVER_CLASSES						     \
-{									     \
-  GENERAL_REGS, FLOAT_REGS, MMX_REGS, SSE_REGS, LIM_REG_CLASSES		     \
-}
-
 /* The same information, inverted:
    Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 149057)
+++ gcc/config/i386/i386.c	(working copy)
@@ -26005,6 +26005,22 @@ ix86_free_from_memory (enum machine_mode
     }
 }
 
+/* Implement TARGET_IRA_COVER_CLASSES.  If -mfpmath=sse, we prefer
+   SSE_REGS to FLOAT_REGS if their costs for a pseudo are the
+   same.  */
+static const enum reg_class *
+i386_ira_cover_classes (void)
+{
+  static const enum reg_class sse_fpmath_classes[] = {
+    GENERAL_REGS, SSE_REGS, MMX_REGS, FLOAT_REGS, LIM_REG_CLASSES
+  };
+  static const enum reg_class no_sse_fpmath_classes[] = {
+    GENERAL_REGS, FLOAT_REGS, MMX_REGS, SSE_REGS, LIM_REG_CLASSES
+  };
+
+ return TARGET_SSE_MATH ? sse_fpmath_classes : no_sse_fpmath_classes;
+}
+
 /* Put float CONST_DOUBLE in the constant pool instead of fp regs.
    QImode must go into class Q_REGS.
    Narrow ALL_REGS to GENERAL_REGS.  This supports allowing movsf and
@@ -30525,6 +30541,9 @@ ix86_enum_va_list (int idx, const char *
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P ix86_legitimate_address_p
 
+#undef TARGET_IRA_COVER_CLASSES
+#define TARGET_IRA_COVER_CLASSES i386_ira_cover_classes
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-i386.h"

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]