Skip to content

Missed optimization when a constant is a power of two #41602

@jameshamm

Description

@jameshamm
mannequin
Bugzilla Link 42257
Resolution FIXED
Resolved on Oct 15, 2019 07:32
Version trunk
OS Linux
CC @davidbolvansky,@LebedevRI,@RKSimon,@rotateright,@ZviRackover
Fixed by commit(s) r374886

Extended Description

The following function is correctly treated as a no-op by clang(trunk, -Ofast --march=skylake)

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

=>

zero(bool):
xor eax, eax
ret

Messing around with this function on compiler explorer (https://godbolt.org/z/grc5ZF), I noticed when the constant is set to a power of two (where the power is not 0 or 1) or the negative of a power of two, the code is no longer optimized away.

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

=>

zero(bool):
shl edi, 2
cmp edi, edi ;; Always sets the ZF
setne al ;; ZF is set, so al is always 0
ret

This missed optimization still happens when the return type is an int, and the missed optimization is not obvious from the assembly (https://godbolt.org/z/ZEwONp).

// Completely optimized
int zero(bool b) {
int x = 18;
return (x * b) + (-x * b);
}

=>

zero(bool):
xor eax, eax
ret

vs

// Missing opportunity
int zero(bool b) {
int x = 4;
return (x * b) + (-x * b);
}

=>

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

The problem disappears if the function parameter is widened,

int zero(int b) {
int x = 4;
return (x * b) + (-x * b);
}

or if the intermediate values are close to overflowing (https://godbolt.org/z/yHPjz2),

int zero(bool b) {
int x = 1 << 31;
return (x * b) + (-x * b);
}

or (as a comment on stackoverflow pointed out https://stackoverflow.com/questions/56416747/missed-optimization-in-clang-only-on-powers-of-two#comment99429730_56416747) if the value is not known.

int zero(bool b, int x) {
return (x * b) + (-x * b);
}

All compile down to

zero(int):
xor eax, eax
ret

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzilla

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions