相关疑难解决方法(0)

使用clang的携带代码生成良好的添加

我正在尝试生成代码(目前使用clang ++ - 3.8),它添加了两个由多个机器字组成的数字.为了简化目前我只添加128位数字,但我希望能够概括这一点.

首先是一些typedef:

typedef unsigned long long unsigned_word;
typedef __uint128_t unsigned_128;
Run Code Online (Sandbox Code Playgroud)

而"结果"类型:

struct Result
{
  unsigned_word lo;
  unsigned_word hi;
};
Run Code Online (Sandbox Code Playgroud)

第一个函数f采用两对无符号字并返回结果,作为一个中间步骤,在添加它们之前将这两个64位字放入一个128位字中,如下所示:

Result f (unsigned_word lo1, unsigned_word hi1, unsigned_word lo2, unsigned_word hi2)
{
  Result x;
  unsigned_128 n1 = lo1 + (static_cast<unsigned_128>(hi1) << 64);
  unsigned_128 n2 = lo2 + (static_cast<unsigned_128>(hi2) << 64);
  unsigned_128 r1 = n1 + n2;
  x.lo = r1 & ((static_cast<unsigned_128>(1) << 64) - 1);
  x.hi = r1 >> 64;
  return x;
}
Run Code Online (Sandbox Code Playgroud)

这实际上非常好地内联:

movq    8(%rsp), …
Run Code Online (Sandbox Code Playgroud)

c++ optimization assembly clang adx

26
推荐指数
1
解决办法
1206
查看次数

长整数例程可以从SSE中受益吗?

我还在研究C++中任意长整数的例程.到目前为止,我已经为64位Intel CPU实现了加/减和乘法.

一切正常,但我想知道我是否可以通过使用SSE来加快速度.我浏览了SSE文档和处理器指令列表,但我找不到任何我认为可以使用的内容,原因如下:

  • SSE有一些整数指令,但大多数指令处理浮点.看起来它不是设计用于整数(例如,是否有较小的整数比较?)

  • SSE的想法是SIMD(相同的指令,多个数据),因此它提供了2或4个独立操作的指令.另一方面,我希望有一个像128位整数加(128位输入和输出)的东西.这似乎不存在.(但是?在AVX2中可能?)

  • 整数加法和减法既不处理输入也不处理输出.因此,手动操作非常麻烦(因而也很慢).

我的问题是:我的评估是正确的还是有什么我忽略的?长整数例程可以从SSE中受益吗?特别是,它们可以帮助我编写更快的添加,子或mul例程吗?

performance integer sse bignum arbitrary-precision

19
推荐指数
1
解决办法
3773
查看次数

使用进位标志添加多字

GCC具有128位整数.使用这些我可以让编译器使用mul(或imul只有一个操作数)指令.例如

uint64_t x,y;
unsigned __int128 z = (unsigned __int128)x*y;
Run Code Online (Sandbox Code Playgroud)

生产mul.我用它来创建一个128x128到256的函数(在更新之前,请参阅此问题的结尾,如果您感兴趣,请参阅此代码).

现在我想要进行256位加法,ADC除了使用汇编之外,我还没有找到让编译器使用的方法.我可以使用汇编程序,但我想要内联函数以提高效率.编译器已经生成了一个有效的128x128到256函数(因为我在这个问题的开头解释了)所以我不明白为什么我应该在汇编中重写它(或者编译器已经有效实现的任何其他函数) .

这是我提出的内联汇编函数:

#define ADD256(X1, X2, X3, X4, Y1, Y2, Y3, Y4) \
 __asm__ __volatile__ ( \
 "addq %[v1], %[u1] \n" \
 "adcq %[v2], %[u2] \n" \
 "adcq %[v3], %[u3] \n" \
 "adcq %[v4], %[u4] \n" \
 : [u1] "+&r" (X1), [u2] "+&r" (X2), [u3] "+&r" (X3), [u4] "+&r" (X4) \
 : [v1]  "r" (Y1), [v2]  "r" (Y2), [v3]  "r" (Y3), [v4] …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly gcc visual-c++

13
推荐指数
1
解决办法
2124
查看次数

_addcarry_u64和_addcarryx_u64与MSVC和ICC

MSVC和ICC都支持内在函数_addcarry_u64_addcarryx_u64.

根据英特尔的内在指南白皮书,这些应分别映射到adcxadox.但是,通过查看生成的程序集,很明显它们分别映射到adc并且adcx没有映射到的内在函数adox.

另外,告诉编译器/arch:AVX2MSVC中启用AVX2 或-march=core-avx2在Linux上启用ICC没有任何区别. 我不确定如何使用MSVC和ICC启用ADX.

MSVC文档列出_addcarryx_u64了ADX技术,_addcarry_u64但没有列出的技术.但是,MSVC针对这些内在函数的文档中的链接直接指向Intel Intrinsic指南,该指南与MSVC自己的文档和生成的程序集相矛盾.

由此我得出结论,英特尔的内在指南和白皮书是错误的.

这对于MSVC感觉有一定意义,它不允许内联汇编它应该提供一种使用adc它的方式_addcarry_u64.

其中的一大优点adcx,并adox为他们在不同的标志(进操作CF和溢出OF),这使得两个独立平行进位链.但是,由于没有内在的adox可能性如何?对于ICC,至少有一个可以使用内联汇编,但在64位模式下使用MSVC是不可能的.


微软和英特尔的文档(白皮书和在线内在指南)都同意了.

_addcarry_u64征的文件说只生产adc.该_addcarryx_u64征可以产生两种adcxadox.然而,在MSVC 2013和2015中,_addcarryx_u64只生产adcx.ICC同时生产.

assembly icc intrinsics visual-c++ adx

7
推荐指数
2
解决办法
1332
查看次数

_umul128 在 Windows 32 位上

在 Visual C++ 中,_umul128 在面向 Windows 32 位时未定义。面向 Win32 时如何将两个无符号 64 位整数相乘?该解决方案只需要在面向 Windows 32 位的 Visual C++ 2017 上运行。

x86 biginteger intrinsics visual-c++

5
推荐指数
1
解决办法
1173
查看次数

如何在c ++的x64架构中使用SSE指令?

目前我正在使用Visual C++内联汇编来使用SSE嵌入一些核心功能; 但是我认为在x64模式下不支持内联汇编.

在x64架构中构建软件时如何使用SSE?

sse simd

3
推荐指数
1
解决办法
2481
查看次数