You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中高效对模拟__int128_t的数组执行二进制补码取反?

AMD64架构下用std::array<uint64_t,2>模拟__int128_t的高效补码取反实现

需求:使用std::array<uint64_t, 2> A模拟__int128_t类型(其中B = A[0] + 2^64 * A[1],A[0]为低64位,A[1]为高64位),需要实现高效的二进制补码取反操作。

已尝试方案

  • 模拟__int128_t取反的汇编指令:
    观察到原生__int128_t取反对应的汇编指令序列为:

    negq    %r12
    adcq    $0, %r13
    negq    %r13
    

    尝试用内联汇编复现该逻辑:

    asm (
        "negq %[low];"
        "adcq $0, %[high];"
        "negq %[high];"
        : [high] "+r"(A[1]), [low] "+r"(A[0])
    );
    

    问题:代码周围产生大量冗余mov指令,降低执行效率。

  • 使用_subborrow_u64函数实现:
    利用补码取反等价于0 - x的特性,通过_subborrow_u64处理进位:

    unsigned char carry = 0;
    carry = _subborrow_u64(carry, 0, A[0], &(A[0]));
    carry = _subborrow_u64(carry, 0, A[1], &(A[1]));
    

    问题:生成的汇编代码包含冗余操作,执行效率偏低。

高效实现方案

方案1:纯C++实现(依赖编译器优化)

基于补码取反的数学定义~x = -x - 1,结合128位值的拆分特性,写出如下代码。现代编译器(GCC/Clang/MSVC)开启-O2或更高优化级别时,会自动生成与原生__int128_t取反完全一致的最优汇编:

void negate(std::array<uint64_t, 2>& A) {
    uint64_t low = ~A[0] + 1;
    uint64_t high = ~A[1];
    if (low == 0) {
        high += 1;
    }
    A[0] = low;
    A[1] = high;
}

或者更简洁的进位处理写法:

void negate(std::array<uint64_t, 2>& A) {
    uint64_t carry = 1;
    A[0] = ~A[0] + carry;
    carry = (A[0] == 0) ? 1 : 0;
    A[1] = ~A[1] + carry;
}

方案2:优化内联汇编

原内联汇编的冗余mov问题源于寄存器约束的灵活性不足,改进后的内联汇编添加标志寄存器约束,让编译器更好地处理上下文:

void negate(std::array<uint64_t, 2>& A) {
    asm volatile (
        "negq %0;"
        "adcq $0, %1;"
        "negq %1;"
        : "+r"(A[0]), "+r"(A[1])
        :
        : "cc" // 告知编译器条件标志寄存器被修改
    );
}

不过更推荐依赖编译器自动优化,手动寄存器约束可能限制全局优化空间。

方案3:直接使用__int128_t(编译器支持时)

如果目标编译器支持__int128_t(如GCC/Clang),直接转换后取反再拆分是最简洁高效的方式,编译器会自动生成最优汇编:

void negate(std::array<uint64_t, 2>& A) {
    __int128_t val = static_cast<__int128_t>(A[1]) << 64 | A[0];
    val = ~val;
    A[0] = static_cast<uint64_t>(val);
    A[1] = static_cast<uint64_t>(val >> 64);
}

内容的提问来源于stack exchange,提问作者ohad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 01:40:32