llvm / llvm/llvm-project

[X86] i128 and/or/xor (memory from) should use simd

Open
#221,551 2 comments 0 reactions 0 assignees View on GitHub
backend:X86 missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

found from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127020
```c
extern __int128 a, b, c, z;

__int128 foo_inout(__int128 x)
{
return (x ^ a ^ b ^ c ^ z);
}

__int128 bar_inout(__int128 x)
{
return (x & a & b & c & z);
}

__int128 baz_inout(__int128 x)
{
return (x | a | b | c | z);
}
```
gcc:
```asm
"foo_inout":
vmovdqa xmm0, XMMWORD PTR "a"[rip]
vmovq xmm2, rdi
vpinsrq xmm1, xmm2, rsi, 1
vpxord xmm0, xmm0, XMMWORD PTR "b"[rip]
vpxord xmm0, xmm0, XMMWORD PTR "c"[rip]
vpxord xmm0, xmm0, XMMWORD PTR "z"[rip]
vpxord xmm0, xmm0, xmm1
vpextrq rdx, xmm0, 1
vmovq rax, xmm0
ret
"bar_inout":
vmovdqa xmm0, XMMWORD PTR "a"[rip]
vmovq xmm2, rdi
vpinsrq xmm1, xmm2, rsi, 1
vpandd xmm0, xmm0, XMMWORD PTR "b"[rip]
vpandd xmm0, xmm0, XMMWORD PTR "c"[rip]
vpandd xmm0, xmm0, XMMWORD PTR "z"[rip]
vpandd xmm0, xmm0, xmm1
vpextrq rdx, xmm0, 1
vmovq rax, xmm0
ret
"baz_inout":
vmovdqa xmm0, XMMWORD PTR "a"[rip]
vmovq xmm2, rdi
vpinsrq xmm1, xmm2, rsi, 1
vpord xmm0, xmm0, XMMWORD PTR "b"[rip]
vpord xmm0, xmm0, XMMWORD PTR "c"[rip]
vpord xmm0, xmm0, XMMWORD PTR "z"[rip]
vpord xmm0, xmm0, xmm1
vpextrq rdx, xmm0, 1
vmovq rax, xmm0
ret
```
clang:
```asm
foo_inout:
mov rax, qword ptr [rip + a@GOTPCREL]
xor rsi, qword ptr [rax + 8]
xor rdi, qword ptr [rax]
mov rax, qword ptr [rip + b@GOTPCREL]
mov rcx, qword ptr [rip + c@GOTPCREL]
mov r8, qword ptr [rcx]
mov rdx, qword ptr [rcx + 8]
xor rdx, qword ptr [rax + 8]
xor rdx, rsi
xor r8, qword ptr [rax]
{nf} xor rax, rdi, r8
mov rcx, qword ptr [rip + z@GOTPCREL]
xor rax, qword ptr [rcx]
xor rdx, qword ptr [rcx + 8]
ret

bar_inout:
mov rax, qword ptr [rip + a@GOTPCREL]
and rsi, qword ptr [rax + 8]
and rdi, qword ptr [rax]
mov rax, qword ptr [rip + b@GOTPCREL]
mov rcx, qword ptr [rip + c@GOTPCREL]
mov r8, qword ptr [rcx]
mov rdx, qword ptr [rcx + 8]
and rdx, qword ptr [rax + 8]
and rdx, rsi
and r8, qword ptr [rax]
{nf} and rax, rdi, r8
mov rcx, qword ptr [rip + z@GOTPCREL]
and rax, qword ptr [rcx]
and rdx, qword ptr [rcx + 8]
ret

baz_inout:
mov rax, qword ptr [rip + a@GOTPCREL]
or rsi, qword ptr [rax + 8]
or rdi, qword ptr [rax]
mov rax, qword ptr [rip + b@GOTPCREL]
mov rcx, qword ptr [rip + c@GOTPCREL]
mov r8, qword ptr [rcx]
mov rdx, qword ptr [rcx + 8]
or rdx, qword ptr [rax + 8]
or rdx, rsi
or r8, qword ptr [rax]
{nf} or rax, rdi, r8
mov rcx, qword ptr [rip + z@GOTPCREL]
or rax, qword ptr [rcx]
or rdx, qword ptr [rcx + 8]
ret
```
https://godbolt.org/z/335snzffE

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the three __int128 functions in the linked Godbolt example and inspect the generated x86 assembly. Compare LLVM's output with the GCC SIMD output for memory operands, then identify the relevant x86 code-generation entry point and add or update a regression test. Done means the operations use suitable SIMD instructions without changing the results.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.