我在測試Intel ADX添加進位並添加溢出到流水線添加大整數。我想看看預期的代碼生成應該是什麼樣子。從_addcarry_u64 and _addcarryx_u64 with MSVC and ICC,我認爲這將是一個合適的測試案例:adcx和adox的測試用例
#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;
}
當我使用-O3
和-madx
檢查generated code from GCC 6.1,它揭示了系列化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代碼應該生成管道。所以我猜我做錯了什麼:
說明
帶符號的8位進位無符號添加64位整數a和b C_IN (攜帶或溢出標誌),並將無符號的64位結果輸出, 和dst(進位或溢出標誌)的執行結果。
怎樣才能生成pipeline'd添加進位/添加溢出(adcx
/adox
)?
其實我已經得到了第5代酷睿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
...
我認爲這些內在函數大多存在,因爲MSVC不允許在64位模式下進行內聯彙編。有了GCC,在這種情況下,您需要使用內聯彙編。事實上,使用GCC已經存在數十年的'adc'的最好方法是內聯彙編。將內聯彙編作爲選項很不錯,但它太糟糕了,比如PITA在GCC中使用它。 –