【发布时间】:2021-08-12 18:25:04
【问题描述】:
在 MSVC 中存在内部函数 __emulu() 和 _umul128()。第一个是u32*u32->u64 乘法,第二个是u64*u64->u128 乘法。
CLang/GCC 是否存在相同的内在函数?
我找到的最接近的是Intel's Guide 中提到的_mulx_u32() 和_mulx_u64()。但是他们产生需要 BMI2 支持的mulx 指令。而 MSVC 的内在函数产生常规的 mul 指令。还有_mulx_u32()在-m64模式下不可用,而__emulu()和_umul128()在MSVC的32位和64位模式下都存在。
您可以在线尝试32-bit code 和64-bit code。
对于 32 位用户,可能会使用 return uint64_t(a) * uint64_t(b);(参见 online),希望编译器能够正确猜测并优化为使用 u32*u32->u64 乘法而不是 u64*u64->u64。但是有没有办法确定这一点?不要依赖编译器猜测两个参数都是 32 位的(即 uint64_t 的较高部分为零)?拥有一些像 __emulu() 这样的内在函数来确保你对代码的了解。
在 GCC/CLang 中有 __int128(参见代码 online),但我们不得不再次依赖编译器的猜测,即我们实际上乘以 64 位数字(即 int128 的较高部分为零)。如果存在一些内在函数,有没有办法在没有编译器猜测的情况下确定?
顺便说一句,uint64_t(32 位)和__int128(64 位)在 GCC/CLang 中生成正确的 mul 指令而不是 mulx。但我们再次必须依赖编译器正确猜测uint64_t 和__int128 的较高部分为零。
当然,我可以查看 GCC/Clang 已优化并正确猜测的汇编程序代码,但查看一次汇编程序并不能保证在所有情况下都会发生相同的情况。而且我不知道在 C++ 中静态断言编译器对汇编指令的猜测正确的方法。
【问题讨论】:
-
github.com/yuikns/intrin/blob/master/intrin_x86.h#L769 ?我花了不到 3 分钟就找到了。
Do same intrinsics exist for CLang/GCC?您是否阅读了编译器文档来检查自己?前任。这里:gcc.gnu.org/onlinedocs/gcc-11.1.0/gcc/…Is there a way to be sure without compiler guessing through using some intrinsic?不,“内在”这个名字已经意味着它依赖于编译器。 -
@KamilCuk 谢谢!通过汇编程序看起来像是一个不错的解决方案。如果您将
__emulu()和_umul128()的汇编代码作为答案发布,那就太好了。我可以接受。 -
@KamilCuk 我也看不到 128 位版本。你知道 128 位的汇编代码吗?
-
@KamilCuk 因此,如果您知道如何在 GCC/Clang 汇编程序中为 32 位和 64 位的解决方案编写代码,请发布此 asm 作为我问题的答案。
标签: c++ 64-bit multiplication 32-bit intrinsics