Hi,

Combine canonicalizes certain AND masks in a comparison with zero into extracts 
of the widest
register type. During matching these are expanded into a very inefficient 
sequence that fails to
match. For example (x & 2) == 0 is matched in combine like this:

Failed to match this instruction:
(set (reg:CC 66 cc)
    (compare:CC (zero_extract:DI (subreg:DI (reg/v:SI 76 [ xD.2641 ]) 0)
            (const_int 1 [0x1])
            (const_int 1 [0x1]))
        (const_int 0 [0])))
Failed to match this instruction:
(set (reg:CC 66 cc)
    (compare:CC (and:DI (lshiftrt:DI (subreg:DI (reg/v:SI 76 [ xD.2641 ]) 0)
                (const_int 1 [0x1]))
            (const_int 1 [0x1]))
        (const_int 0 [0])))

Neither matches the AArch64 patterns for ANDS/TST (which is just compare and 
AND). If the immediate
is not a power of 2 or a power of 2 -1 then it matches correctly as expected.

I don't understand how ((x >> 1) & 1) != 0 could be a useful expansion (it even 
uses shifts by 0 at
times which are unlikely to ever match anything). Why does combine not try to 
match the obvious (x &
C) != 0 case? Single-bit and mask tests are very common, so this blocks 
efficient code generation on
many targets.

It's trivial to change change_zero_ext to expand extracts always into AND and 
remove the redundant
subreg. However wouldn't it make more sense to never special case certain AND 
immediate in the first
place?

Wilco






Reply via email to