llvm / llvm/llvm-project

`(x == 0 || y == 0)` can fold to `(x * y == 0)` for small integers in `-Oz` mode

Open
#164,501 5 comments 0 reactions 1 assignee Claimed by @vidsinghal View on GitHub
llvm:instcombine missed-optimization
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

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.