[V2,5/7] ira: Add all nregs >= 2 pseudos to tracke subreg list

Message ID 20231112095858.3669003-6-lehua.ding@rivai.ai
State Unresolved
Headers
Series ira/lra: Support subreg coalesce |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Lehua Ding Nov. 12, 2023, 9:58 a.m. UTC
  This patch relax the subreg track capability to all subreg registers.

gcc/ChangeLog:

	* ira-build.cc (get_reg_unit_size): New.
	(has_same_nregs): New.
	(ira_set_allocno_class): Adjust.

---
 gcc/ira-build.cc | 41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)
  

Patch

diff --git a/gcc/ira-build.cc b/gcc/ira-build.cc
index 13f0f7336ed..f88aeeeeaef 100644
--- a/gcc/ira-build.cc
+++ b/gcc/ira-build.cc
@@ -607,6 +607,37 @@  ira_create_allocno (int regno, bool cap_p,
   return a;
 }
 
+/* Return single register size of allocno A.  */
+static poly_int64
+get_reg_unit_size (ira_allocno_t a)
+{
+  enum reg_class aclass = ALLOCNO_CLASS (a);
+  gcc_assert (aclass != NO_REGS);
+  machine_mode mode = ALLOCNO_MODE (a);
+  int nregs = ALLOCNO_NREGS (a);
+  poly_int64 block_size = REGMODE_NATURAL_SIZE (mode);
+  int nblocks = get_nblocks (mode);
+  gcc_assert (nblocks % nregs == 0);
+  return block_size * (nblocks / nregs);
+}
+
+/* Return true if TARGET_CLASS_MAX_NREGS and TARGET_HARD_REGNO_NREGS results is
+   same. It should be noted that some targets may not implement these two very
+   uniformly, and need to be debugged step by step. For example, in V3x1DI mode
+   in AArch64, TARGET_CLASS_MAX_NREGS returns 2 but TARGET_HARD_REGNO_NREGS
+   returns 3. They are in conflict and need to be repaired in the Hook of
+   AArch64.  */
+static bool
+has_same_nregs (ira_allocno_t a)
+{
+  for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (REGNO_REG_CLASS (i) != NO_REGS
+	&& reg_class_subset_p (REGNO_REG_CLASS (i), ALLOCNO_CLASS (a))
+	&& ALLOCNO_NREGS (a) != hard_regno_nregs (i, ALLOCNO_MODE (a)))
+      return false;
+  return true;
+}
+
 /* Set up register class for A and update its conflict hard
    registers.  */
 void
@@ -624,12 +655,12 @@  ira_set_allocno_class (ira_allocno_t a, enum reg_class aclass)
 
   if (aclass == NO_REGS)
     return;
-  /* SET the unit_size of one register.  */
-  machine_mode mode = ALLOCNO_MODE (a);
-  int nregs = ira_reg_class_max_nregs[aclass][mode];
-  if (nregs == 2 && maybe_eq (GET_MODE_SIZE (mode), nregs * UNITS_PER_WORD))
+  gcc_assert (!ALLOCNO_TRACK_SUBREG_P (a));
+  /* Set unit size and track_subreg_p flag for pseudo which need occupied multi
+     hard regs.  */
+  if (ALLOCNO_NREGS (a) > 1 && has_same_nregs (a))
     {
-      ALLOCNO_UNIT_SIZE (a) = UNITS_PER_WORD;
+      ALLOCNO_UNIT_SIZE (a) = get_reg_unit_size (a);
       ALLOCNO_TRACK_SUBREG_P (a) = true;
       return;
     }