Hello,
I am seeing GCC combining:
(insn 17 16 18 3 (set (reg:SI 104 [ D.4588 ])
(zero_extend:SI (reg:HI 103 [ D.4587 ]))) test-18.c:24 1426
{zero_extendhisi2}
(expr_list:REG_DEAD (reg:HI 103 [ D.4587 ])
(nil)))
(insn 18 17 19 3 (set (reg:BI 105)
(gt:BI (reg:SI 104 [ D.4588 ])
(const_int 4 [0x4]))) test-18.c:24 1372 {cmp_simode}
(expr_list:REG_DEAD (reg:SI 104 [ D.4588 ])
(nil)))
into a paradoxical use:
(set (reg:BI 105)
(gt:BI (subreg:SI (reg:HI 103 [ D.4587 ]) 0)
(const_int 4 [0x4])))
Reload then transforms (subreg:SI (reg:HI 103 [ D.4587 ]) 0) into (reg:SI 18),
allocating 103 to 18, but changing the mode to SI.
This is wrong and it will generate wrong code.
I can use canonicalize_comparison like s390 to remove the subreg, however the
question then becomes about how to avoid this in general. We cannot allow a
zero_extend to become a paradoxical subreg and then have the subreg discarded.
Most of our instructions are vector instructions which will change the
remainder of the register.
I have defined WORD_REGISTER_OPERATIONS and CANNOT_CHANGE_MODE_CLASS(from, to,
class) and set it to true if GET_MODE_SIZE (from) < GET_MODE_SIZE (to) but it
didn't help.
Any suggestions for a generic solution?
Paulo Matos