llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.31k stars 11.69k forks source link

LLVM 13 regression: lost transformation x < C && y < C && z < C to (x | y | z) < C #51087

Open davidbolvansky opened 3 years ago

davidbolvansky commented 3 years ago
Bugzilla Link 51745
Version trunk
OS Linux
CC @RKSimon,@nikic,@Kojoley,@rotateright

Extended Description

x < C && y < C && z < C to (x | y | z) < C where C is power of two.

bool src1 (unsigned x, unsigned y, unsigned z, unsigned w) { return x < 1024 && y < 1024 && z < 1024 && w < 1024; }

bool tgt1 (unsigned x, unsigned y, unsigned z, unsigned w) { return (x | y | z | w) < 1024; }

GCC: src1(unsigned int, unsigned int, unsigned int, unsigned int): or edx, ecx or edx, esi or edx, edi cmp edx, 1023 setbe al ret tgt1(unsigned int, unsigned int, unsigned int, unsigned int): or edx, ecx or edx, esi or edx, edi cmp edx, 1023 setbe al ret

Clang trunk: src1(unsigned int, unsigned int, unsigned int, unsigned int): # @​src1(unsigned int, unsigned int, unsigned int, unsigned int) cmp edi, 1024 setb al cmp esi, 1024 setb sil and sil, al cmp edx, 1024 setb dl cmp ecx, 1024 setb al and al, dl and al, sil ret tgt1(unsigned int, unsigned int, unsigned int, unsigned int): # @​tgt1(unsigned int, unsigned int, unsigned int, unsigned int) or edi, esi or edx, ecx or edx, edi cmp edx, 1024 setb al ret

Regressed with LLVM 13 which disabled select-to-or optimization.

nikic commented 3 years ago

I don't think this fold should be performed in the middle end at all, as it breaks canonical comparison structure. I'm handling this special pattern in LVI, but many other places reasoning about conditions don't.

We should fold this in DAG instead.

Kojoley commented 3 years ago

Looks very similar to bug 51577

Kojoley commented 4 months ago

LLVM 14 fixed the regression.