llvm / llvm/llvm-project

[clang] `memcmp`-like function with pointer parameters and written as a for loop never transformed into `memcmp`

Open
#167,397 2 comments 0 reactions 0 assignees View on GitHub
llvm:optimizations missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Given the following code

```c++
auto equal(
int const * const lhs,
int const * const rhs
) -> bool {
for (int n = 0; n != 10; ++n) {
if (lhs[n] != rhs[n]) {
return false;
}
}
return true;
}
```

I would expect something like a call to `memcmp` for sufficiently large size. Instead, at `-O3` it follows this pattern for 2 <= size <= 59:

```asm
equal(int const*, int const*):
mov eax, dword ptr [rdi]
cmp eax, dword ptr [rsi]
jne .LBB0_10
mov eax, dword ptr [rdi + 4]
cmp eax, dword ptr [rsi + 4]
jne .LBB0_10
mov eax, dword ptr [rdi + 8]
cmp eax, dword ptr [rsi + 8]
jne .LBB0_10
mov eax, dword ptr [rdi + 12]
cmp eax, dword ptr [rsi + 12]
jne .LBB0_10
mov eax, dword ptr [rdi + 16]
cmp eax, dword ptr [rsi + 16]
jne .LBB0_10
mov eax, dword ptr [rdi + 20]
cmp eax, dword ptr [rsi + 20]
jne .LBB0_10
mov eax, dword ptr [rdi + 24]
cmp eax, dword ptr [rsi + 24]
jne .LBB0_10
mov eax, dword ptr [rdi + 28]
cmp eax, dword ptr [rsi + 28]
jne .LBB0_10
mov eax, dword ptr [rdi + 32]
cmp eax, dword ptr [rsi + 32]
jne .LBB0_10
mov eax, dword ptr [rdi + 36]
cmp eax, dword ptr [rsi + 36]
sete al
ret
.LBB0_10:
xor eax, eax
ret
```

And then for size >= 60 it does (with the constant adjusted appropriately)

```asm
equal(int const*, int const*):
xor eax, eax
.LBB0_1:
mov ecx, dword ptr [rdi + 4*rax]
mov edx, dword ptr [rsi + 4*rax]
cmp ecx, edx
jne .LBB0_3
cmp rax, 59
lea rax, [rax + 1]
jne .LBB0_1
.LBB0_3:
cmp ecx, edx
sete al
ret
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.