diff mbox

Add target hook to compute register pressure classes

Message ID 99f2c503-18fc-0599-736a-fb4dc388ef6a@linux.vnet.ibm.com
State New
Headers show

Commit Message

Pat Haugen Nov. 4, 2016, 4:18 p.m. UTC
While working to get -fsched-pressure profitable on PowerPC, one of the things I noticed causing problems was the selection of pressure classes. Understanding that getting the computation of pressure classes correct for all targets in the machine independent code is going to be extremely hard (or impossible), I propose the following target hook which lets the target decide the set of pressure classes to use. I will follow this up with an implementation of the hook for the rs6000 backend, but am currently benchmarking variations of it to see which is best.

Bootstrap/regtest on powerpc64le with no new regressions. Ok for trunk?

Note that the ira.c changes are not as complicated as what it looks, I only added a few lines to invoke the target hook, the rest is just indentation changes to move the existing code into the else leg.

-Pat

2016-11-04  Pat Haugen  <pthaugen@us.ibm.com>

	* target.def (compute_pressure_classes): New target hook.
	* doc/tm.texi.in: Document it.
	* doc/tm.texi: Regenerate.
	* ira.c (setup_pressure_classes): Call target hook if defined.

Comments

Vladimir Makarov Nov. 4, 2016, 7:12 p.m. UTC | #1
On 11/04/2016 12:18 PM, Pat Haugen wrote:
> While working to get -fsched-pressure profitable on PowerPC, one of the things I noticed causing problems was the selection of pressure classes. Understanding that getting the computation of pressure classes correct for all targets in the machine independent code is going to be extremely hard (or impossible), I propose the following target hook which lets the target decide the set of pressure classes to use. I will follow this up with an implementation of the hook for the rs6000 backend, but am currently benchmarking variations of it to see which is best.

>

> Bootstrap/regtest on powerpc64le with no new regressions. Ok for trunk?

Yes.  It is OK, Pat.  Thanks for working on powerpc insn-scheduling issues.
> Note that the ira.c changes are not as complicated as what it looks, I only added a few lines to invoke the target hook, the rest is just indentation changes to move the existing code into the else leg.

>
diff mbox

Patch

Index: gcc/target.def
===================================================================
--- gcc/target.def	(revision 241821)
+++ gcc/target.def	(working copy)
@@ -5039,6 +5039,16 @@  DEFHOOK
   machine_mode, (enum insn_code icode),
   default_cstore_mode)
 
+/* This target hook allows the backend to compute the register pressure
+   classes to use.  */
+DEFHOOK
+(compute_pressure_classes,
+ "A target hook which lets a backend compute the set of pressure classes to\
+  be used by those optimization passes which take register pressure into\
+  account, as opposed to letting IRA compute them.  It returns the number of\
+  register classes stored in the array @var{pressure_classes}.",
+ int, (enum reg_class *pressure_classes), NULL)
+
 /* True if a structure, union or array with MODE containing FIELD should
    be accessed using BLKmode.  */
 DEFHOOK
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 241821)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -2509,6 +2509,8 @@  value that the middle-end intended.
 
 @hook TARGET_CSTORE_MODE
 
+@hook TARGET_COMPUTE_PRESSURE_CLASSES
+
 @node Stack and Calling
 @section Stack Layout and Calling Conventions
 @cindex calling conventions
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 241821)
+++ gcc/doc/tm.texi	(working copy)
@@ -2903,6 +2903,10 @@  This hook defines a class of registers w
 This hook defines the machine mode to use for the boolean result of  conditional store patterns.  The ICODE argument is the instruction code  for the cstore being performed.  Not definiting this hook is the same  as accepting the mode encoded into operand 0 of the cstore expander  patterns.
 @end deftypefn
 
+@deftypefn {Target Hook} int TARGET_COMPUTE_PRESSURE_CLASSES (enum reg_class *@var{pressure_classes})
+A target hook which lets a backend compute the set of pressure classes to  be used by those optimization passes which take register pressure into  account, as opposed to letting IRA compute them.  It returns the number of  register classes stored in the array @var{pressure_classes}.
+@end deftypefn
+
 @node Stack and Calling
 @section Stack Layout and Calling Conventions
 @cindex calling conventions
Index: gcc/ira.c
===================================================================
--- gcc/ira.c	(revision 241821)
+++ gcc/ira.c	(working copy)
@@ -792,78 +792,85 @@  setup_pressure_classes (void)
   HARD_REG_SET temp_hard_regset2;
   bool insert_p;
 
