Следующие циклы транспонируют целую матрицу в другую целочисленную матрицу. когда я компилировал интересно, он генерирует команду movaps
для сохранения результата в матрицу вывода. почему gcc
делает это?Почему эта программа SSE2 (целые) генерирует movaps (float)?
данные:
int __attribute__((aligned(16))) t[N][M]
, __attribute__((aligned(16))) c_tra[N][M];
петли:
for(i=0; i<N; i+=4){
for(j=0; j<M; j+=4){
row0 = _mm_load_si128((__m128i *)&t[i][j]);
row1 = _mm_load_si128((__m128i *)&t[i+1][j]);
row2 = _mm_load_si128((__m128i *)&t[i+2][j]);
row3 = _mm_load_si128((__m128i *)&t[i+3][j]);
__t0 = _mm_unpacklo_epi32(row0, row1);
__t1 = _mm_unpacklo_epi32(row2, row3);
__t2 = _mm_unpackhi_epi32(row0, row1);
__t3 = _mm_unpackhi_epi32(row2, row3);
/* values back into I[0-3] */
row0 = _mm_unpacklo_epi64(__t0, __t1);
row1 = _mm_unpackhi_epi64(__t0, __t1);
row2 = _mm_unpacklo_epi64(__t2, __t3);
row3 = _mm_unpackhi_epi64(__t2, __t3);
_mm_store_si128((__m128i *)&c_tra[j][i], row0);
_mm_store_si128((__m128i *)&c_tra[j+1][i], row1);
_mm_store_si128((__m128i *)&c_tra[j+2][i], row2);
_mm_store_si128((__m128i *)&c_tra[j+3][i], row3);
}
}
Сборочные сгенерированный код:
.L39:
lea rcx, [rsi+rdx]
movdqa xmm1, XMMWORD PTR [rdx]
add rdx, 16
add rax, 2048
movdqa xmm6, XMMWORD PTR [rcx+rdi]
movdqa xmm3, xmm1
movdqa xmm2, XMMWORD PTR [rcx+r9]
punpckldq xmm3, xmm6
movdqa xmm5, XMMWORD PTR [rcx+r10]
movdqa xmm4, xmm2
punpckhdq xmm1, xmm6
punpckldq xmm4, xmm5
punpckhdq xmm2, xmm5
movdqa xmm5, xmm3
punpckhqdq xmm3, xmm4
punpcklqdq xmm5, xmm4
movdqa xmm4, xmm1
punpckhqdq xmm1, xmm2
punpcklqdq xmm4, xmm2
movaps XMMWORD PTR [rax-2048], xmm5
movaps XMMWORD PTR [rax-1536], xmm3
movaps XMMWORD PTR [rax-1024], xmm4
movaps XMMWORD PTR [rax-512], xmm1
cmp r11, rdx
jne .L39
gcc -Wall -msse4.2 -masm="intel" -O2 -c -S
skylake
linuxmint
-mavx2
или -march=naticve
сгенерируйте VEX-кодировку: vmovaps
.
На самом деле Intel и AMD рекомендуют применять методы генерации кода. На самом деле, для современных процессоров Intel рекомендует всегда использовать '' movups'', поскольку выровненные и неравномерные нагрузки имеют одинаковые значения, ориентированные на производительность. См. [Intel] (http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html) и [AMD] (http: //developer.amd.com/resources/developer-guides-manuals/) руководства по оптимизации программного обеспечения. –
@ChuckWalbourn 'movups' и' movaps' имеют только ту же производительность, что и Nehalem. Но даже это вводит в заблуждение, потому что «movups» не может сбрасывать операции, так что действительно только «vmovaps» устарел. Итак, вы уверены, что это рекомендации Intel и AMD? Возможно, они хотят всегда использовать 'vmovups', если ваше оборудование поддерживает его. –
@ChuckWalbourn Я искал справочник Intel, на который вы указали, но я не нашел рекомендации, которую вы упомянули. В каком разделе вы ссылаетесь. Я также искал 'vmovaps', и он несколько раз показывался в коде, поэтому даже Intel все еще использует его. –