Hi, revision 171520 changed ARM's CANNOT_CHANGE_MODE_CLASS to loosen up on VFP registers. Richard Sandiford mentioned it being essential for accessing individual lanes/subregs of vector types.
PR48808 and PR48792 basically triggered after the change due to insns like: (insn 39 41 43 2 (set (subreg:SI (reg:HI 234) 0) (fix:SI (fix:DF (reg:DF 77 s14 [233])))) t.i:32 666 {*truncsidf2_vfp} (expr_list:REG_DEAD (reg:DF 77 s14 [233]) (nil))) The output reload trips over when seeing that we can go from SI-->HI in VFP_LO_REGS (CANNOT_CHANGE_MODE_CLASS now returning 0) by attempting to place an HImode into VFP_LO_REGS... This patch tries to fix this by adding back the reg_classes_intersect_p() check, plus further tests to ensure both FROM/TO modes are actually (not) valid for VFP registers. An alternative fix direction would be to add similar mode/regclass validity checks to all places where CANNOT_CHANGE_MODE_CLASS is used in the RTL core, which may stratify things a bit more (the internals documentation does not mention anything on whether the backend should check this mode/regclass condition by itself). But this seems a bit scattered and probably a little risky, so I'll settle for the ARM specific fix for now. This is still pending testing, but the testcases for the two PRs no longer ICE with this fix. It should also not interfere with Richard S' original NEON lane access intention. Okay for trunk if tests pass? Thanks, Chung-Lin 2011-05-30 Chung-Lin Tang <clt...@codesourcery.com> PR target/48808 PR target/48792 * config/arm/arm.h (CANNOT_CHANGE_MODE_CLASS): Return true when FROM or TO modes are invalid for VFP registers.
Index: config/arm/arm.h =================================================================== --- config/arm/arm.h (revision 174395) +++ config/arm/arm.h (working copy) @@ -1103,6 +1103,9 @@ #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ ? reg_classes_intersect_p (FPA_REGS, (CLASS)) \ + || (reg_classes_intersect_p (VFP_REGS, (CLASS)) \ + && (! HARD_REGNO_MODE_OK (FIRST_VFP_REGNUM, (FROM)) \ + || ! HARD_REGNO_MODE_OK (FIRST_VFP_REGNUM, (TO)))) \ : 0) /* The class value for index registers, and the one for base regs. */