https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94567
--- Comment #5 from Jeffrey A. Law <law at redhat dot com> --- I've pondered just killing that pattern, but I'm pretty sure there'll be notable regressions. There was a clear regression we fixed in gcc-6 due to not handling QImode operands in that pattern. What I'm playing with is looking at pos + len and if it hits the sign bit in the operand's mode, then widening the mode. Something like this: + /* If the mask is going to have the sign bit set in the mode + we want to do the comparison, then we must widen the target + mode. Otherwise the flags will be incorrect when we split + this into a (compare (and (op0) (mask))) and a subsequent + test like LE will get the wrong result. */ + if (mode < E_DImode + && pos + len == GET_MODE_PRECISION (mode)) + { + mode = GET_MODE_WIDER_MODE (mode).require (); + val = gen_lowpart (mode, val); + } + Which I think is roughly what you were suggesting. Mine does it with a SUBREG, so it matches existing patterns... A ZERO_EXTEND may well require new patterns.