[V3,5/7] ira: Add all nregs >= 2 pseudos to tracke subreg list
Checks
Commit Message
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
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.
@@ -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;
}