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