首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >128位由64位本地除法

128位由64位本地除法
EN

Stack Overflow用户
提问于 2022-09-09 20:30:25
回答 1查看 99关注 0票数 3

我需要执行128位的64位师在锈。x86-64 ISA包含用于此目的的本机DIV指令。但是,我编译的测试代码不使用此指令。

测试代码:

代码语言:javascript
复制
pub fn div(hi: u64, lo: u64, divisor: u64) -> u64 {
   assert!(hi < divisor);

   let dividend = ((hi as u128) << 64) + lo as u128;
   (dividend / divisor as u128) as u64
}

编译器资源管理器输出:

代码语言:javascript
复制
example::div:
    push    rax
    cmp     rdi, rdx
    jae     .LBB0_1
    mov     rax, rdi
    mov     rdi, rsi
    mov     rsi, rax
    xor     ecx, ecx
    call    qword ptr [rip + __udivti3@GOTPCREL]
    pop     rcx
    ret
.LBB0_1:
    ...

相反,通过__udivti3执行128位除法的低效128位。这可能是因为如果商数不适合64位,则DIV指令会导致CPU异常。然而,就我的情况而言,这是不可能的: hi <除数,lo < 2^64 ->股利= hi * 2^64 + lo <= (除数- 1) * 2^64 + 2^64 -1=除数* 2^64 -1 ->股息/除数<= 2^64 -1/除数< 2^64

如何强制编译器使用本机指令?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-09 23:25:50

您唯一的选择是使用内联程序集。可能有一个模糊的编译器标志组合,可以强迫llvm执行优化本身,但我不认为试图找到它是值得的。对于程序集,它将如下所示:

代码语言:javascript
复制
use std::arch::asm;
pub fn div(hi: u64, lo: u64, divisor: u64) -> u64 {

    assert!(hi < divisor);

    #[cfg(target_arch = "x86_64")]
    unsafe {
        let mut quot = lo;
        let mut _rem = hi;
        asm!(
            "div {divisor}",
            divisor = in(reg) divisor,
            inout("rax") quot,
            inout("rdx") _rem,
            options(pure, nomem, nostack)
        );
        quot
    }
    #[cfg(not(target_arch = "x86_64"))]
    {
        let dividend = ((hi as u128) << 64) + lo as u128;
        (dividend / divisor as u128) as u64
    }
}

哥德波特

在x86_64上,这只是将除法编译成一个小寄存器洗牌,然后是一个div,然后在其他系统上执行对__udivti3的调用。它也不应该妨碍优化器太多,因为它是纯的。

确实值得对您的应用程序进行基准测试,看看这是否真的有帮助。对于llvm来说,对整数除法的推理要比内联程序集容易得多,其他地方的优化也很容易导致这个版本比使用默认版本运行得慢。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73667228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档