https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119971
--- Comment #2 from Jeffrey A. Law <law at gcc dot gnu.org> --- The pattern Andrew quoted I think is OK. It "eats" the & 31 because that's implicitly done by the hardware for the "w" forms of the shift instructions. The real problem is when we use that shift count in this pattern: ;; The logical-and against 0x1 implicitly extends the result. So we can treat ;; an SImode bext as-if it's DImode without any explicit extension. (define_insn "*bextdisi" [(set (match_operand:DI 0 "register_operand" "=r") (and:DI (subreg:DI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") (match_operand:QI 2 "register_operand" "r")) 0) (const_int 1)))] "TARGET_64BIT && TARGET_ZBS" "bext\t%0,%1,%2" [(set_attr "type" "bitmanip")]) It might seem like that pattern is safe, particularly since a shift count outside 0..31 would be undefined behavior. But the hw is going to use an & 63 mask rather than a & 31 mask for rv64. So when the splitter corerctly eliminates the & 31 and we match the bextdisi pattern we can get incorrect results. I need to ponder this a bit more. But that's my take right now.