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.