让GCC在没有内联汇编的情况下使用进位逻辑实现任意精度算术?

mor*_*rog 8 c optimization gcc compiler-optimization arbitrary-precision

使用任意精度算术(例如512位整数)时,有没有办法让GCC在不使用内联汇编的情况下使用ADC和类似指令?

乍一看GMP的源代码显示,它们只是为每个支持的平台提供了汇编实现.

这是我编写的测试代码,它从命令行添加两个128位数字并打印结果.(受mini-gmp的add_n启发):

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

int main (int argc, char **argv)
{
    uint32_t a[4];
    uint32_t b[4];
    uint32_t c[4];
    uint32_t carry = 0;

    for (int i = 0; i < 4; ++i)
    {
        a[i] = strtoul (argv[i+1], NULL, 16);
        b[i] = strtoul (argv[i+5], NULL, 16);
    }

    for (int i = 0; i < 4; ++i)
    {
        uint32_t aa = a[i];
        uint32_t bb = b[i];
        uint32_t r = aa + carry;
        carry = (r < carry);
        r += bb;
        carry += (r < bb);
        c[i] = r;
    }

    printf ("%08X%08X%08X%08X + %08X%08X%08X%08X =\n", a[3], a[2], a[1], a[0], b[3], b[2], b[1], b[0]);
    printf ("%08X%08X%08X%08X\n", c[3], c[2], c[1], c[0]);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

GCC -O3 -std=c99adc经过检查,不会产生任何指示objdump.我的gcc版本是i686-pc-mingw32-gcc (GCC) 4.5.2.

Jim*_*myB 1

如果GCC发现需要执行以下操作,则它使用进位标志:例如,当在 32 位机器上将 两个值相加时,这必须得到 1 32 位加 1 32 位。但除了那些编译器被迫使用进位的情况之外,可能无法说服编译器在没有汇编器的情况下这样做。因此,使用可用的最大整数类型可能会有益,从而允许 GCC 通过有效地让它知道值的单个“组件”属于在一起来优化操作。
uint64_tADDADC

对于简单的加法,计算进位的另一种方法可能是查看操作数中的相关位,例如:

uint32_t aa,bb,rr;
bool msbA, msbB, msbR, carry;
// ...

rr = aa+bb;

msbA = aa >= (1<<31); // equivalent: (aa & (1<<31)) != 0;
msbB = bb >= (1<<31);
msbR = rr >= (1<<31);


carry = (msbA && msbB) || ( !msbR && ( msbA || msbB) );
Run Code Online (Sandbox Code Playgroud)

  • 另一个廉价的技巧是仅使用 32 位字中的 31 位(更好的是,64 位中的 63 位)。您放弃 3% 或更少的存储容量,但会在总和的 MSB 中为您计算进位位。 (3认同)
  • 也许值得看看 GCC 的整数溢出内置:https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html (2认同)