unnecessary movzx eax, al after shr
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The following code appears to emit a redundant `movzx eax, al`, clearing upper bits which are already zeroed. (because shr will never set any of the extended bits).
```cpp
#include
auto test_code(uint8_t b) -> bool {
const uint64_t TABLE[4] = {287948901175001088, 576460745995190270, 0, 0};
return ((TABLE[(uint64_t)b / 64] >> (b % 64)) & 1) == 1;
}
```
```asm
test_code(unsigned char):
mov eax, edi
shr al, 6
movzx eax, al ;; <-- My complaint is about this instruction here, which shouldn't be emitted.
lea rcx, [rip + .L__const.test_code(unsigned char).TABLE]
mov rax, qword ptr [rcx + 8*rax]
bt rax, rdi
setb al
ret
.L__const.test_code(unsigned char).TABLE:
.quad 287948901175001088
.quad 576460745995190270
.quad 0
.quad 0
```
https://godbolt.org/z/16zGPoKcE
Compare that to this code, which works as I expect:
I've removed the explicit cast, and now llvm doesn't emit the extra instruction:
```cpp
#include
auto test_code(uint8_t b) -> bool {
const uint64_t TABLE[4] = {287948901175001088, 576460745995190270, 0, 0};
return ((TABLE[b / 64] >> (b % 64)) & 1) == 1;
}
```
compiles to
```asm
test_code(unsigned char):
mov eax, edi
shr edi, 6
lea rcx, [rip + .L__const.test_code(unsigned char).TABLE]
mov rcx, qword ptr [rcx + 8*rdi]
bt rcx, rax
setb al
ret
.L__const.test_code(unsigned char).TABLE:
.quad 287948901175001088
.quad 576460745995190270
.quad 0
.quad 0
```
https://godbolt.org/z/97hcxvW4G
However, the movzx instruction can be elided in both versions, not just this second one.
Rust only lets me express the version that produces the broken code: https://godbolt.org/z/hh458xo5E
Contributor guide
Assessment
This issue has not been assessed yet.