2017-02-15 43 views
2

Следующие циклы транспонируют целую матрицу в другую целочисленную матрицу. когда я компилировал интересно, он генерирует команду 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.

ответ

6

Функционально эти инструкции являются одинаковыми. Я не люблю копировать + вставить другие высказывания людей, как у меня так мало ссылок объясняя это:

Difference between MOVDQA and MOVAPS x86 instructions?

https://software.intel.com/en-us/forums/intel-isa-extensions/topic/279587

http://masm32.com/board/index.php?topic=1138.0

https://www.gamedev.net/blog/615/entry-2250281-demystifying-sse-move-instructions/

Укороченный вариант:

Итак, по большей части вам следует попытаться использовать команду перемещения, которая соответствует , с операциями, которые вы собираетесь использовать на этих регистрах. Однако есть дополнительное осложнение. Нагрузки и магазины в память и из памяти выполняются на отдельном порту от целого числа и единиц с плавающей запятой; таким образом, инструкции, загружающие из памяти в , регистр или хранилище из регистра в память будут испытывать такую ​​же задержку независимо от типа данных, который вы прикрепляете к перемещению. Таким образом, в этом случае, movaps, movapd и movdqa будут иметь одинаковую задержку Укажите, какие данные вы используете. Так как movaps (и movups) закодированы в двоичной форме с одним меньшим байтом, чем два других, имеет смысл использовать его для всех перемещений reg-mem независимо от типа данных.

Так что это оптимизация GCC.

+1

На самом деле 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/) руководства по оптимизации программного обеспечения. –

+0

@ChuckWalbourn 'movups' и' movaps' имеют только ту же производительность, что и Nehalem. Но даже это вводит в заблуждение, потому что «movups» не может сбрасывать операции, так что действительно только «vmovaps» устарел. Итак, вы уверены, что это рекомендации Intel и AMD? Возможно, они хотят всегда использовать 'vmovups', если ваше оборудование поддерживает его. –

+0

@ChuckWalbourn Я искал справочник Intel, на который вы указали, но я не нашел рекомендации, которую вы упомянули. В каком разделе вы ссылаетесь. Я также искал 'vmovaps', и он несколько раз показывался в коде, поэтому даже Intel все еще использует его. –

 Смежные вопросы

  • Нет связанных вопросов^_^