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