[24/61] P5600: Option -msched-weight added

Message ID 20250131171232.1018281-26-aleksandar.rakic@htecgroup.com
State New
Headers
Series Improve Mips target |

Commit Message

Aleksandar Rakic Jan. 31, 2025, 5:13 p.m. UTC
  From: Jaydeep Patil <jaydeep.patil@imgtec.com>

Cherry-picked 0cf2542b41d8102800af180f0b6da1fe55a9d76b
from https://github.com/MIPS/gcc

Signed-off-by: Prachi Godbole <prachi.godbole@imgtec.com>
Signed-off-by: Jaydeep Patil <jaydeep.patil@imgtec.com>
Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
Signed-off-by: Aleksandar Rakic <aleksandar.rakic@htecgroup.com>
---
 gcc/config/mips/mips.cc  | 242 +++++++++++++++++++++++++++++++++++++++
 gcc/config/mips/mips.opt |   3 +
 2 files changed, 245 insertions(+)
  

Patch

diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 56e0d4ba021..55339d577fb 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -74,6 +74,17 @@  along with GCC; see the file COPYING3.  If not see
 /* This file should be included last.  */
 #include "target-def.h"
 
+/* Definitions used in ready queue reordering for first scheduling pass.  */
+
+static int *level = NULL;
+static int *consumer_luid = NULL;
+
+#define LEVEL(INSN)	\
+  level[INSN_UID ((INSN))]
+
+#define CONSUMER_LUID(INSN)	\
+  consumer_luid[INSN_UID ((INSN))]
+
 /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF.  */
 #define UNSPEC_ADDRESS_P(X)					\
   (GET_CODE (X) == UNSPEC					\
@@ -16737,6 +16748,220 @@  mips_74k_agen_reorder (rtx_insn **ready, int nready)
       break;
     }
 }
