Ich teste Intel ADX hinzufügen mit tragen und hinzufügen mit Überlauf zu Pipeline fügt auf große Ganzzahlen. Ich würde gerne sehen, wie die Code-Generierung aussehen sollte. Von _addcarry_u64 and _addcarryx_u64 with MSVC and ICC, dachte ich, das ein geeigneter Testfall wäre:Testfall für adcx und 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;
}
Als ich die generated code from GCC 6.1-O3
und -madx
verwende, prüfen zeigt es serialisiert addc
. -O1
und -O2
erzeugt ähnliche Ergebnisse:
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
So wird der Testfall vermute ich, nicht ganz die Marke schlagen, oder ich tue etwas falsch, oder ich bin mit etwas falsch, ...
Wenn ich die Dokumente von Intel unter _addcarryx_u64
richtig analysiere, glaube ich, dass der C-Code die Pipeline erzeugen sollte. Also ich vermute ich etwas tue, falsch:
Beschreibung
hinzufügen unsigned 64-Bit ganze Zahlen a und b mit unsigned 8-Bit-Carry-in C_IN (tragen oder Überlauf-Flag), und speichern Sie das vorzeichenlose 64-Bit-Ergebnis in out, und den Übertrag in dst (Übertrag oder Überlauf-Flag).
Wie kann ich die pipeline'd mit Trage hinzufügen generieren/add mit Überlauf (adcx
/adox
)?
Ich habe tatsächlich eine fünfte für den Test bereit Core i7 Generation (man beachte den adx
CPU-Flag):
$ 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
...
Ich denke, dass diese intrinsics meist da sind, weil MSVC Inline-Assembly in 64-Bit-Modus nicht zulässt. Bei GCC wird in diesem Fall die Inline-Montage benötigt. Tatsächlich ist der beste Weg, 'adc' zu verwenden, der seit Jahrzehnten mit GCC zusammenarbeitet, die Inline-Montage. Es ist schön, Inline-Assemblierung als Option zu haben, aber es ist zu schade, dass es wie PITA in GCC verwendet wird. –