Регистры не содержат инструкции, но я предполагаю, что вы имели в виду объединение нескольких значений в один регистр, чтобы вы могли добавить их оба с помощью одной инструкции.
Да, это называется SIMD. (Одна инструкция, несколько данных) На x86-64 SSE2 (потоковые расширения SIMD) гарантированно доступны, поэтому у вас есть 16 различных 16-байтовых регистров (xmm0..15). И у вас есть инструкции, которые могут сделать упакованные FP добавить / sub / mul / div / sqrt / cmp из 4x 32-битных чисел с плавающей запятой, 2x 64-битных двойных, упакованных целых чисел add / sub / cmp / shift / et c для байта, Размеры операндов word, dword и qword.
(С некоторыми пробелами; SSE2 не очень ортогональн, например, самый узкий сдвиг - 16-битный, упакованный минимум / максимум доступен только для определенных размеров. Некоторые из этих пробелов заполнено SSE4.1).
И побитово-логические вещи, где ширина элемента не имеет значения (до AVX512 с регистрами маски ...)
См. https://www.felixcloutier.com/x86/. p...
инструкции типа paddw
упакованы целыми числами. ...ps
и pd
являются упакованными одинарными или упакованными двойными числами с плавающей запятой.
Компиляторы часто используют инструкции SSE / SSE2, такие как movdqa
, чтобы обнулить или скопировать память в 16-байтовом фрагменты, а также для «векторизации» (используйте вычисления SIMD) для циклов над массивами. И G CC 7 или 8 и более поздние знают, как объединить нагрузки / хранилища соседних элементов структуры или элементов массива в скалярную загрузку или хранилище, например, с помощью RAX.
например, эта сумма массива:
int sumarr(const int *arr)
{
int sum = 0;
for(int i=0; i < 10240; i++) {
sum += arr[i];
}
return sum;
}
компилируется следующим образом с GCC9.3 -O3 для x86-64 в проводнике компилятора Godbolt
sumarr:
lea rax, [rdi+40960] # endp = arr + size
pxor xmm0, xmm0
.L2: # do {
movdqu xmm2, XMMWORD PTR [rdi] # v = arr[i + 0..3]
add rdi, 16 # p += 4
paddd xmm0, xmm2 # sum += v // packed addition of 4 elements
cmp rax, rdi
jne .L2 # }while(p != endp)
... then a horizontal vector sum ...
MOVD eax, xmm0
ret
Векторизация похожа на распараллеливание и для Подобное сокращение (суммирование массива до скалярного) требует ассоциативных операций. например, версия FP будет векторизоваться только с -ffast-math
или с OpenMP.
В регистре общего назначения, таком как RAX, в котором нет инструкций для добавления SIMD без переноса между границами байтов (например, * 1042). *paddb xmm0, xmm1
), он называется SWAR (SIMD в регистре).
Этот метод был более полезен в прошлом на ISA без надлежащего набора инструкций SIMD, таких как Alpha или MIPS64. Но это все еще возможно, и методы SWAR могут быть полезны как часть чего-то наподобие подсчета без инструкции popcnt
, например, маскировка каждого второго бита и сдвиг, так что вы эффективно делаете 32 отдельных дополнения (которые не могут быть переполнены в каждом прочее) в 2-битные аккумуляторы.
Popcnt bithack, показанный в Как посчитать количество установленных бит в 32-битном целом числе? делает это, расширяясь до 4-битных счетчиков, затем 8-разрядный, затем используется умножение для сдвига и сложения на 4 различных сдвига и получения суммы в старшем байте.