Issue 164501
Summary `(x == 0 || y == 0)` can fold to `(x * y == 0)` for small integers in `-Oz` mode
Labels new issue
Assignees
Reporter Explorer09
    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 <stdbool.h>
#include <stdint.h>

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
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to