Hi,
This is the second patch computing available/clobber registers for register 
classes.
It's the same as the original patch posted 
@https://gcc.gnu.org/ml/gcc-patches/2017-05/msg01022.html

Bootstrap and test on x86_64 and AArch64 ongoing.  Any comments?

Thanks,
bin
2017-04-27  Bin Cheng  <bin.ch...@arm.com>

        * cfgloop.h (struct target_cfgloop): Change x_target_avail_regs and
        x_target_clobbered_regs into array fields.
        (init_avail_clobber_regs): New declaration.
        * cfgloopanal.c (memmodel.h, ira.h): Include header files.
        (init_set_costs): Remove computation for old x_target_avail_regs and
        x_target_clobbered_regs fields.
        (init_avail_clobber_regs): New function.
        (estimate_reg_pressure_cost): Update the uses.
        * toplev.c (cfgloop.h): Update comment why the header file is needed.
        (backend_init_target): Call init_avail_clobber_regs.
        * tree-predcom.c (memmodel.h, ira.h): Include header files.
        (MAX_DISTANCE): Update the use.
        * tree-ssa-loop-ivopts.c (AVAILABLE_REGS, CLOBBERED_REGS): New marco.
        (ivopts_estimate_reg_pressure, determine_set_costs): Update the uses.
From 47a2074d21f4b28b4c38233628e94bcaef9ed40d Mon Sep 17 00:00:00 2001
From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com>
Date: Thu, 19 Apr 2018 15:54:14 +0100
Subject: [PATCH 2/6] init-avail_clob-regs-20180428.txt

---
 gcc/cfgloop.h              | 10 ++++---
 gcc/cfgloopanal.c          | 68 +++++++++++++++++++++++++++++++++++-----------
 gcc/toplev.c               |  3 +-
 gcc/tree-predcom.c         |  4 ++-
 gcc/tree-ssa-loop-ivopts.c | 14 ++++++----
 5 files changed, 72 insertions(+), 27 deletions(-)

diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index af9bfab..3d06e1c 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -773,11 +773,12 @@ loop_iterator::~loop_iterator ()
 
 /* The properties of the target.  */
 struct target_cfgloop {
-  /* Number of available registers.  */
-  unsigned x_target_avail_regs;
+  /* Number of available registers per register pressure class.  */
+  unsigned x_target_avail_regs[N_REG_CLASSES];
 
-  /* Number of available registers that are call-clobbered.  */
-  unsigned x_target_clobbered_regs;
+  /* Number of available registers that are call-clobbered, per register
+     pressure class.  */
+  unsigned x_target_clobbered_regs[N_REG_CLASSES];
 
   /* Number of registers reserved for temporary expressions.  */
   unsigned x_target_res_regs;
@@ -812,6 +813,7 @@ extern struct target_cfgloop *this_target_cfgloop;
    invariant motion.  */
 extern unsigned estimate_reg_pressure_cost (unsigned, unsigned, bool, bool);
 extern void init_set_costs (void);
+extern void init_avail_clobber_regs (void);
 
 /* Loop optimizer initialization.  */
 extern void loop_optimizer_init (unsigned);
diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c
index 3af0b2d..20010bb 100644
--- a/gcc/cfgloopanal.c
+++ b/gcc/cfgloopanal.c
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "backend.h"
 #include "rtl.h"
+#include "memmodel.h"
+#include "ira.h"
 #include "tree.h"
 #include "predict.h"
 #include "memmodel.h"
@@ -344,20 +346,6 @@ init_set_costs (void)
   rtx reg2 = gen_raw_REG (SImode, LAST_VIRTUAL_REGISTER + 2);
   rtx addr = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 3);
   rtx mem = validize_mem (gen_rtx_MEM (SImode, addr));
-  unsigned i;
-
-  target_avail_regs = 0;
-  target_clobbered_regs = 0;
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i)
-	&& !fixed_regs[i])
-      {
-	target_avail_regs++;
-	if (call_used_regs[i])
-	  target_clobbered_regs++;
-      }
-
-  target_res_regs = 3;
 
   for (speed = 0; speed < 2; speed++)
      {
@@ -387,6 +375,54 @@ init_set_costs (void)
   default_rtl_profile ();
 }
 
