This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: Combine of compare & and oddity


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







Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]