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