From 497498c878d48754318e486428e2aa30854020b9 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 9 Mar 2020 19:42:57 +0000 Subject: lra: Tighten check for reloading paradoxical subregs [PR94052] simplify_operand_subreg tries to detect whether the allocation for a pseudo in a paradoxical subreg is also valid for the outer mode. The condition it used to check for an invalid combination was: else if (REG_P (reg) && REGNO (reg) >= FIRST_PSEUDO_REGISTER && (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0 && (hard_regno_nregs (hard_regno, innermode) < hard_regno_nregs (hard_regno, mode)) && (regclass = lra_get_allocno_class (REGNO (reg))) && (type != OP_IN || !in_hard_reg_set_p (reg_class_contents[regclass], mode, hard_regno) || overlaps_hard_reg_set_p (lra_no_alloc_regs, mode, hard_regno))) I think there are two problems with this: (1) It never actually checks whether the hard register is valid for the outer mode (in the hard_regno_mode_ok sense). If it isn't, any attempt to reload in the outer mode is likely to cycle, because the implied regno/mode combination will be just as invalid next time curr_insn_transform sees the subreg. (2) The check is valid for little-endian only. For big-endian we need to move hard_regno backwards. Using simplify_subreg_regno should avoid both problems. As the existing comment says, IRA should always take subreg references into account when allocating hard registers, so this fix-up should only really be needed for pseudos allocated by LRA itself. gcc/ 2020-03-21 Richard Sandiford PR rtl-optimization/94052 * lra-constraints.c (simplify_operand_subreg): Reload the inner register of a paradoxical subreg if simplify_subreg_regno fails to give a valid hard register for the outer mode. gcc/testsuite/ 2020-03-21 Tamar Christina PR target/94052 * gcc.target/aarch64/pr94052.C: New test. --- gcc/lra-constraints.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'gcc/lra-constraints.c') diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index f71e0c9..bf6d4a2 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -1489,7 +1489,7 @@ static bool process_address (int, bool, rtx_insn **, rtx_insn **); static bool simplify_operand_subreg (int nop, machine_mode reg_mode) { - int hard_regno; + int hard_regno, inner_hard_regno; rtx_insn *before, *after; machine_mode mode, innermode; rtx reg, new_reg; @@ -1735,15 +1735,19 @@ simplify_operand_subreg (int nop, machine_mode reg_mode) for the new uses. */ else if (REG_P (reg) && REGNO (reg) >= FIRST_PSEUDO_REGISTER - && (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0 - && (hard_regno_nregs (hard_regno, innermode) - < hard_regno_nregs (hard_regno, mode)) - && (regclass = lra_get_allocno_class (REGNO (reg))) - && (type != OP_IN - || !in_hard_reg_set_p (reg_class_contents[regclass], - mode, hard_regno) - || overlaps_hard_reg_set_p (lra_no_alloc_regs, - mode, hard_regno))) + && paradoxical_subreg_p (operand) + && (inner_hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0 + && ((hard_regno + = simplify_subreg_regno (inner_hard_regno, innermode, + SUBREG_BYTE (operand), mode)) < 0 + || ((hard_regno_nregs (inner_hard_regno, innermode) + < hard_regno_nregs (hard_regno, mode)) + && (regclass = lra_get_allocno_class (REGNO (reg))) + && (type != OP_IN + || !in_hard_reg_set_p (reg_class_contents[regclass], + mode, hard_regno) + || overlaps_hard_reg_set_p (lra_no_alloc_regs, + mode, hard_regno))))) { /* The class will be defined later in curr_insn_transform. */ enum reg_class rclass -- cgit v1.1