This patch completely relax to track all eligible subregs. gcc/ChangeLog:
* ira-build.cc (get_reg_unit_size): New. (has_same_nregs): New. (ira_set_allocno_class): Relax. --- gcc/ira-build.cc | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/gcc/ira-build.cc b/gcc/ira-build.cc index 1c47f81ce9d..379f877ca67 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; } -- 2.36.3