Hi Uros, As requested this patch is split out from my previous submission. https://gcc.gnu.org/pipermail/gcc-patches/2024-August/659450.html This patch enables STV when the first operand of a TImode binary logic operand (AND, IOR or XOR) is a memory operand, which is commonly the case with read-modify-write instructions.
A different motivating example from the one given above is: __int128 m, p, q; void foo() { m ^= (p & q); } Currently with -O2 -mavx, RMW instructions are rejected by STV, resulting in scalar code: foo: movq p(%rip), %rax movq p+8(%rip), %rdx andq q(%rip), %rax andq q+8(%rip), %rdx xorq %rax, m(%rip) xorq %rdx, m+8(%rip) ret With this patch they become scalar-to-vector candidates: foo: vmovdqa p(%rip), %xmm0 vpand q(%rip), %xmm0, %xmm0 vpxor m(%rip), %xmm0, %xmm0 vmovdqa %xmm0, m(%rip) ret This patch has been tested on x86_64-pc-linux-gnu with make bootstrap and make -k check, both with and without --target_board=unix{-m32} with no new failures. Ok for mainline? 2024-08-31 Roger Sayle <ro...@nextmovesoftware.com> gcc/ChangeLog * config/i386/i386-features.cc (timode_scalar_to_vector_candidate_p): Support the first operand of AND, IOR and XOR being MEM_P, i.e. a read-modify-write insn. gcc/testsuite/ChangeLog * gcc.target/i386/movti-2.c: Change dg-options to -Os. * gcc.target/i386/movti-4.c: Expected output of original movti-2.c. Thanks in advance, Roger --
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index c09a5c7..3434d00 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -2330,14 +2330,16 @@ timode_scalar_to_vector_candidate_p (rtx_insn *insn) || CONST_SCALAR_INT_P (XEXP (src, 1)) || timode_mem_p (XEXP (src, 1)))) return true; - return REG_P (XEXP (src, 0)) + return (REG_P (XEXP (src, 0)) + || timode_mem_p (XEXP (src, 0))) && (REG_P (XEXP (src, 1)) || CONST_SCALAR_INT_P (XEXP (src, 1)) || timode_mem_p (XEXP (src, 1))); case IOR: case XOR: - return REG_P (XEXP (src, 0)) + return (REG_P (XEXP (src, 0)) + || timode_mem_p (XEXP (src, 0))) && (REG_P (XEXP (src, 1)) || CONST_SCALAR_INT_P (XEXP (src, 1)) || timode_mem_p (XEXP (src, 1))); diff --git a/gcc/testsuite/gcc.target/i386/movti-2.c b/gcc/testsuite/gcc.target/i386/movti-2.c index 73f69d2..c3a6ae3 100644 --- a/gcc/testsuite/gcc.target/i386/movti-2.c +++ b/gcc/testsuite/gcc.target/i386/movti-2.c @@ -1,5 +1,5 @@ /* { dg-do compile { target int128 } } */ -/* { dg-options "-O2 -mavx" } */ +/* { dg-options "-Os -mavx" } */ __int128 m; void foo() diff --git a/gcc/testsuite/gcc.target/i386/movti-4.c b/gcc/testsuite/gcc.target/i386/movti-4.c new file mode 100644 index 0000000..eac66fc --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/movti-4.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2 -mavx" } */ +__int128 m; + +void foo() +{ + m &= ((__int128)0x0123456789abcdefULL<<64) | 0x0123456789abcdefULL; +} + +/* { dg-final { scan-assembler-times "movabsq" 1 } } */ +/* { dg-final { scan-assembler-times "vpand" 1 } } */