我正在测试带有进位的英特尔 ADX添加和带有溢出的添加到管道添加大整数。我想看看预期的代码生成应该是什么样子。从_addcarry_u64 和 _addcarryx_u64 与 MSVC 和 ICC,我认为这将是一个合适的测试用例:
#include <stdint.h>
#include <x86intrin.h>
#include "immintrin.h"
int main(int argc, char* argv[])
{
#define MAX_ARRAY 100
uint8_t c1 = 0, c2 = 0;
uint64_t a[MAX_ARRAY]={0}, b[MAX_ARRAY]={0}, res[MAX_ARRAY];
for(unsigned int i=0; i< MAX_ARRAY; i++){
c1 = _addcarryx_u64(c1, res[i], a[i], (unsigned long long int*)&res[i]);
c2 = _addcarryx_u64(c2, res[i], b[i], (unsigned long long int*)&res[i]);
}
return 0;
}
当我使用and检查从 GCC 6.1 生成的代码时,它显示 serialized 。并产生类似的结果:-O3
-madx
addc
-O1
-O2
main:
subq $688, %rsp
xorl %edi, %edi
xorl %esi, %esi
leaq -120(%rsp), %rdx
xorl %ecx, %ecx
leaq 680(%rsp), %r8
.L2:
movq (%rdx), %rax
addb $-1, %sil
adcq %rcx, %rax
setc %sil
addb $-1, %dil
adcq %rcx, %rax
setc %dil
movq %rax, (%rdx)
addq $8, %rdx
cmpq %r8, %rdx
jne .L2
xorl %eax, %eax
addq $688, %rsp
ret
所以我猜测测试用例没有达到目标,或者我做错了什么,或者我使用不正确,......
如果我_addcarryx_u64
正确解析英特尔的文档,我相信 C 代码应该生成管道。所以我猜我做错了什么:
描述
将无符号 64 位整数 a 和 b 与无符号 8 位进位 c_in(进位或溢出标志)相加,并将无符号 64 位结果存储在 out 中,并将进位结果存储在 dst(进位或溢出标志)中。
如何生成带有进位添加/带有溢出(adcx
/ adox
)的管道?
我实际上已经准备好要测试的第 5 代 Core i7(注意adx
cpu 标志):
$ cat /proc/cpuinfo | grep adx
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush
dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc
arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni
pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1
sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm
3dnowprefetch ida arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase
tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt
...