https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94567
--- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> --- (In reply to Jeffrey A. Law from comment #11) > Rather than extending that hack, I think just widening the mode when the > sign bit is being tested (c#5) is simpler and easier to understand. The > bits you're changing should be killed rather than extended to handle more > cases. That is not a hack. x86_64 doesn't have an instruction that ands a 64-bit reg/mem with a 32-bit zero extended immediate (nor 64-bit immediate), so when we want to use reg against 32-bit zero extended, we need to use 32-bit instruction and that has different behavior for the SF, so we must ensure we don't care about that most significant bit. Now for these other cases, perhaps we could instead user wider mode if possible, but it isn't possible always. So, combine my patch with the last condition changed into >= 32 from == GET_MODE (operands[2]) and then apply what you have in #c5, but with hardcoded SImode instead of wider mode - we want to avoid introducing HImode stuff when there wasn't before, it is both larger and slower - and only do it if GET_MODE (operands[0]) isn't CCZmode. If pos + len >= 32, such in the pos + len == 64 special case where we turn testing bits pos (< 32) up to most significant into a testq which has that sign-extended 32-bit immediate, then the pattern before splitting would have always SF zero (unless pos is 0) but split pattern would always copy there the MSB of the 64-bit register.