Help for a little llvm_asm function

I have this little function with llvm_asm, are you able and willing to translate its asm part to the new asm syntax?

#![feature(llvm_asm)]

#[allow(unused_mut, unused_assignments, unused_variables)]
fn mul_modulus(a: u64, b: u64, m: u64) -> u64 {
    assert_ne!(m, 0);
    let mut r: u64;
    let mut q: u64;

    unsafe {
        llvm_asm!("mulq $3; divq $4;"
                  : "=&{ax}"(q), "=&{dx}"(r)
                  : "{ax}"(a), "r"(b), "r"(m)
                  );
    }
    r
}

fn main() {
    let a = 17628679390175273563;
    let b = 16437465186518824769;
    let m = 17393055579609446543;
    println!("{}", (u128::from(a) * u128::from(b)) % u128::from(m));
    println!("{}", mul_modulus(a, b, m) == 14970600445638585462);
}

(I suggested to add a similar function to the std lib, but it doesn't work in all cases, so it was refused because std lib should contain functions that work on as many input values as possible).

Try this:

#![feature(asm)]

#[allow(unused_assignments, unused_variables)]
#[inline(never)]
fn mul_modulus(a: u64, b: u64, m: u64) -> u64 {
    assert_ne!(m, 0);
    let mut r: u64;
    let mut q: u64;

    unsafe {
        asm!(
            "mul {b}; div {m};",
            b = in(reg) b, m = in(reg) m,
            inout("rax") a => q, out("rdx") r,
        );
    }
    r
}

fn main() {
    let a = 17628679390175273563;
    let b = 16437465186518824769;
    let m = 17393055579609446543;
    println!("{}", (u128::from(a) * u128::from(b)) % u128::from(m));
    println!("{}", mul_modulus(a, b, m) == 14970600445638585462);
}
1 Like

Thank you, it works well and with the same efficiency. The asm of the two functions (stripping out the assert) is almost the same:

mul_modulus1:
    movq    %rdx, %rcx
    movq    %rdi, %rax
    mulq    %rsi
    divq    %rcx
    movq    %rdx, %rax
    retq

mul_modulus2:
    pushq   %rax
    movq    %rdx, %rcx
    movq    %rdi, %rax
    mulq    %rsi
    divq    %rcx
    movq    %rdx, %rax
    popq    %rcx
    retq

If you add options(nostack, nomem) it should be identical.

1 Like