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