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


Reply via email to