-  n = 0;
-  for (cl = 0; cl < N_REG_CLASSES; cl++)
-    {
-      if (ira_class_hard_regs_num[cl] == 0)
-	continue;
-      if (ira_class_hard_regs_num[cl] != 1
-	  /* A register class without subclasses may contain a few
-	     hard registers and movement between them is costly
-	     (e.g. SPARC FPCC registers).  We still should consider it
-	     as a candidate for a pressure class.  */
-	  && alloc_reg_class_subclasses[cl][0] < cl)
+  if (targetm.compute_pressure_classes)
+    n = targetm.compute_pressure_classes (pressure_classes);
+  else
+    { 
+      n = 0;
+      for (cl = 0; cl < N_REG_CLASSES; cl++)
 	{
-	  /* Check that the moves between any hard registers of the
-	     current class are not more expensive for a legal mode
-	     than load/store of the hard registers of the current
-	     class.  Such class is a potential candidate to be a
-	     register pressure class.  */
-	  for (m = 0; m < NUM_MACHINE_MODES; m++)
+	  if (ira_class_hard_regs_num[cl] == 0)
+	    continue;
+	  if (ira_class_hard_regs_num[cl] != 1
+	      /* A register class without subclasses may contain a few
+		 hard registers and movement between them is costly
+		 (e.g. SPARC FPCC registers).  We still should consider it
+		 as a candidate for a pressure class.  */
+	      && alloc_reg_class_subclasses[cl][0] < cl)
 	    {
-	      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-	      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-	      AND_COMPL_HARD_REG_SET (temp_hard_regset,
-				      ira_prohibited_class_mode_regs[cl][m]);
-	      if (hard_reg_set_empty_p (temp_hard_regset))
+	      /* Check that the moves between any hard registers of the
+		 current class are not more expensive for a legal mode
+		 than load/store of the hard registers of the current
+		 class.  Such class is a potential candidate to be a
+		 register pressure class.  */
+	      for (m = 0; m < NUM_MACHINE_MODES; m++)
+		{
+		  COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+		  AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+		  AND_COMPL_HARD_REG_SET (temp_hard_regset,
+					  ira_prohibited_class_mode_regs[cl][m]);
+		  if (hard_reg_set_empty_p (temp_hard_regset))
+		    continue;
+		  ira_init_register_move_cost_if_necessary ((machine_mode) m);
+		  cost = ira_register_move_cost[m][cl][cl];
+		  if (cost <= ira_max_memory_move_cost[m][cl][1]
+		      || cost <= ira_max_memory_move_cost[m][cl][0])
+		    break;
+		}
+	      if (m >= NUM_MACHINE_MODES)
 		continue;
-	      ira_init_register_move_cost_if_necessary ((machine_mode) m);
-	      cost = ira_register_move_cost[m][cl][cl];
-	      if (cost <= ira_max_memory_move_cost[m][cl][1]
-		  || cost <= ira_max_memory_move_cost[m][cl][0])
-		break;
 	    }
-	  if (m >= NUM_MACHINE_MODES)
-	    continue;
-	}
-      curr = 0;
-      insert_p = true;
-      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-      /* Remove so far added pressure classes which are subset of the
-	 current candidate class.  Prefer GENERAL_REGS as a pressure
-	 register class to another class containing the same
-	 allocatable hard registers.  We do this because machine
-	 dependent cost hooks might give wrong costs for the latter
-	 class but always give the right cost for the former class
-	 (GENERAL_REGS).  */
-      for (i = 0; i < n; i++)
-	{
-	  cl2 = pressure_classes[i];
-	  COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl2]);
-	  AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
-	  if (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2)
-	      && (! hard_reg_set_equal_p (temp_hard_regset, temp_hard_regset2)
-		  || cl2 == (int) GENERAL_REGS))
+	  curr = 0;
+	  insert_p = true;
+	  COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+	  AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+	  /* Remove so far added pressure classes which are subset of the
+	     current candidate class.  Prefer GENERAL_REGS as a pressure
+	     register class to another class containing the same
+	     allocatable hard registers.  We do this because machine
+	     dependent cost hooks might give wrong costs for the latter
+	     class but always give the right cost for the former class
+	     (GENERAL_REGS).  */
+	  for (i = 0; i < n; i++)
 	    {
+	      cl2 = pressure_classes[i];
+	      COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl2]);
+	      AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+	      if (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2)
+		  && (! hard_reg_set_equal_p (temp_hard_regset,
+					      temp_hard_regset2)
+		      || cl2 == (int) GENERAL_REGS))
+		{
+		  pressure_classes[curr++] = (enum reg_class) cl2;
+		  insert_p = false;
+		  continue;
+		}
+	      if (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset)
+		  && (! hard_reg_set_equal_p (temp_hard_regset2,
+					      temp_hard_regset)
+		      || cl == (int) GENERAL_REGS))
+		continue;
+	      if (hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset))
+		insert_p = false;
 	      pressure_classes[curr++] = (enum reg_class) cl2;
-	      insert_p = false;
-	      continue;
 	    }
-	  if (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset)
-	      && (! hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset)
-		  || cl == (int) GENERAL_REGS))
-	    continue;
-	  if (hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset))
-	    insert_p = false;
-	  pressure_classes[curr++] = (enum reg_class) cl2;
+	  /* If the current candidate is a subset of a so far added
+	     pressure class, don't add it to the list of the pressure
+	     classes.  */
+	  if (insert_p)
+	    pressure_classes[curr++] = (enum reg_class) cl;
+	  n = curr;
 	}
-      /* If the current candidate is a subset of a so far added
-	 pressure class, don't add it to the list of the pressure
-	 classes.  */
-      if (insert_p)
-	pressure_classes[curr++] = (enum reg_class) cl;
-      n = curr;
     }
 #ifdef ENABLE_IRA_CHECKING
   {