https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94567
--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So something like: --- gcc/config/i386/i386.md.jj 2020-03-16 22:56:55.556043275 +0100 +++ gcc/config/i386/i386.md 2020-04-15 19:07:04.405933639 +0200 @@ -8732,8 +8732,20 @@ && ix86_match_ccmode (insn, /* *testdi_1 requires CCZmode if the mask has bit 31 set and all bits above it clear. */ - GET_MODE (operands[2]) == DImode - && INTVAL (operands[3]) + INTVAL (operands[4]) == 32 + (GET_MODE (operands[2]) == DImode + && INTVAL (operands[3]) + INTVAL (operands[4]) == 32) + /* If zero_extract mode precision is the same + as len, the SF of the zero_extract + comparison will be the most significant + extracted bit, but this could be matched + after splitting only for pos 0 len all bits + trivial extractions. Require CCZmode. */ + || (GET_MODE_PRECISION (<MODE>mode) + == INTVAL (operands[3])) + /* Otherwise, require CCZmode if we'd use a mask + with the most significant bit set. */ + || (INTVAL (operands[3]) + INTVAL (operands[4]) + == GET_MODE (operands[2])) ? CCZmode : CCNOmode)" "#" "&& 1" @@ -8758,7 +8770,12 @@ } /* Small HImode tests can be converted to QImode. */ - if (register_operand (val, HImode) && pos + len <= 8) + if (register_operand (val, HImode) + && (pos + len < 8 + /* If the mask would include all bits, ensure we don't + care about the SF. */ + || (pos + len == 8 + && GET_MODE (operands[0]) == CCZmode))) { val = gen_lowpart (QImode, val); mode = QImode;