diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2020-03-09 19:42:57 +0000 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2020-03-21 08:53:30 +0000 |
commit | 497498c878d48754318e486428e2aa30854020b9 (patch) | |
tree | ab6586cb024f7e343a0116430fc67e05c2f68c66 /gcc/lra-constraints.c | |
parent | 15711e837b245ab1bbd2c9c49a010524d4e9d384 (diff) | |
download | gcc-497498c878d48754318e486428e2aa30854020b9.zip gcc-497498c878d48754318e486428e2aa30854020b9.tar.gz gcc-497498c878d48754318e486428e2aa30854020b9.tar.bz2 |
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 <richard.sandiford@arm.com>
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 <tamar.christina@arm.com>
PR target/94052
* gcc.target/aarch64/pr94052.C: New test.
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r-- | gcc/lra-constraints.c | 24 |
1 files changed, 14 insertions, 10 deletions
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 |