'Missed optimization in clang only on powers of two

When compiling with -Ofast, clang correctly deduces that the following function will always return 0.

int zero(bool b) {
    const int x = 5;
    return (x * b) + (-x * b);
}

compiles to

zero(bool):                               # @zero(bool)
        xor     eax, eax
        ret

However, if I change the constant to be any power of two (except 1 or 0), clang no longer makes the same deduction

int zero(bool b) {
    const int x = 8;
    return (x * b) + (-x * b);
}

compiles to

zero(bool):                               # @zero(bool)
        mov     eax, edi
        shl     eax, 3
        xor     dil, 1
        movzx   ecx, dil
        lea     eax, [rax + 8*rcx]
        add     eax, -8
        ret

The code compiled with compiler explorer.

If I change the function parameter to be anything bigger (short, int, long) the optimization is correctly made.

What causes this weird edge case?



Solution 1:[1]

It is an optimization problem in Clang, which was fixed after version 10.0.0. We can reproduce this problem in version 9.0.1.

Compared versions 9.0.1 and 10.0.0 in compiler explorer.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nejc Galof