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;