`(x == 0 || y == 0)` can fold to `(x * y == 0)` for small integers in `-Oz` mode
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
This is an optimization feature request. (And a follow-up of #160612)
If the integers `a` and `b` are so small that `(a * b)` (the multiplication) cannot overflow, then `(a == 0 || b == 0)` can convert to `(a * b == 0)` for smaller code size.
Because it's significantly slower to use multiplication in place of logical checks, I expect this optimization be performed only in `-Oz` mode.
Note that Clang is already able to transform `(a * b == 0)` into `(a == 0 || b == 0)` if the result never overflows. This request is about the doing the opposite transformation for an aggressive code size reduction.
Architectures that I know can benefit from this optimization include: x86-64 and RISCV64.
```c
#include
#include
bool func1(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
return a == 0 || b == 0 || c == 0 || d == 0;
}
bool func2(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
if (a == 0)
return true;
if (b == 0)
return true;
if (c == 0)
return true;
return d == 0;
}
bool func3(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
return ((uint32_t)a * b * c * d) == 0;
}
```
[Compiler Explorer link](https://godbolt.org/z/43Y37cqGc)
```assembly
func2:
testl %edi, %edi
sete %al
testl %esi, %esi
sete %sil
orb %al, %sil
testl %edx, %edx
sete %dl
testl %ecx, %ecx
sete %al
orb %dl, %al
orb %sil, %al
retq
func3:
imull %esi, %edi
imull %ecx, %edx
imull %edi, %edx
testl %edx, %edx
sete %al
retq
```
EDIT: [I've reported the same feature request in GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122385)
Contributor guide
Assessment
This issue has not been assessed yet.