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