Visual c++ _使用MSVC和ICC添加Carry_u64和_addcarryx_u64
MSVC和ICC都支持内部函数Visual c++ _使用MSVC和ICC添加Carry_u64和_addcarryx_u64,visual-c++,assembly,intrinsics,icc,adx,Visual C++,Assembly,Intrinsics,Icc,Adx,MSVC和ICC都支持内部函数\u addcarry\u u64和\u addcarryx\u u64 根据,这些应分别映射到adcx和adox。但是,通过查看生成的程序集,可以清楚地看到它们分别映射到adc和adcx,并且没有映射到adox的内在属性 此外,告诉编译器在Linux上使用ICC启用AVX2时使用/arch:AVX2或-march=core-AVX2也没有什么区别。 我不知道如何使用MSVC和ICC启用ADX 该列表使用ADX技术列出了\u addcarryx\u u64,而\u
\u addcarry\u u64
和\u addcarryx\u u64
根据,这些应分别映射到adcx
和adox
。但是,通过查看生成的程序集,可以清楚地看到它们分别映射到adc
和adcx
,并且没有映射到adox
的内在属性
此外,告诉编译器在Linux上使用ICC启用AVX2时使用/arch:AVX2
或-march=core-AVX2
也没有什么区别。
我不知道如何使用MSVC和ICC启用ADX
该列表使用ADX技术列出了\u addcarryx\u u64
,而\u addcarry\u u64
没有列出的技术。但是,MSVC文档中有关这些内部函数的链接直接指向《英特尔内部函数指南》,该指南与MSVC自己的文档和生成的程序集相矛盾
由此我得出结论,英特尔的内在指南和白皮书是错误的
这对于MSVC来说有一定的意义,因为它不允许内联汇编。它应该提供一种使用adc
的方法,就像它使用\u addcarry\u u64
一样
adcx
和adox
的一大优点是,它们在不同的标志(进位CF
和溢出of
)上运行,这允许两个独立的平行进位链。然而,既然没有adox的内在特性,这怎么可能呢?对于ICC,至少可以使用内联汇编,但对于64位模式的MSVC,这是不可能的
微软和英特尔的文档(白皮书和在线内部指南)现在都同意了
\u addcarry\u u64
内部文档说明仅生成adc
。\u addcarryx\u u64
内部可产生adcx
或adox
。然而,在MSVC 2013和2015中,\u addcarryx\u u64
仅产生adcx
。ICC生产这两种产品。它们映射到adc
、adcx
和adox
。编译器根据您如何使用指令来决定要使用哪些指令。如果并行执行两个大整数加法,编译器将使用adcx
和adox
,以获得更高的吞吐量。例如:
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]);
}
无符号字符c1=0,c2=0
对于(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]);
}
与此相关,GCC目前不支持ADOX和ADCX。“目前”包括GCC 6.4(Fedora 25)和GCC 7.1(Fedora 26)。GCC有效地禁用了intrinsic,但它仍然通过在预处理器中定义\uuuuuuuuuuuuu
来宣传支持。另见。非常感谢席若瑶发现这个问题。
根据GCC帮助邮件列表上的Uros Bizjak,GCC可能会。另见
关于ADOX和ADCX,Clang有自己的一系列问题。Clang3.9和4.0在尝试使用它们时崩溃。另见。根据Craig Topper的说法,它应该在Clang 5.0中修复
我很抱歉在MSVC问题下发布这些信息。这是搜索有关使用Intrinsic的信息时为数不多的点击之一。ADOX和ADCX是从Broadwell开始引入的,那么如何让它与AVX2一起工作呢?@LưuVĩnhPhúc,非常好。如何使用MSVC和ICC启用ADX
?在任何情况下,编译器仍然使用_addcarryx生成adcx_u64@LưuVĩnhPhúc,ICC 13.0.1(我从中使用)于2012年底发布,因此它可能不支持ADX
。ICC现在达到了15.0.2。我认为如果没有启用ADX,那么MSVC和ICC都会使用adc
和\u addcarry\u u64
。这可以解释我所观察到的情况。如果ADX
未启用(并且\u addcarryx\u u64
应该生成adox
而不是adcx
),则编译应该会失败。我刚买了一台Skylake笔记本电脑,这是我开始玩的东西之一。在VS2015和ICC15上,\u addcarry\u u64()
仅产生adc
。在VS2015上,\u addcarryx\u u64()
仅产生adcx
,而从不产生adox
。在ICC15上,\u addcarryx\u u64()
可以根据编译器的判断生成adcx
或adox
。实际上,ICC15试图对其进行智能化处理,当它检测到存在多个进位链时,将生成adox
。也就是说,它不是最优的,我第一次尝试内联汇编时就能够轻而易举地击败ICC15。但是,当您试图实现可变长度乘法时,操作的尺寸在运行时之前是未知的,您需要循环。和循环具有计数器,这些计数器将对标志寄存器进行缓冲。这意味着您需要保存和恢复这两个标志。这太糟糕了。我不知道如何使用ICC或MSVC启用ADX
。我不确定ICC13是否支持它。也许您可以将示例的程序集输出添加到您的答案中?“我不知道如何使用ICC启用ADX…”-对于GCC、ICC和可能的Clang,请使用-march=native
(如果是本机CPU功能),或添加-madx
功能标志。相关,请参见。它不会在GCC 6.1下的-O3
中生成adcx
/adox
“编译器根据您如何使用它们来决定要使用哪些指令…”-您认为4路进位加法是否会使编译器生成除序列化adc
之外的其他指令?@jww:这看起来是adcx/adox的完美用例。但我认为编译器还不够聪明,无法充分利用这一优势。目前,它们支持生成正确代码的内在机制。也许在一年左右的时间里,他们会制作出既快速又正确的代码,而不需要修改源代码。注意clang3.8.1在这里确实使用了adcx,但是使用了一些非常糟糕的标志保存(sahf)和eax的push/pop(a