https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94878

            Bug ID: 94878
           Summary: Failure to optimize div with bls/or pattern
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gabravier at gmail dot com
  Target Milestone: ---

unsigned y(unsigned x)
{
    unsigned s = x & -x;
    return s | (x % s);
}

With -O3, LLVM outputs : 

y(unsigned int):
  blsi ecx, edi
  lea eax, [rcx - 1]
  and eax, edi
  or eax, ecx
  ret

GCC outputs :

y(unsigned int):
  mov eax, edi
  xor edx, edx
  blsi ecx, edi
  div ecx
  mov eax, edx
  or eax, ecx
  ret

If a single change to this function is applied, changing it to this :

unsigned y(unsigned x)
{
    unsigned s = x & -x;
    return x | (x % s);
}

It's equivalent to `return x`, and LLVM recognises this : 

y(unsigned int):
  mov eax, edi
  ret

While GCC does not :

y(unsigned int):
  mov eax, edi
  xor edx, edx
  blsi ecx, edi
  div ecx
  mov eax, edx
  or eax, edi
  ret

Reply via email to