https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84759
Bug ID: 84759 Summary: Calculation of quotient and remainder with constant denominator uses __umoddi3+__udivdi3 instead of __udivmoddi4 Product: gcc Version: 7.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: b7.10110111 at gmail dot com Target Milestone: --- Starting from GCC 7, code calculating both quotient and remainder of a loong division calls a single __udivmodti4. But this only happens for general values of denominator, while for specific constants for some reason GCC still generates calls to __umodti3 and __udivti3. See the following code (the picture is the same for x86 and amd64 targets): #ifdef __SIZEOF_INT128__ typedef __uint128_t Longer; #else typedef unsigned long long Longer; #endif typedef unsigned long Shorter; Shorter divmod(Longer numerator, Shorter denominator, Shorter* remainder) { *remainder = numerator%denominator; return numerator/denominator; } Shorter divmodConst(Longer numerator, Shorter* remainder) { const Shorter denominator = 100; *remainder = numerator%denominator; return numerator/denominator; } Here divmod is optimized, while divmodConst appears not optimized: divmod: sub esp, 28 xor edx, edx mov eax, DWORD PTR [esp+40] lea ecx, [esp+8] sub esp, 12 push ecx push edx push eax push DWORD PTR [esp+60] push DWORD PTR [esp+60] call __udivmoddi4 mov edx, DWORD PTR [esp+76] mov ecx, DWORD PTR [esp+40] mov DWORD PTR [edx], ecx add esp, 60 ret divmodConst: push edi push esi sub esp, 4 mov esi, DWORD PTR [esp+16] mov edi, DWORD PTR [esp+20] push 0 push 100 push edi push esi call __umoddi3 add esp, 16 mov edx, DWORD PTR [esp+24] mov DWORD PTR [edx], eax push 0 push 100 push edi push esi call __udivdi3 add esp, 20 pop esi pop edi ret