https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109907
--- Comment #19 from Georg-Johann Lay <gjl at gcc dot gnu.org> --- Created attachment 55139 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55139&action=edit C test case, insert bits in place This testcase is from PR82931. It transfers one bit to the same bit-position in the output: typedef __UINT8_TYPE__ uint8_t; #define Bit8Mask ((uint8_t) BitMask) void merge1_8 (uint8_t *dst, const uint8_t *src) { *dst = (*src & BitMask) | (*dst & ~ Bit8Mask); } void merge2_8 (uint8_t *dst, const uint8_t *src) { *dst ^= (*dst ^ *src) & Bit8Mask; } combine detects in merge1_8 that this is a bit insertion, but fails because the input is MEM: Failed to match this instruction: (set (zero_extract:QI (mem:QI (reg/v/f:HI 48 [ dst ]) [0 *dst_8(D)+0 S1 A8]) (const_int 1 [0x1]) (const_int 4 [0x4])) (lshiftrt:QI (reg:QI 50) (const_int 4 [0x4]))) So maybe this is a missed opportunity in combine, or combine cannot split away the MEM because it doesn't have a pseudo handy (combine cannot pop new pseudos). The target could handle this: Supply an insn that matches, and then split the MEM in split1 to a new pseudo. No need to say, that's not an optimal solution. In merge2_8, combine doesn't even recognize a bit insertion. The closest is a combine or 3 insns that resemble the input: Failed to match this instruction: (set (reg:QI 53) (ior:QI (and:QI (reg:QI 43 [ _1 ]) (const_int -17 [0xffffffffffffffef])) (and:QI (reg:QI 51 [ *src_6(D) ]) (const_int 16 [0x10])))) Again, the backend could provide a pattern for this. Dunno why combine fails; maybe because a bit-insertion requires that the output operand maches the input operand that gets ANDed with -17.