aboutsummaryrefslogtreecommitdiff
path: root/gcc/lra-constraints.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2020-03-09 19:42:57 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2020-03-21 08:53:30 +0000
commit497498c878d48754318e486428e2aa30854020b9 (patch)
treeab6586cb024f7e343a0116430fc67e05c2f68c66 /gcc/lra-constraints.c
parent15711e837b245ab1bbd2c9c49a010524d4e9d384 (diff)
downloadgcc-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.c24
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