+
+/* These functions are called when -msched-weight is set.  */
+
+/* Find register born in given X if any.  */
+
+static int
+find_reg_born (rtx x)
+{
+  if (GET_CODE (x) == CLOBBER)
+    return 1;
+
+  if (GET_CODE (x) == SET)
+    {
+      if (REG_P (SET_DEST (x)) && reg_mentioned_p (SET_DEST (x), SET_SRC (x)))
+	return 0;
+      return 1;
+    }
+  return 0;
+}
+
+/* Calculate register weight for given INSN.  */
+
+static int
+get_weight (rtx insn)
+{
+  int weight = 0;
+  rtx x;
+
+  /* Increment weight for each register born here.  */
+  x = PATTERN (insn);
+  weight = find_reg_born (x);
+
+  if (GET_CODE (x) == PARALLEL)
+    {
+      int i;
+      for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
+	{
+	  x = XVECEXP (PATTERN (insn), 0, i);
+	  weight += find_reg_born (x);
+	}
+    }
+
+  /* Decrement weight for each register that dies here.  */
+  for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
+    {
+      if (REG_NOTE_KIND (x) == REG_DEAD || REG_NOTE_KIND (x) == REG_UNUSED)
+	{
+	  rtx note = XEXP (x, 0);
+	  if (REG_P (note))
+	    weight--;
+	}
+    }
+  return weight;
+}
+
+/* TARGET_SCHED_WEIGHT helper function.
+   Allocate and initialize global data.  */
+
+static void
+mips_weight_init_global (int old_max_uid)
+{
+  level = (int *) xcalloc (old_max_uid, sizeof (int));
+  consumer_luid = (int *) xcalloc (old_max_uid, sizeof (int));
+}
+
+/* Implement TARGET_SCHED_INIT_GLOBAL.  */
+
+static void
+mips_sched_init_global (FILE *dump ATTRIBUTE_UNUSED,
+			int verbose ATTRIBUTE_UNUSED,
+			int old_max_uid)
+{
+  if (!reload_completed && TARGET_SCHED_WEIGHT)
+    mips_weight_init_global (old_max_uid);
+}
+
+/* TARGET_SCHED_WEIGHT helper function.  Called for each basic block
+   with dependency chain information in HEAD and TAIL.
+   Calculates LEVEL for each INSN from its forward dependencies
+   and finds out UID of first consumer instruction (CONSUMER_LUID) of INSN.  */
+
+static void
+mips_weight_evaluation (rtx_insn *head, rtx_insn *tail)
+{
+  sd_iterator_def sd_it;
+  dep_t dep;
+  rtx_insn *prev_head, *insn;
+  rtx x;
+  prev_head = PREV_INSN (head);
+
+  for (insn = tail; insn != prev_head; insn = PREV_INSN (insn))
+    if (INSN_P (insn))
+      {
+	FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
+	  {
+	    x = DEP_CON (dep);
+	    if (! DEBUG_INSN_P (x))
+	      {
+		if (LEVEL (x) > LEVEL (insn))
+		  LEVEL (insn) = LEVEL (x);
+		CONSUMER_LUID (insn) = INSN_LUID (x);
+	      }
+	  }
+	LEVEL (insn)++;
+      }
+}
+
+/* Implement TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK.  */
+
+static void
+mips_evaluation_hook (rtx_insn *head, rtx_insn *tail)
+{
+  if (!reload_completed && TARGET_SCHED_WEIGHT)
+    mips_weight_evaluation (head, tail);
+}
+
+/* Implement TARGET_SCHED_SET_SCHED_FLAGS.
+   Enables DONT_BREAK_DEPENDENCIES for the first scheduling pass.
+   It prevents breaking of dependencies on mem/inc pair in the first pass
+   which would otherwise increase stalls.  */
+
+static void
+mips_set_sched_flags (spec_info_t spec_info ATTRIBUTE_UNUSED)
+{
+  if (!reload_completed && TARGET_SCHED_WEIGHT)
+    {
+      unsigned int *flags = &(current_sched_info->flags);
+      *flags |= DONT_BREAK_DEPENDENCIES;
+    }
+}
+
+static void
+mips_weight_finish_global ()
+{
+  if (level != NULL)
+    free (level);
+
+  if (consumer_luid != NULL)
+    free (consumer_luid);
+}
+
+/* Implement TARGET_SCHED_FINISH_GLOBAL.  */
+
+static void
+mips_sched_finish_global (FILE *dump ATTRIBUTE_UNUSED,
+			  int verbose ATTRIBUTE_UNUSED)
+{
+  if (!reload_completed && TARGET_SCHED_WEIGHT)
+    mips_weight_finish_global ();
+}
+
+
+/* This is a TARGET_SCHED_WEIGHT (option -msched-weight) helper function
+   which is called during reordering of instructions in the first pass
+   of the scheduler.  The function swaps the instruction at (NREADY - 1)
+   of the READY list with another instruction in READY list as per
+   the following algorithm.  The scheduler then picks the instruction
+   at READY[NREADY - 1] and schedules it.
+
+   Every instruction is assigned with a value LEVEL.
+   [See: mips_weight_evaluation ().]
+
+   1. INSN with highest LEVEL is chosen to be scheduled next, ties broken by
+      1a. Choosing INSN that is used early in the flow or
+      1b. Choosing INSN with greater INSN_TICK.
+
+   2. Choose INSN having less LEVEL number iff,
+      2a. It is used early and
+      2b. Has greater INSN_TICK and
+      2c. Contributes less to the register pressure.  */
+
+static void
+mips_sched_weight (rtx_insn **ready, int nready)
+{
+  int max_level = LEVEL (ready[nready-1]), toswap = nready-1;
+  int i;
+#define INSN_TICK(INSN) (HID (INSN)->tick)
+
+  for (i = nready - 2; i >= 0; i--)
+    {
+      rtx_insn *insn = ready[i];
+      if (LEVEL (insn) == max_level)
+	{
+	  if (INSN_PRIORITY (insn) >= INSN_PRIORITY (ready[toswap]))
+	    {
+	      if (CONSUMER_LUID (insn) < CONSUMER_LUID (ready[toswap]))
+		toswap = i;
+	    }
+	  else if (INSN_TICK (insn) > INSN_TICK (ready[toswap]))
+	    toswap = i;
+	}
+      if (LEVEL (insn) > max_level)
+	{
+	  max_level = LEVEL (insn);
+	  toswap = i;
+	}
+      if (LEVEL (insn) < max_level)
+	{
+	  if (CONSUMER_LUID (insn) < CONSUMER_LUID (ready[toswap])
+	      && INSN_TICK (insn) > INSN_TICK (ready[toswap])
+	      && get_weight (insn) < get_weight (ready[toswap]))
+	    toswap = i;
+	}
+    }
+
+  if (toswap != (nready-1))
+    {
+      rtx_insn *temp = ready[nready-1];
+      ready[nready-1] = ready[toswap];
+      ready[toswap] = temp;
+    }
+#undef INSN_TICK
+}
+
 
 /* Implement TARGET_SCHED_INIT.  */
 
@@ -16774,6 +16999,11 @@  mips_sched_reorder_1 (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
 
   if (TUNE_74K)
     mips_74k_agen_reorder (ready, *nreadyp);
+
+  if (! reload_completed
+      && TARGET_SCHED_WEIGHT
+      && *nreadyp > 1)
+    mips_sched_weight (ready, *nreadyp);
 }
 
 /* Implement TARGET_SCHED_REORDER.  */
@@ -25252,6 +25482,18 @@  mips_bit_clear_p (enum machine_mode mode, unsigned HOST_WIDE_INT m)
 #undef TARGET_SECTION_TYPE_FLAGS
 #define TARGET_SECTION_TYPE_FLAGS mips_section_type_flags
 
+#undef TARGET_SCHED_INIT_GLOBAL
+#define TARGET_SCHED_INIT_GLOBAL mips_sched_init_global
+
+#undef TARGET_SCHED_FINISH_GLOBAL
+#define TARGET_SCHED_FINISH_GLOBAL mips_sched_finish_global
+
+#undef TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
+#define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK mips_evaluation_hook
+
+#undef TARGET_SCHED_SET_SCHED_FLAGS
+#define TARGET_SCHED_SET_SCHED_FLAGS mips_set_sched_flags
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-mips.h"
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index fa6ecd988a6..d162702c220 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -573,3 +573,6 @@  Target Undocumented Var(TARGET_USE_COPYW_UCOPYW) Init(-1)
 minline-intermix
 Target Var(TARGET_INLINE_INTERMIX)
 Allow inlining even if the compression flags differ between caller and callee.
+
+msched-weight
+Target Var(TARGET_SCHED_WEIGHT) Undocumented