diff mbox series

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

Message ID 20231112120817.2635864-6-lehua.ding@rivai.ai
State New
Headers show
Series ira/lra: Support subreg coalesce | expand

Commit Message

Lehua Ding Nov. 12, 2023, 12:08 p.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(-)

Comments

Vladimir Makarov Nov. 16, 2023, 9:14 p.m. UTC | #1
On 11/12/23 07:08, Lehua Ding wrote:
> This patch relax the subreg track capability to all subreg registers.
The patch is ok for me when general issues I mentioned in my first email 
and the issue given below are fixed.
> gcc/ChangeLog:
>
> 	* ira-build.cc (get_reg_unit_size): New.
> 	(has_same_nregs): New.
> 	(ira_set_allocno_class): Adjust.
>
...
> +
> +/* 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;
> +}
> +

It is better to fix the problem source.  But sometimes it is hard to do 
this for all targets.  RA already has analogous code.  So it is ok for 
me.  The only thing is that it is too expensive to do this for each 
allocno.  You should implement some cache (class, mode)->result.
diff mbox series

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;
     }