如何让Rust编译时使用x86-64原生128bit by 64bit DIV指令?
如何让Rust编译器在128位除以64位的场景中使用x86-64原生DIV指令?
你需要在Rust中执行由两个u64(hi和lo)拼接成的128位数值除以64位除数的操作,x86-64指令集的DIV指令原生支持该操作,但当前代码却调用了低效的__udivti3(128位除以128位)函数。你已经通过数学推导证明:在hi < divisor的约束下,商必然能放入64位,不会触发DIV指令的溢出异常。以下是两种可行的解决方案:
方法1:使用内联汇编直接调用DIV指令
通过内联汇编手动实现操作,完全控制指令生成,彻底绕开编译器的保守优化逻辑:
pub fn div(hi: u64, lo: u64, divisor: u64) -> u64 { assert!(hi < divisor); let mut quotient: u64; unsafe { // x86-64 DIV指令规则:rdx:rax作为被除数,除以rdx中的除数,商存入rax,余数存入rdx asm!( "div rdx", inout("rax") lo => quotient, inout("rdx") hi => _, in("rdx") divisor, options(nostack, preserves_flags) ); } quotient }
该代码直接生成div rdx指令,完全利用硬件原生支持,性能最优。
方法2:给编译器提供明确约束,引导生成DIV指令
通过不稳定特性和强制内联,给编译器传递更明确的优化信号,促使它生成原生指令(依赖Rust版本和编译优化等级):
#![feature(core_intrinsics)] use core::intrinsics::unchecked_div; #[inline(always)] pub fn div(hi: u64, lo: u64, divisor: u64) -> u64 { assert!(hi < divisor); let dividend = ((hi as u128) << 64) | (lo as u128); // 用unchecked_div告知编译器无需处理溢出情况 unsafe { unchecked_div(dividend, divisor as u128) as u64 } }
注意:需要启用core_intrinsics不稳定特性,且必须用--release模式编译以开启优化。
验证结果
编译时执行rustc --release --emit asm your_code.rs查看生成的汇编代码,两种方法都能生成原生DIV指令,而非调用__udivti3函数。
内容的提问来源于stack exchange,提问作者ubw
相关产品推荐
相关产品推荐

