llvm / llvm/llvm-project

Suboptimal code for comparisons between variables extended to 128 bits

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

Description

https://godbolt.org/z/4WEbeWP6n
https://alive2.llvm.org/ce/z/4Stvke

```rust
#[unsafe(no_mangle)]
pub fn src1(x: i32, y: u64) -> bool {
i128::from(x) < i128::from(y)
}

#[unsafe(no_mangle)]
pub fn tgt1(x: i32, y: u64) -> bool {
(y.cast_signed() < 0) || i64::from(x) < y.cast_signed()
}

#[unsafe(no_mangle)]
pub fn src2(x: i16, y: u32) -> bool {
i128::from(x) < i128::from(y)
}

#[unsafe(no_mangle)]
pub fn tgt2(x: i16, y: u32) -> bool {
i64::from(x) < i64::from(y)
}

#[unsafe(no_mangle)]
pub fn src3(x: i8, y: u16) -> bool {
i128::from(x) < i128::from(y)
}

#[unsafe(no_mangle)]
pub fn tgt3(x: i8, y: u16) -> bool {
i32::from(x) < i32::from(y)
}

#[unsafe(no_mangle)]
pub fn src4(x: i8, y: u8) -> bool {
i128::from(x) < i128::from(y)
}

#[unsafe(no_mangle)]
pub fn tgt4(x: i8, y: u8) -> bool {
i32::from(x) < i32::from(y)
}
```

# Assembly (AArch64)
```asm
src1:
sxtw x8, w0
asr x9, x8, #63
cmp x8, x1
sbcs xzr, x9, xzr
cset w0, lt
ret

src2:
sxth x8, w0
asr x9, x8, #63
cmp x8, w1, uxtw
sbcs xzr, x9, xzr
cset w0, lt
ret

src3:
sxtb x8, w0
asr x9, x8, #63
cmp x8, w1, uxth
sbcs xzr, x9, xzr
cset w0, lt
ret

src4:
sxtb x8, w0
asr x9, x8, #63
cmp x8, w1, uxtb
sbcs xzr, x9, xzr
cset w0, lt
ret

tgt1:
sxtw x8, w0
cmp x1, #0
ccmp x1, x8, #0, pl
cset w0, gt
ret

tgt2:
mov w8, w1
cmp x8, w0, sxth
cset w0, gt
ret

tgt3:
sxtb w8, w0
cmp w8, w1, uxth
cset w0, lt
ret

tgt4:
sxtb w8, w0
cmp w8, w1, uxtb
cset w0, lt
ret
```

# Assembly (x86_64)
```asm
src1:
movsxd rax, edi
mov rcx, rax
sar rcx, 63
cmp rax, rsi
sbb rcx, 0
setl al
ret

src2:
movsx rax, di
mov rcx, rax
sar rcx, 63
mov edx, esi
cmp rax, rdx
sbb rcx, 0
setl al
ret

src3:
movsx rax, dil
mov rcx, rax
sar rcx, 63
movzx edx, si
cmp rax, rdx
sbb rcx, 0
setl al
ret

src4:
movsx rax, dil
mov rcx, rax
sar rcx, 63
movzx edx, sil
cmp rax, rdx
sbb rcx, 0
setl al
ret

tgt1:
test rsi, rsi
sets cl
movsxd rax, edi
cmp rsi, rax
setg al
or al, cl
ret

tgt2:
movsx rax, di
mov ecx, esi
cmp rax, rcx
setl al
ret

tgt3:
movsx eax, dil
movzx ecx, si
cmp eax, ecx
setl al
ret

tgt4:
movsx eax, dil
movzx ecx, sil
cmp eax, ecx
setl al
ret
```

Contributor guide

Open the contributing guide

Research direction

Start with the Rust functions in the issue and reproduce the AArch64 and x86_64 output using the linked Godbolt example; use the linked Alive2 proof to confirm the proposed comparisons are equivalent. Trace which LLVM optimization stage handles these widened integer comparisons and compare generated assembly before and after. Done means the valid cases avoid unnecessary 128-bit comparison sequences on the affected targets.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.