On Thu, Feb 02, 2017 at 11:27:12AM +0100, Aurelien Buhrig wrote:
> > Hrm, maybe you can show the RTL before and after this transform?
> RTL before combine:
> (set (reg:SI 31 (lshiftt:SI (reg:SI 29) (const_int 16))))
> (set (reg:HI 1 "r1") (reg:HI 25))
> (set (reg:HI 0 "r0") (subreg:HI (reg:SI 31) 0))    ; LE target
> 
> r0 and r1 are HI regs
> 
> RTL after combining 1 --> 3:
> (set (reg:HI 1 "r1") (reg:HI 25))
> (set (reg:SI 0 "r0") (lshift:SI (reg:SI 29) (const_int 16)))
>  and r1 is clobbered by last insn.

Ah, much clearer now, thanks!

There is this test:

      && (((GET_MODE_SIZE (GET_MODE (src)) + (UNITS_PER_WORD - 1))
           / UNITS_PER_WORD)
          == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
               + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))

On most targets the size of a register is (at least) UNITS_PER_WORD, so
this works there.  But this code should really use can_change_dest_mode,
at least for hard registers, which does

  if (regno < FIRST_PSEUDO_REGISTER)
    return (HARD_REGNO_MODE_OK (regno, mode)
            && REG_NREGS (x) >= hard_regno_nregs[regno][mode]);

i.e. it tests the new mode does not use more hard registers than the
old one did, which indeed would be bad.


Segher

Reply via email to