From: Robin Dapp <rdapp.gcc@gmail.com>
To: Jeff Law <jeffreyalaw@gmail.com>,
gcc-patches <gcc-patches@gcc.gnu.org>,
richard.sandiford@arm.com
Cc: rdapp.gcc@gmail.com
Subject: Re: [PATCH] fwprop: Allow UNARY_P and check register pressure.
Date: Thu, 7 Sep 2023 09:56:29 +0200 [thread overview]
Message-ID: <3e0c212c-ef1b-26a6-3515-724cd2bc870f@gmail.com> (raw)
In-Reply-To: <mpt4jk7qbfe.fsf@arm.com>
> Thanks for giving it a go. Can you post the latest version of the
> regpressure patch too? The previous on-list version I could find
> seems to be too old.
Oh, sure, attached. Apologies, I added the regpressure_same_class
convenience helper but forgot to re-send it.
Regards
Robin
From d3f87e4de7d7d05a2fcf8c948097b14eadf08c90 Mon Sep 17 00:00:00 2001
From: Robin Dapp <rdapp@ventanamicro.com>
Date: Mon, 24 Jul 2023 16:25:38 +0200
Subject: [PATCH] gcse: Extract reg pressure handling into separate file.
This patch extracts the hoist-pressure handling from gcse and puts it
into a separate file so it can be used by other passes in the future.
No functional change.
gcc/ChangeLog:
* Makefile.in: Add regpressure.o.
* gcse.cc (struct bb_data): Move to regpressure.cc.
(BB_DATA): Ditto.
(get_regno_pressure_class): Ditto.
(get_pressure_class_and_nregs): Ditto.
(record_set_data): Ditto.
(update_bb_reg_pressure): Ditto.
(should_hoist_expr_to_dom): Ditto.
(hoist_code): Ditto.
(change_pressure): Ditto.
(calculate_bb_reg_pressure): Ditto.
(one_code_hoisting_pass): Ditto.
* gcse.h (single_set_gcse): Export single_set_gcse.
* regpressure.cc: New file.
* regpressure.h: New file.
---
gcc/Makefile.in | 1 +
gcc/gcse.cc | 304 ++---------------------------------
gcc/gcse.h | 2 +
gcc/regpressure.cc | 391 +++++++++++++++++++++++++++++++++++++++++++++
gcc/regpressure.h | 48 ++++++
5 files changed, 459 insertions(+), 287 deletions(-)
create mode 100644 gcc/regpressure.cc
create mode 100644 gcc/regpressure.h
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 5930b52462a..62768a84f81 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1610,6 +1610,7 @@ OBJS = \
reg-stack.o \
regcprop.o \
reginfo.o \
+ regpressure.o \
regrename.o \
regstat.o \
reload.o \
diff --git a/gcc/gcse.cc b/gcc/gcse.cc
index f689c0c2687..5bafef7970f 100644
--- a/gcc/gcse.cc
+++ b/gcc/gcse.cc
@@ -160,6 +160,7 @@ along with GCC; see the file COPYING3. If not see
#include "gcse.h"
#include "gcse-common.h"
#include "function-abi.h"
+#include "regpressure.h"
/* We support GCSE via Partial Redundancy Elimination. PRE optimizations
are a superset of those done by classic GCSE.
@@ -419,30 +420,6 @@ static bool doing_code_hoisting_p = false;
/* For available exprs */
static sbitmap *ae_kill;
\f
-/* Data stored for each basic block. */
-struct bb_data
-{
- /* Maximal register pressure inside basic block for given register class
- (defined only for the pressure classes). */
- int max_reg_pressure[N_REG_CLASSES];
- /* Recorded register pressure of basic block before trying to hoist
- an expression. Will be used to restore the register pressure
- if the expression should not be hoisted. */
- int old_pressure;
- /* Recorded register live_in info of basic block during code hoisting
- process. BACKUP is used to record live_in info before trying to
- hoist an expression, and will be used to restore LIVE_IN if the
- expression should not be hoisted. */
- bitmap live_in, backup;
-};
-
-#define BB_DATA(bb) ((struct bb_data *) (bb)->aux)
-
-static basic_block curr_bb;
-
-/* Current register pressure for each pressure class. */
-static int curr_reg_pressure[N_REG_CLASSES];
-\f
static void compute_can_copy (void);
static void *gmalloc (size_t) ATTRIBUTE_MALLOC;
@@ -494,8 +471,6 @@ static bool should_hoist_expr_to_dom (basic_block, struct gcse_expr *,
enum reg_class,
int *, bitmap, rtx_insn *);
static bool hoist_code (void);
-static enum reg_class get_regno_pressure_class (int regno, int *nregs);
-static enum reg_class get_pressure_class_and_nregs (rtx_insn *insn, int *nregs);
static bool one_code_hoisting_pass (void);
static rtx_insn *process_insert_insn (struct gcse_expr *);
static bool pre_edge_insert (struct edge_list *, struct gcse_expr **);
@@ -2402,7 +2377,7 @@ record_set_data (rtx dest, const_rtx set, void *data)
}
}
-static const_rtx
+const_rtx
single_set_gcse (rtx_insn *insn)
{
struct set_data s;
@@ -2804,72 +2779,6 @@ compute_code_hoist_data (void)
fprintf (dump_file, "\n");
}
-/* Update register pressure for BB when hoisting an expression from
- instruction FROM, if live ranges of inputs are shrunk. Also
- maintain live_in information if live range of register referred
- in FROM is shrunk.
-
- Return 0 if register pressure doesn't change, otherwise return
- the number by which register pressure is decreased.
-
- NOTE: Register pressure won't be increased in this function. */
-
-static int
-update_bb_reg_pressure (basic_block bb, rtx_insn *from)
-{
- rtx dreg;
- rtx_insn *insn;
- basic_block succ_bb;
- df_ref use, op_ref;
- edge succ;
- edge_iterator ei;
- int decreased_pressure = 0;
- int nregs;
- enum reg_class pressure_class;
-
- FOR_EACH_INSN_USE (use, from)
- {
- dreg = DF_REF_REAL_REG (use);
- /* The live range of register is shrunk only if it isn't:
- 1. referred on any path from the end of this block to EXIT, or
- 2. referred by insns other than FROM in this block. */
- FOR_EACH_EDGE (succ, ei, bb->succs)
- {
- succ_bb = succ->dest;
- if (succ_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
- continue;
-
- if (bitmap_bit_p (BB_DATA (succ_bb)->live_in, REGNO (dreg)))
- break;
- }
- if (succ != NULL)
- continue;
-
- op_ref = DF_REG_USE_CHAIN (REGNO (dreg));
- for (; op_ref; op_ref = DF_REF_NEXT_REG (op_ref))
- {
- if (!DF_REF_INSN_INFO (op_ref))
- continue;
-
- insn = DF_REF_INSN (op_ref);
- if (BLOCK_FOR_INSN (insn) == bb
- && NONDEBUG_INSN_P (insn) && insn != from)
- break;
- }
-
- pressure_class = get_regno_pressure_class (REGNO (dreg), &nregs);
- /* Decrease register pressure and update live_in information for
- this block. */
- if (!op_ref && pressure_class != NO_REGS)
- {
- decreased_pressure += nregs;
- BB_DATA (bb)->max_reg_pressure[pressure_class] -= nregs;
- bitmap_clear_bit (BB_DATA (bb)->live_in, REGNO (dreg));
- }
- }
- return decreased_pressure;
-}
-
/* Determine if the expression EXPR should be hoisted to EXPR_BB up in
flow graph, if it can reach BB unimpared. Stop the search if the
expression would need to be moved more than DISTANCE instructions.
@@ -2917,12 +2826,9 @@ should_hoist_expr_to_dom (basic_block expr_bb, struct gcse_expr *expr,
/* Record old information of basic block BB when it is visited
at the first time. */
if (!bitmap_bit_p (hoisted_bbs, bb->index))
- {
- struct bb_data *data = BB_DATA (bb);
- bitmap_copy (data->backup, data->live_in);
- data->old_pressure = data->max_reg_pressure[pressure_class];
- }
- decreased_pressure = update_bb_reg_pressure (bb, from);
+ regpressure_init_bb_info (bb, pressure_class);
+
+ decreased_pressure = regpressure_update_bb_reg_pressure (bb, from);
}
/* Terminate the search if distance, for which EXPR is allowed to move,
is exhausted. */
@@ -2945,8 +2851,7 @@ should_hoist_expr_to_dom (basic_block expr_bb, struct gcse_expr *expr,
on ARM target, while it has no obvious effect on other
targets like x86, x86_64, mips and powerpc. */
else if (CONST_INT_P (expr->expr)
- || (BB_DATA (bb)->max_reg_pressure[pressure_class]
- >= ira_class_hard_regs_num[pressure_class]
+ || (!regpressure_viable (bb, pressure_class)
&& decreased_pressure < *nregs))
distance -= bb_size[bb->index];
}
@@ -3073,7 +2978,6 @@ hoist_code (void)
int *to_bb_head;
int *bb_size;
bool changed = false;
- struct bb_data *data;
/* Basic blocks that have occurrences reachable from BB. */
bitmap from_bbs;
/* Basic blocks through which expr is hoisted. */
@@ -3206,8 +3110,9 @@ hoist_code (void)
max_distance += (bb_size[dominated->index]
- to_bb_head[INSN_UID (occr->insn)]);
- pressure_class = get_pressure_class_and_nregs (occr->insn,
- &nregs);
+ pressure_class =
+ regpressure_get_pressure_class_and_nregs (occr->insn,
+ &nregs);
/* Note if the expression should be hoisted from the dominated
block to BB if it can reach DOMINATED unimpared.
@@ -3262,13 +3167,11 @@ hoist_code (void)
/* Increase register pressure of basic blocks to which
expr is hoisted because of extended live range of
output. */
- data = BB_DATA (bb);
- data->max_reg_pressure[pressure_class] += nregs;
+ regpressure_increase (bb, pressure_class, nregs);
+
EXECUTE_IF_SET_IN_BITMAP (hoisted_bbs, 0, k, bi)
- {
- data = BB_DATA (BASIC_BLOCK_FOR_FN (cfun, k));
- data->max_reg_pressure[pressure_class] += nregs;
- }
+ regpressure_increase (BASIC_BLOCK_FOR_FN (cfun, k),
+ pressure_class, nregs);
}
else if (flag_ira_hoist_pressure)
{
@@ -3276,12 +3179,8 @@ hoist_code (void)
blocks recorded in hoisted_bbs when expr will not be
hoisted. */
EXECUTE_IF_SET_IN_BITMAP (hoisted_bbs, 0, k, bi)
- {
- data = BB_DATA (BASIC_BLOCK_FOR_FN (cfun, k));
- bitmap_copy (data->live_in, data->backup);
- data->max_reg_pressure[pressure_class]
- = data->old_pressure;
- }
+ regpressure_reset (BASIC_BLOCK_FOR_FN (cfun, k),
+ pressure_class);
}
if (flag_ira_hoist_pressure)
@@ -3343,166 +3242,6 @@ hoist_code (void)
return changed;
}
-/* Return pressure class and number of needed hard registers (through
- *NREGS) of register REGNO. */
-static enum reg_class
-get_regno_pressure_class (int regno, int *nregs)
-{
- if (regno >= FIRST_PSEUDO_REGISTER)
- {
- enum reg_class pressure_class;
-
- pressure_class = reg_allocno_class (regno);
- pressure_class = ira_pressure_class_translate[pressure_class];
- *nregs
- = ira_reg_class_max_nregs[pressure_class][PSEUDO_REGNO_MODE (regno)];
- return pressure_class;
- }
- else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)
- && ! TEST_HARD_REG_BIT (eliminable_regset, regno))
- {
- *nregs = 1;
- return ira_pressure_class_translate[REGNO_REG_CLASS (regno)];
- }
- else
- {
- *nregs = 0;
- return NO_REGS;
- }
-}
-
-/* Return pressure class and number of hard registers (through *NREGS)
- for destination of INSN. */
-static enum reg_class
-get_pressure_class_and_nregs (rtx_insn *insn, int *nregs)
-{
- rtx reg;
- enum reg_class pressure_class;
- const_rtx set = single_set_gcse (insn);
-
- reg = SET_DEST (set);
- if (GET_CODE (reg) == SUBREG)
- reg = SUBREG_REG (reg);
- if (MEM_P (reg))
- {
- *nregs = 0;
- pressure_class = NO_REGS;
- }
- else
- {
- gcc_assert (REG_P (reg));
- pressure_class = reg_allocno_class (REGNO (reg));
- pressure_class = ira_pressure_class_translate[pressure_class];
- *nregs
- = ira_reg_class_max_nregs[pressure_class][GET_MODE (SET_SRC (set))];
- }
- return pressure_class;
-}
-
-/* Increase (if INCR_P) or decrease current register pressure for
- register REGNO. */
-static void
-change_pressure (int regno, bool incr_p)
-{
- int nregs;
- enum reg_class pressure_class;
-
- pressure_class = get_regno_pressure_class (regno, &nregs);
- if (! incr_p)
- curr_reg_pressure[pressure_class] -= nregs;
- else
- {
- curr_reg_pressure[pressure_class] += nregs;
- if (BB_DATA (curr_bb)->max_reg_pressure[pressure_class]
- < curr_reg_pressure[pressure_class])
- BB_DATA (curr_bb)->max_reg_pressure[pressure_class]
- = curr_reg_pressure[pressure_class];
- }
-}
-
-/* Calculate register pressure for each basic block by walking insns
- from last to first. */
-static void
-calculate_bb_reg_pressure (void)
-{
- int i;
- unsigned int j;
- rtx_insn *insn;
- basic_block bb;
- bitmap curr_regs_live;
- bitmap_iterator bi;
-
-
- ira_setup_eliminable_regset ();
- curr_regs_live = BITMAP_ALLOC (®_obstack);
- FOR_EACH_BB_FN (bb, cfun)
- {
- curr_bb = bb;
- BB_DATA (bb)->live_in = BITMAP_ALLOC (NULL);
- BB_DATA (bb)->backup = BITMAP_ALLOC (NULL);
- bitmap_copy (BB_DATA (bb)->live_in, df_get_live_in (bb));
- bitmap_copy (curr_regs_live, df_get_live_out (bb));
- for (i = 0; i < ira_pressure_classes_num; i++)
- curr_reg_pressure[ira_pressure_classes[i]] = 0;
- EXECUTE_IF_SET_IN_BITMAP (curr_regs_live, 0, j, bi)
- change_pressure (j, true);
-
- FOR_BB_INSNS_REVERSE (bb, insn)
- {
- rtx dreg;
- int regno;
- df_ref def, use;
-
- if (! NONDEBUG_INSN_P (insn))
- continue;
-
- FOR_EACH_INSN_DEF (def, insn)
- {
- dreg = DF_REF_REAL_REG (def);
- gcc_assert (REG_P (dreg));
- regno = REGNO (dreg);
- if (!(DF_REF_FLAGS (def)
- & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
- {
- if (bitmap_clear_bit (curr_regs_live, regno))
- change_pressure (regno, false);
- }
- }
-
- FOR_EACH_INSN_USE (use, insn)
- {
- dreg = DF_REF_REAL_REG (use);
- gcc_assert (REG_P (dreg));
- regno = REGNO (dreg);
- if (bitmap_set_bit (curr_regs_live, regno))
- change_pressure (regno, true);
- }
- }
- }
- BITMAP_FREE (curr_regs_live);
-
- if (dump_file == NULL)
- return;
-
- fprintf (dump_file, "\nRegister Pressure: \n");
- FOR_EACH_BB_FN (bb, cfun)
- {
- fprintf (dump_file, " Basic block %d: \n", bb->index);
- for (i = 0; (int) i < ira_pressure_classes_num; i++)
- {
- enum reg_class pressure_class;
-
- pressure_class = ira_pressure_classes[i];
- if (BB_DATA (bb)->max_reg_pressure[pressure_class] == 0)
- continue;
-
- fprintf (dump_file, " %s=%d\n", reg_class_names[pressure_class],
- BB_DATA (bb)->max_reg_pressure[pressure_class]);
- }
- }
- fprintf (dump_file, "\n");
-}
-
/* Top level routine to perform one code hoisting (aka unification) pass
Return true if a change was made. */
@@ -3524,13 +3263,7 @@ one_code_hoisting_pass (void)
/* Calculate register pressure for each basic block. */
if (flag_ira_hoist_pressure)
- {
- regstat_init_n_sets_and_refs ();
- ira_set_pseudo_classes (false, dump_file);
- alloc_aux_for_blocks (sizeof (struct bb_data));
- calculate_bb_reg_pressure ();
- regstat_free_n_sets_and_refs ();
- }
+ regpressure_init ();
/* We need alias. */
init_alias_analysis ();
@@ -3554,10 +3287,7 @@ one_code_hoisting_pass (void)
}
if (flag_ira_hoist_pressure)
- {
- free_aux_for_blocks ();
- free_reg_info ();
- }
+ regpressure_cleanup ();
free_hash_table (&expr_hash_table);
free_gcse_mem ();
obstack_free (&gcse_obstack, NULL);
diff --git a/gcc/gcse.h b/gcc/gcse.h
index e68afdcea21..1162086570d 100644
--- a/gcc/gcse.h
+++ b/gcc/gcse.h
@@ -43,4 +43,6 @@ void gcse_cc_finalize (void);
extern bool gcse_or_cprop_is_too_expensive (const char *);
extern rtx_insn *insert_insn_end_basic_block (rtx_insn *, basic_block);
+const_rtx single_set_gcse (rtx_insn *insn);
+
#endif
diff --git a/gcc/regpressure.cc b/gcc/regpressure.cc
new file mode 100644
index 00000000000..7846d320a66
--- /dev/null
+++ b/gcc/regpressure.cc
@@ -0,0 +1,391 @@
+/* Register pressure helper functions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "df.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "ira.h"
+#include "gcse.h"
+#include "gcse-common.h"
+#include "regpressure.h"
+
+struct bb_data
+{
+ /* Maximal register pressure inside basic block for given register class
+ (defined only for the pressure classes). */
+ int max_reg_pressure[N_REG_CLASSES];
+ /* Recorded register pressure of basic block before trying to hoist
+ an expression. Will be used to restore the register pressure
+ if the expression should not be hoisted. */
+ int old_pressure;
+ /* Recorded register live_in info of basic block during code hoisting
+ process. BACKUP is used to record live_in info before trying to
+ hoist an expression, and will be used to restore LIVE_IN if the
+ expression should not be hoisted. */
+ bitmap live_in, backup;
+};
+
+#define BB_DATA(bb) ((struct bb_data *) (bb)->aux)
+
+static basic_block curr_bb;
+
+/* Current register pressure for each pressure class. */
+static int curr_reg_pressure[N_REG_CLASSES];
+
+/* Update register pressure for BB when hoisting an expression from
+ instruction FROM, if live ranges of inputs are shrunk. Also
+ maintain live_in information if live range of register referred
+ in FROM is shrunk.
+
+ Return 0 if register pressure doesn't change, otherwise return
+ the number by which register pressure is decreased.
+
+ NOTE: Register pressure won't be increased in this function. */
+
+int
+regpressure_update_bb_reg_pressure (basic_block bb, rtx_insn *from)
+{
+ rtx dreg;
+ rtx_insn *insn;
+ basic_block succ_bb;
+ df_ref use, op_ref;
+ edge succ;
+ edge_iterator ei;
+ int decreased_pressure = 0;
+ int nregs;
+ enum reg_class pressure_class;
+
+ FOR_EACH_INSN_USE (use, from)
+ {
+ dreg = DF_REF_REAL_REG (use);
+ /* The live range of register is shrunk only if it isn't:
+ 1. referred on any path from the end of this block to EXIT, or
+ 2. referred by insns other than FROM in this block. */
+ FOR_EACH_EDGE (succ, ei, bb->succs)
+ {
+ succ_bb = succ->dest;
+ if (succ_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
+ continue;
+
+ if (regpressure_is_live_in (succ_bb, REGNO (dreg)))
+ break;
+ }
+ if (succ != NULL)
+ continue;
+
+ op_ref = DF_REG_USE_CHAIN (REGNO (dreg));
+ for (; op_ref; op_ref = DF_REF_NEXT_REG (op_ref))
+ {
+ if (!DF_REF_INSN_INFO (op_ref))
+ continue;
+
+ insn = DF_REF_INSN (op_ref);
+ if (BLOCK_FOR_INSN (insn) == bb && NONDEBUG_INSN_P (insn)
+ && insn != from)
+ break;
+ }
+
+ pressure_class
+ = regpressure_get_regno_pressure_class (REGNO (dreg), &nregs);
+ /* Decrease register pressure and update live_in information for
+ this block. */
+ if (!op_ref && pressure_class != NO_REGS)
+ {
+ decreased_pressure += nregs;
+ regpressure_decrease (bb, pressure_class, nregs);
+ regpressure_clear_live_in (bb, REGNO (dreg));
+ }
+ }
+ return decreased_pressure;
+}
+
+/* Increase (if INCR_P) or decrease current register pressure for
+ register REGNO. */
+static void
+change_pressure (int regno, bool incr_p)
+{
+ int nregs;
+ enum reg_class pressure_class;
+
+ pressure_class = regpressure_get_regno_pressure_class (regno, &nregs);
+ if (!incr_p)
+ curr_reg_pressure[pressure_class] -= nregs;
+ else
+ {
+ curr_reg_pressure[pressure_class] += nregs;
+ if (regpressure_get (curr_bb, pressure_class)
+ < curr_reg_pressure[pressure_class])
+ BB_DATA (curr_bb)->max_reg_pressure[pressure_class]
+ = curr_reg_pressure[pressure_class];
+ }
+}
+
+/* Calculate register pressure for each basic block by walking insns
+ from last to first. */
+static void
+calculate_bb_reg_pressure (void)
+{
+ int i;
+ unsigned int j;
+ rtx_insn *insn;
+ basic_block bb;
+ bitmap curr_regs_live;
+ bitmap_iterator bi;
+
+ ira_setup_eliminable_regset ();
+ curr_regs_live = BITMAP_ALLOC (®_obstack);
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ curr_bb = bb;
+ BB_DATA (bb)->live_in = BITMAP_ALLOC (NULL);
+ BB_DATA (bb)->backup = BITMAP_ALLOC (NULL);
+ bitmap_copy (BB_DATA (bb)->live_in, df_get_live_in (bb));
+ bitmap_copy (curr_regs_live, df_get_live_out (bb));
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ curr_reg_pressure[ira_pressure_classes[i]] = 0;
+ EXECUTE_IF_SET_IN_BITMAP (curr_regs_live, 0, j, bi)
+ change_pressure (j, true);
+
+ FOR_BB_INSNS_REVERSE (bb, insn)
+ {
+ rtx dreg;
+ int regno;
+ df_ref def, use;
+
+ if (!NONDEBUG_INSN_P (insn))
+ continue;
+
+ FOR_EACH_INSN_DEF (def, insn)
+ {
+ dreg = DF_REF_REAL_REG (def);
+ gcc_assert (REG_P (dreg));
+ regno = REGNO (dreg);
+ if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
+ {
+ if (bitmap_clear_bit (curr_regs_live, regno))
+ change_pressure (regno, false);
+ }
+ }
+
+ FOR_EACH_INSN_USE (use, insn)
+ {
+ dreg = DF_REF_REAL_REG (use);
+ gcc_assert (REG_P (dreg));
+ regno = REGNO (dreg);
+ if (bitmap_set_bit (curr_regs_live, regno))
+ change_pressure (regno, true);
+ }
+ }
+ }
+ BITMAP_FREE (curr_regs_live);
+
+ if (dump_file == NULL)
+ return;
+
+ fprintf (dump_file, "\nRegister Pressure: \n");
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ fprintf (dump_file, " Basic block %d: \n", bb->index);
+ for (i = 0; (int) i < ira_pressure_classes_num; i++)
+ {
+ enum reg_class pressure_class;
+
+ pressure_class = ira_pressure_classes[i];
+ if (BB_DATA (bb)->max_reg_pressure[pressure_class] == 0)
+ continue;
+
+ fprintf (dump_file, " %s=%d\n", reg_class_names[pressure_class],
+ BB_DATA (bb)->max_reg_pressure[pressure_class]);
+ }
+ }
+ fprintf (dump_file, "\n");
+}
+
+/* Initialize needed resources for register pressure calculation. */
+void
+regpressure_init ()
+{
+ regstat_init_n_sets_and_refs ();
+ ira_set_pseudo_classes (false, dump_file);
+ if (flag_ira_hoist_pressure)
+ {
+ alloc_aux_for_blocks (sizeof (struct bb_data));
+ calculate_bb_reg_pressure ();
+ }
+ regstat_free_n_sets_and_refs ();
+}
+
+/* Free up all initialized resources. */
+void
+regpressure_cleanup ()
+{
+ if (flag_ira_hoist_pressure)
+ {
+ free_aux_for_blocks ();
+ }
+ free_reg_info ();
+}
+
+/* Initialize aux data for BB regarding PRESSURE_CLASS. */
+void
+regpressure_init_bb_info (basic_block bb, enum reg_class pressure_class)
+{
+ /* Record old information of basic block BB when it is visited
+ at the first time. */
+ struct bb_data *data = BB_DATA (bb);
+ bitmap_copy (data->backup, data->live_in);
+ data->old_pressure = data->max_reg_pressure[pressure_class];
+}
+
+/* Increase PRESSURE_CLASS's register pressure in BB by NREGS. */
+void
+regpressure_increase (basic_block bb, enum reg_class pressure_class, int nregs)
+{
+ struct bb_data *data = BB_DATA (bb);
+ data->max_reg_pressure[pressure_class] += nregs;
+}
+
+/* Decrease PRESSURE_CLASS's register pressure in BB by NREGS. */
+void
+regpressure_decrease (basic_block bb, enum reg_class pressure_class, int nregs)
+{
+ struct bb_data *data = BB_DATA (bb);
+ data->max_reg_pressure[pressure_class] -= nregs;
+}
+
+/* Reset PRESSURE_CLASS's register pressure in BB to its initial value. */
+void
+regpressure_reset (basic_block bb, enum reg_class pressure_class)
+{
+ struct bb_data *data = BB_DATA (bb);
+ bitmap_copy (data->live_in, data->backup);
+ data->max_reg_pressure[pressure_class] = data->old_pressure;
+}
+
+/* Return TRUE if the current register pressure of PRESSURE_CLASS in BB
+ is less than the number of hard regs. */
+bool
+regpressure_viable (basic_block bb, enum reg_class pressure_class)
+{
+ return (regpressure_get (bb, pressure_class)
+ < ira_class_hard_regs_num[pressure_class]);
+}
+
+/* Return pressure class and number of needed hard registers (through
+ *NREGS) of register REGNO. */
+enum reg_class
+regpressure_get_regno_pressure_class (int regno, int *nregs)
+{
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ enum reg_class pressure_class;
+
+ pressure_class = reg_allocno_class (regno);
+ pressure_class = ira_pressure_class_translate[pressure_class];
+ *nregs
+ = ira_reg_class_max_nregs[pressure_class][PSEUDO_REGNO_MODE (regno)];
+ return pressure_class;
+ }
+ else if (!TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)
+ && !TEST_HARD_REG_BIT (eliminable_regset, regno))
+ {
+ *nregs = 1;
+ return ira_pressure_class_translate[REGNO_REG_CLASS (regno)];
+ }
+ else
+ {
+ *nregs = 0;
+ return NO_REGS;
+ }
+}
+
+/* Return pressure class and number of hard registers (through *NREGS)
+ for destination of INSN. */
+enum reg_class
+regpressure_get_pressure_class_and_nregs (rtx_insn *insn, int *nregs)
+{
+ rtx reg;
+ enum reg_class pressure_class;
+ const_rtx set = single_set_gcse (insn);
+
+ reg = SET_DEST (set);
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+ if (MEM_P (reg))
+ {
+ *nregs = 0;
+ pressure_class = NO_REGS;
+ }
+ else
+ {
+ gcc_assert (REG_P (reg));
+ pressure_class = reg_allocno_class (REGNO (reg));
+ pressure_class = ira_pressure_class_translate[pressure_class];
+ *nregs
+ = ira_reg_class_max_nregs[pressure_class][GET_MODE (SET_SRC (set))];
+ }
+ return pressure_class;
+}
+
+/* Return TRUE if REGNO is live (incoming) in BB. */
+bool
+regpressure_is_live_in (basic_block bb, int regno)
+{
+ return bitmap_bit_p (BB_DATA (bb)->live_in, regno);
+}
+
+/* Clear the live (incoming) bit for REGNO in BB. */
+void
+regpressure_clear_live_in (basic_block bb, int regno)
+{
+ bitmap_clear_bit (BB_DATA (bb)->live_in, regno);
+}
+
+/* Set the live (incoming) bit for REGNO in BB. */
+void
+regpressure_set_live_in (basic_block bb, int regno)
+{
+ bitmap_set_bit (BB_DATA (bb)->live_in, regno);
+}
+
+/* Returns the register pressure for PRESSURE_CLASS in BB. */
+int
+regpressure_get (basic_block bb, enum reg_class pressure_class)
+{
+ return BB_DATA (bb)->max_reg_pressure[pressure_class];
+}
+
+bool
+regpressure_same_class (rtx a, rtx b)
+{
+ enum reg_class a_class, b_class;
+ int a_nregs, b_nregs;
+
+ a_class = regpressure_get_regno_pressure_class (REGNO (a), &a_nregs);
+ b_class = regpressure_get_regno_pressure_class (REGNO (b), &b_nregs);
+
+ return a_class == b_class;
+}
diff --git a/gcc/regpressure.h b/gcc/regpressure.h
new file mode 100644
index 00000000000..b9008699acd
--- /dev/null
+++ b/gcc/regpressure.h
@@ -0,0 +1,48 @@
+/* Register pressure helper functions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_REGPRESSURE_H
+#define GCC_REGPRESSURE_H
+
+int regpressure_update_bb_reg_pressure (basic_block bb, rtx_insn *from);
+
+void regpressure_init ();
+void regpressure_cleanup ();
+
+void regpressure_init_bb_info (basic_block bb, enum reg_class pressure_class);
+
+void regpressure_increase (basic_block bb, enum reg_class pressure_class, int nregs);
+void regpressure_decrease (basic_block bb, enum reg_class pressure_class, int nregs);
+
+int regpressure_get (basic_block bb, enum reg_class pressure_class);
+
+bool regpressure_is_live_in (basic_block bb, int regno);
+void regpressure_clear_live_in (basic_block bb, int regno);
+void regpressure_set_live_in (basic_block bb, int regno);
+
+void regpressure_reset (basic_block bb, enum reg_class pressure_class);
+
+bool regpressure_viable (basic_block bb, enum reg_class pressure_class);
+
+enum reg_class regpressure_get_regno_pressure_class (int regno, int *nregs);
+enum reg_class regpressure_get_pressure_class_and_nregs (rtx_insn *insn, int *nregs);
+
+bool regpressure_same_class (rtx a, rtx b);
+
+#endif
--
2.41.0
next prev parent reply other threads:[~2023-09-07 7:56 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-07 10:26 Robin Dapp
2023-08-24 14:06 ` Robin Dapp
2023-08-28 23:33 ` Jeff Law
2023-08-29 11:40 ` Richard Sandiford
2023-09-05 6:53 ` Robin Dapp
2023-09-05 8:38 ` Richard Sandiford
2023-09-05 8:45 ` Robin Dapp
2023-09-06 11:22 ` Robin Dapp
2023-09-06 20:44 ` Richard Sandiford
2023-09-07 7:56 ` Robin Dapp [this message]
2023-09-07 13:42 ` Richard Sandiford
2023-09-07 14:25 ` Robin Dapp
2023-09-26 16:24 ` Richard Sandiford
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3e0c212c-ef1b-26a6-3515-724cd2bc870f@gmail.com \
--to=rdapp.gcc@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jeffreyalaw@gmail.com \
--cc=richard.sandiford@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).