public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] gcse: Extract reg pressure handling into separate file.
@ 2023-07-28 10:17 Robin Dapp
  2023-07-31 16:05 ` Jeff Law
  0 siblings, 1 reply; 2+ messages in thread
From: Robin Dapp @ 2023-07-28 10:17 UTC (permalink / raw)
  To: gcc-patches; +Cc: rdapp.gcc

Hi,

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 and I also abstained from c++ifying the code.
The naming with the regpressure_ prefix might be a bit clunky for
now and I'm open to a better scheme.

Some minor helper functions are added that just encapsulate BB aux
data manipulation.  All of this is in preparation for fwprop to
use register pressure data if needed.

Bootstrapped and regtested on x86, aarch64 and power. 

Regards
 Robin

From 65e69834eeb08ba093786e386ac16797cec4d8a7 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 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 | 379 +++++++++++++++++++++++++++++++++++++++++++++
 gcc/regpressure.h  |  46 ++++++
 5 files changed, 445 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 683774ad446..88880a8e23e 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1605,6 +1605,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..1c967528b04
--- /dev/null
+++ b/gcc/regpressure.cc
@@ -0,0 +1,379 @@
+/* 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 (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;
+	  BB_DATA (bb)->max_reg_pressure[pressure_class] -= nregs;
+	  bitmap_clear_bit (BB_DATA (bb)->live_in, 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 (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");
+}
+
+/* Initialized needed resources for register pressure calculation.  */
+void
+regpressure_init ()
+{
+  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 ();
+    }
+}
+
+/* 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 (BB_DATA (bb)->max_reg_pressure[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 in BB.  */
+bool
+regpressure_is_live (basic_block bb, int regno)
+{
+  return bitmap_bit_p (BB_DATA (bb)->live_in, regno);
+}
+
+/* Clear the live bit for REGNO in BB.  */
+void
+regpressure_clear_live (basic_block bb, int regno)
+{
+  bitmap_clear_bit (BB_DATA (bb)->live_in, regno);
+}
+
+/* Set the live bit for REGNO in BB.  */
+void
+regpressure_set_live (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];
+}
diff --git a/gcc/regpressure.h b/gcc/regpressure.h
new file mode 100644
index 00000000000..e987d3c7bfe
--- /dev/null
+++ b/gcc/regpressure.h
@@ -0,0 +1,46 @@
+/* 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 (basic_block bb, int regno);
+void regpressure_clear_live (basic_block bb, int regno);
+void regpressure_set_live (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);
+
+#endif
-- 
2.41.0

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] gcse: Extract reg pressure handling into separate file.
  2023-07-28 10:17 [PATCH] gcse: Extract reg pressure handling into separate file Robin Dapp
@ 2023-07-31 16:05 ` Jeff Law
  0 siblings, 0 replies; 2+ messages in thread
From: Jeff Law @ 2023-07-31 16:05 UTC (permalink / raw)
  To: Robin Dapp, gcc-patches



On 7/28/23 04:17, Robin Dapp via Gcc-patches wrote:
> Hi,
> 
> 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 and I also abstained from c++ifying the code.
> The naming with the regpressure_ prefix might be a bit clunky for
> now and I'm open to a better scheme.
> 
> Some minor helper functions are added that just encapsulate BB aux
> data manipulation.  All of this is in preparation for fwprop to
> use register pressure data if needed.
> 
> Bootstrapped and regtested on x86, aarch64 and power.
> 
> Regards
>   Robin
> 
>  From 65e69834eeb08ba093786e386ac16797cec4d8a7 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 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.
OK.  Feel free to C++ify if you want now ;-)  Having a reasonably well 
encapculated module to allow us to query register pressure seems like a 
step forward.

jeff

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-07-31 16:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-28 10:17 [PATCH] gcse: Extract reg pressure handling into separate file Robin Dapp
2023-07-31 16:05 ` Jeff Law

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