_addcarry_u64和_addcarryx_u64与MSVC和ICC

时间:2015-03-24 09:46:51

标签: visual-c++ assembly intrinsics icc adx

MSVC和ICC都支持内在函数_addcarry_u64_addcarryx_u64

根据Intel's Intrinsic Guidewhite paper,这些应分别映射到adcxadox。但是,通过查看生成的程序集,很明显它们分别映射到adcadcx,并且没有内在映射到adox

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

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

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

这对于MSVC意义而言是有道理的,它不允许内联汇编它应该提供一种使用adc的方法,它与_addcarry_u64一起使用。

adcxadox的一大优势是它们在不同的标志上运行(携带CF和溢出OF),这允许两个独立的并行进位链。但是,由于adox没有内在因素,这怎么可能?对于ICC,至少有一个可以使用内联汇编,但在64位模式下使用MSVC是不可能的。


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

_addcarry_u64内在文档说明只生成adc_addcarryx_u64内在因素可以生成adcxadox。但是,在MSVC 2013和2015中,_addcarryx_u64仅生成adcx。 ICC生产两者。

2 个答案:

答案 0 :(得分:3)

他们映射到adcadcxadox。编译器根据您使用它们的方式决定使用哪些指令。如果并行执行两个big-int添加,编译器将使用adcxadox,以获得更高的吞吐量。例如:

unsigned char c1 = 0, c2 = 0
for(i=0; i< 100; i++){ 
    c1 = _addcarry_u64(c1, res[i], a[i], &res[i]);
    c2 = _addcarry_u64(c2, res[i], b[i], &res[i]);
}

答案 1 :(得分:3)

相关,GCC目前不支持ADOX和ADCX。 &#34;目前&#34;包括GCC 6.4(Fedora 25)和GCC 7.1(Fedora 26)。 GCC有效地禁用了内在函数,但它仍然通过在预处理器中定义__ADX__来宣传支持。另请参阅Issue 67317, Silly code generation for _addcarry_u32/_addcarry_u64。非常感谢习若愚找到了这个问题。

根据GCC帮助邮件列表中的Uros Bizjak,GCC可能会never support the intrinsics。另请参阅GCC does not generate ADCX or ADOX for _addcarryx_u64

Clang在ADOX和ADCX方面有一系列问题。 Clang 3.9和4.0在尝试使用它们时崩溃。另请参阅Issue 34249, Panic when using _addcarryx_u64 with Clang 3.9。根据Craig Topper的说法,它应该在Clang 5.0中修复。

我很抱歉在MSVC问题下发布信息。这是搜索有关使用内在函数的信息时为数不多的点击之一。