https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96938
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Plus the less reduced testcase: void baz (char *f, int o, char v) { *f = (*f & ~(1 << o)) | (v << o); } On bar above, we match this during combine: Trying 10, 11 -> 13: 10: r96:SI=0xfffffffffffffffe 11: {r98:SI=r96:SI<-<r93:SI#0;clobber flags:CC;} REG_UNUSED flags:CC REG_DEAD r96:SI 13: {r100:SI=r98:SI&r99:SI;clobber flags:CC;} REG_DEAD r99:SI REG_DEAD r98:SI REG_UNUSED flags:CC Successfully matched this instruction into *btrsi: (parallel [ (set (reg:SI 100 [ t ]) (and:SI (rotate:SI (const_int -2 [0xfffffffffffffffe]) (subreg:QI (reg/v:SI 93 [ o ]) 0)) (reg:SI 99 [ *f_11(D) ]))) (clobber (reg:CC 17 flags)) ]) but on baz the similar 3 insns fails: Trying 10, 11 -> 12: 10: r95:SI=0xfffffffffffffffe 11: {r97:QI#0=r95:SI<-<r92:SI#0;clobber flags:CC;} REG_UNUSED flags:CC REG_DEAD r95:SI 12: {r98:QI=r97:QI&[r91:DI];clobber flags:CC;} REG_DEAD r97:QI REG_UNUSED flags:CC Failed to match this instruction: (parallel [ (set (reg:QI 98) (and:QI (subreg:QI (rotate:SI (const_int -2 [0xfffffffffffffffe]) (subreg:QI (reg/v:SI 92 [ o ]) 0)) 0) (mem:QI (reg/v/f:DI 91 [ f ]) [0 *f_11(D)+0 S1 A8]))) (clobber (reg:CC 17 flags)) ]) and similarly with foo: Trying 8, 9 -> 10: 8: r89:SI=0xfffffffffffffffe 9: {r91:QI#0=r89:SI<-<r93:SI#0;clobber flags:CC;} REG_UNUSED flags:CC REG_DEAD r93:SI REG_DEAD r89:SI 10: {[r92:DI]=[r92:DI]&r91:QI;clobber flags:CC;} REG_DEAD r92:DI REG_UNUSED flags:CC REG_DEAD r91:QI Failed to match this instruction: (parallel [ (set (zero_extract:HI (mem:QI (reg:DI 92) [0 *x_7(D)+0 S1 A8]) (const_int 1 [0x1]) (zero_extend:SI (subreg:QI (reg:SI 93) 0))) (const_int 0 [0])) (clobber (reg:CC 17 flags)) ]) There is no btrb instruction (there is btrw though) but we couldn't really use that anyway because the shifts are 32-bit and need to be well defined even if the shift count is >= 8.