public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
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 (&reg_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 (&reg_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



  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).