SIGN IN SIGN UP

Rollup merge of #160819 - TDecking:div_ceil, r=clarfonthey

Rework `div_ceil` for nonzero integers

This changes the definition of `NonZero::div_ceil` for improved performance by employing a different algorithm.
The generated assembly is better in nearly every case, with the exception of the division by a constant 2, which gains one instruction.

<details>

<summary>Assembly</summary>

```asm
div_ceil_16_new:
        lea     rax, [rdi - 1]
        shr     rax, 4
        inc     rax
        ret

div_ceil_16_old:
        mov     rax, rdi
        shr     rax, 4
        and     edi, 15
        cmp     rdi, 1
        sbb     rax, -1
        ret

div_ceil_21_new:
        lea     rcx, [rdi - 1]
        movabs  rdx, -8784163844623596007
        mov     rax, rcx
        mul     rdx
        sub     rcx, rdx
        shr     rcx
        add     rcx, rdx
        shr     rcx, 4
        inc     rcx
        mov     rax, rcx
        ret

div_ceil_21_old:
        movabs  rcx, -8784163844623596007
        mov     rax, rdi
        mul     rcx
        movabs  rcx, -3513665537849438403
        imul    rcx, rdi
        sub     rdi, rdx
        shr     rdi
        add     rdi, rdx
        shr     rdi, 4
        movabs  rdx, 878416384462359600
        xor     eax, eax
        cmp     rcx, rdx
        seta    al
        add     rax, rdi
        ret

div_ceil_2_new:
        lea     rax, [rdi - 1]
        shr     rax
        inc     rax
        ret

div_ceil_2_old:
        mov     rax, rdi
        mov     rcx, rdi
        shr     rcx
        sub     rax, rcx
        ret

div_ceil_3_new:
        lea     rax, [rdi - 1]
        movabs  rcx, -6148914691236517205
        mul     rcx
        shr     rdx
        lea     rax, [rdx + 1]
        ret

div_ceil_3_old:
        mov     rax, rdi
        movabs  rcx, -6148914691236517205
        mul     rcx
        shr     rdx
        movabs  rsi, 6148914691236517205
        xor     ecx, ecx
        cmp     rax, rsi
        seta    cl
        add     rcx, rdx
        mov     rax, rcx
        ret

div_ceil_generic_new:
        mov     rax, rdi
        dec     rax
        mov     rcx, rax
        or      rcx, rsi
        shr     rcx, 32
        je      .LBB8_1
        xor     edx, edx
        div     rsi
        inc     rax
        ret
.LBB8_1:
        xor     edx, edx
        div     esi
        inc     rax
        ret

div_ceil_generic_old:
        mov     rax, rdi
        mov     rcx, rdi
        or      rcx, rsi
        shr     rcx, 32
        je      .LBB9_1
        xor     edx, edx
        div     rsi
        cmp     rdx, 1
        sbb     rax, -1
        ret
.LBB9_1:
        xor     edx, edx
        div     esi
        cmp     rdx, 1
        sbb     rax, -1
        ret
```

</details>

It is theoretically possible to adapt this algorithm for normal unsigned integers and possibly even signed normal integers,
but the results were questionable at best, which is why the change was restricted to unsigned nonzero integers.
J
Jonathan Brouwer committed
165b70daf47392ca6a12071926e818913a71f025
Committed by GitHub <noreply@github.com> on 8/25/2026, 5:05:35 AM