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.

Reply via email to