+/* Initialize available, clobbered register for each register classes.  */
+
+void
+init_avail_clobber_regs (void)
+{
+  int j;
+  unsigned i;
+  bool general_regs_presented_p = false;
+
+  /* Check if GENERAL_REGS is one of pressure classes.  */
+  for (j = 0; j < ira_pressure_classes_num; j++)
+    {
+      target_avail_regs[j] = 0;
+      target_clobbered_regs[j] = 0;
+      if (ira_pressure_classes[j] == GENERAL_REGS)
+	general_regs_presented_p = true;
+    }
+  target_avail_regs[GENERAL_REGS] = 0;
+  target_clobbered_regs[GENERAL_REGS] = 0;
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      if (fixed_regs[i])
+	continue;
+
+      bool call_used = call_used_regs[i];
+
+      for (j = 0; j < ira_pressure_classes_num; j++)
+	if (TEST_HARD_REG_BIT (reg_class_contents[ira_pressure_classes[j]], i))
+	  {
+	    target_avail_regs[ira_pressure_classes[j]]++;
+	    if (call_used)
+	      target_clobbered_regs[ira_pressure_classes[j]]++;
+	  }
+
+      /* Compute pressure information for GENERAL_REGS separately.  */
+      if (!general_regs_presented_p)
+	if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i))
+	  {
+	    target_avail_regs[GENERAL_REGS]++;
+	    if (call_used)
+	      target_clobbered_regs[GENERAL_REGS]++;
+	  }
+    }
+
+  target_res_regs = 3;
+}
+
 /* Estimates cost of increased register pressure caused by making N_NEW new
    registers live around the loop.  N_OLD is the number of registers live
    around the loop.  If CALL_P is true, also take into account that
@@ -399,12 +435,12 @@ estimate_reg_pressure_cost (unsigned n_new, unsigned n_old, bool speed,
 {
   unsigned cost;
   unsigned regs_needed = n_new + n_old;
-  unsigned available_regs = target_avail_regs;
+  unsigned available_regs = target_avail_regs[GENERAL_REGS];
 
   /* If there is a call in the loop body, the call-clobbered registers
      are not available for loop invariants.  */
   if (call_p)
-    available_regs = available_regs - target_clobbered_regs;
+    available_regs = available_regs - target_clobbered_regs[GENERAL_REGS];
 
   /* If we have enough registers, we should use them and not restrict
      the transformations unnecessarily.  */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index b066bcc..0a2662b 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -59,7 +59,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "common/common-target.h"
 #include "langhooks.h"
-#include "cfgloop.h" /* for init_set_costs */
+#include "cfgloop.h" /* For init_set_costs and init_avail_clobber_regs.  */
 #include "hosthooks.h"
 #include "opts.h"
 #include "opts-diagnostic.h"
@@ -1797,6 +1797,7 @@ backend_init_target (void)
 
   init_expr_target ();
   ira_init ();
+  init_avail_clobber_regs ();
 
   /* We may need to recompute regno_save_code[] and regno_restore_code[]
      after a mode change as well.  */
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index 2bde732..aeadbf7 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -209,6 +209,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "backend.h"
 #include "rtl.h"
+#include "memmodel.h"
+#include "ira.h"
 #include "tree.h"
 #include "gimple.h"
 #include "predict.h"
@@ -238,7 +240,7 @@ along with GCC; see the file COPYING3.  If not see
 /* The maximum number of iterations between the considered memory
    references.  */
 
-#define MAX_DISTANCE (target_avail_regs < 16 ? 4 : 8)
+#define MAX_DISTANCE (target_avail_regs[GENERAL_REGS] < 16 ? 4 : 8)
 
 /* Data references (or phi nodes that carry data reference values across
    loop iterations).  */
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index b313571..6e14933 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -135,6 +135,10 @@ avg_loop_niter (struct loop *loop)
   return niter;
 }
 
+/* Information about target general registers.  */
+#define AVAILABLE_REGS (target_avail_regs[GENERAL_REGS])
+#define CLOBBERED_REGS (target_clobbered_regs[GENERAL_REGS])
+
 struct iv_use;
 
 /* Representation of the induction variable.  */
@@ -5627,13 +5631,13 @@ ivopts_estimate_reg_pressure (struct ivopts_data *data, unsigned n_invs,
 {
   unsigned cost;
   unsigned n_old = data->regs_used, n_new = n_invs + n_cands;
-  unsigned regs_needed = n_new + n_old, available_regs = target_avail_regs;
+  unsigned regs_needed = n_new + n_old, available_regs = AVAILABLE_REGS;
   bool speed = data->speed;
 
   /* If there is a call in the loop body, the call-clobbered registers
      are not available for loop invariants.  */
   if (data->body_includes_call)
-    available_regs = available_regs - target_clobbered_regs;
+    available_regs = available_regs - CLOBBERED_REGS;
 
   /* If we have enough registers.  */
   if (regs_needed + target_res_regs < available_regs)
@@ -5674,8 +5678,8 @@ determine_set_costs (struct ivopts_data *data)
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "<Global Costs>:\n");
-      fprintf (dump_file, "  target_avail_regs %d\n", target_avail_regs);
-      fprintf (dump_file, "  target_clobbered_regs %d\n", target_clobbered_regs);
+      fprintf (dump_file, "  target_avail_regs %d\n", AVAILABLE_REGS);
+      fprintf (dump_file, "  target_clobbered_regs %d\n", CLOBBERED_REGS);
       fprintf (dump_file, "  target_reg_cost %d\n", target_reg_cost[data->speed]);
       fprintf (dump_file, "  target_spill_cost %d\n", target_spill_cost[data->speed]);
     }
@@ -5715,7 +5719,7 @@ determine_set_costs (struct ivopts_data *data)
     {
       fprintf (dump_file, "  cost for size:\n");
       fprintf (dump_file, "  ivs\tcost\n");
-      for (j = 0; j <= 2 * target_avail_regs; j++)
+      for (j = 0; j <= 2 * AVAILABLE_REGS; j++)
 	fprintf (dump_file, "  %d\t%d\n", j,
 		 ivopts_estimate_reg_pressure (data, 0, j));
       fprintf (dump_file, "\n");
-- 
1.9.1

Reply via email to