https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102224
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> --- The problem is actually about not catering to op0 == op1. In that case what we really want is x & 0x80000000 rather than x ^ (x & 0x80000000). Unfortunately after RA the mask needs to be already emitted, I think e.g. because of PIC etc. we can't easily use a different constant at that point, and for non-AVX pandn insn the negation is on the "0" constrained operand. So --- gcc/config/i386/i386-expand.c.jj 2021-09-06 14:47:43.184050185 +0200 +++ gcc/config/i386/i386-expand.c 2021-09-07 11:35:30.798849245 +0200 @@ -2289,12 +2289,20 @@ ix86_split_xorsign (rtx operands[]) mode = GET_MODE (dest); vmode = GET_MODE (mask); - op1 = lowpart_subreg (vmode, op1, mode); - x = gen_rtx_AND (vmode, op1, mask); - emit_insn (gen_rtx_SET (op1, x)); + if (rtx_equal_p (op0, op1)) + { + op0 = lowpart_subreg (vmode, op0, mode); + x = gen_rtx_AND (vmode, op0, gen_rtx_NOT (vmode, mask)); + } + else + { + op1 = lowpart_subreg (vmode, op1, mode); + x = gen_rtx_AND (vmode, op1, mask); + emit_insn (gen_rtx_SET (op1, x)); - op0 = lowpart_subreg (vmode, op0, mode); - x = gen_rtx_XOR (vmode, op1, op0); + op0 = lowpart_subreg (vmode, op0, mode); + x = gen_rtx_XOR (vmode, op1, op0); + } dest = lowpart_subreg (vmode, dest, mode); emit_insn (gen_rtx_SET (dest, x)); doesn't work without -mavx.