Hi,
Currently available/clobber registers are computed only for GENERAL_REGS, this
patch extends it for all reg pressure classes.  It also updates existing uses
in various places.

Bootstrap and test on x86_64 and AArch64.  Is it OK?

Thanks,
bin
2017-05-10  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 (determine_set_costs): Update the uses.
        (determine_set_costs): Ditto.
From f9a2481957916e880d89972344ecc074f74ada95 Mon Sep 17 00:00:00 2001
From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com>
Date: Mon, 24 Apr 2017 14:42:23 +0100
Subject: [PATCH 2/6] init-available-regs-20170316.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 a8bec1d..853a04a 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -754,11 +754,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;
@@ -793,6 +794,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 aa06c96..befbf36 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"
@@ -336,20 +338,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++)
      {
@@ -379,6 +367,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
@@ -391,12 +427,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 f1384fc..3ab8522 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"
@@ -1668,6 +1668,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 57d8f7d..96af63f 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -189,6 +189,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"
@@ -218,7 +220,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 d865fd2..f750162 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -5970,10 +5970,14 @@ 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_reg_cost %d\n", 
target_reg_cost[data->speed]);
-      fprintf (dump_file, "  target_spill_cost %d\n", 
target_spill_cost[data->speed]);
+      fprintf (dump_file, "  target_avail_regs %d\n",
+              target_avail_regs[GENERAL_REGS]);
+      fprintf (dump_file, "  target_clobbered_regs %d\n",
+              target_clobbered_regs[GENERAL_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]);
     }
 
   n = 0;
@@ -6007,7 +6011,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 * target_avail_regs[GENERAL_REGS]; j++)
        fprintf (dump_file, "  %d\t%d\n", j,
                 ivopts_global_cost_for_size (data, j));
       fprintf (dump_file, "\n");
-- 
1.9.1

Reply via email to