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

            Bug ID: 115287
           Summary: Missed optimzation: fold `div(v, a) * b + rem(v, a)`
                    to `div(v, a) * (b - a) + v`
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: xxs_chy at outlook dot com
  Target Milestone: ---

Godbolt example: https://godbolt.org/z/b5va37Tzx

For example:

unsigned char _bin2bcd(unsigned val)
{
        return ((val / 10) << 4) + val % 10;
}

can be folded to:

unsigned char new_bin2bcd(unsigned val)
{
        return val / 10 * 6 + val;
}

With O3 on x86 generates:

_bin2bcd:
        mov     edx, edi
        mov     eax, 3435973837
        imul    rdx, rax
        shr     rdx, 35
        mov     eax, edx
        lea     edx, [rdx+rdx*4]
        add     edx, edx
        sal     eax, 4
        sub     edi, edx
        add     eax, edi
        ret
new_bin2bcd:
        mov     eax, edi
        mov     edx, 3435973837
        imul    rax, rdx
        shr     rax, 35
        lea     eax, [rax+rax*2]
        lea     eax, [rdi+rax*2]
        ret

For this case, "new_bin2bcd" is cheaper.

This C snippet is extracted from
https://github.com/torvalds/linux/blob/master/lib/bcd.c

Reply via email to