lra: Tighten check for reloading paradoxical subregs [PR94052]
authorRichard Sandiford <richard.sandiford@arm.com>
Mon, 9 Mar 2020 19:42:57 +0000 (19:42 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Sat, 21 Mar 2020 08:53:30 +0000 (08:53 +0000)
commit497498c878d48754318e486428e2aa30854020b9
treeab6586cb024f7e343a0116430fc67e05c2f68c66
parent15711e837b245ab1bbd2c9c49a010524d4e9d384
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.
gcc/ChangeLog
gcc/lra-constraints.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.target/aarch64/pr94052.C [new file with mode: 0644]