Опитвам се да напиша някакъв код с интензивни изчисления за цел на Windows x64, със SSE или новите инструкции на AVX, компилиран в GCC 4.5.2 и 4.6.1, MinGW64 (TDM GCC компилация и някои персонализирани компилации). Моите опции за компилатор са -O3 -mavx
. (-m64
се подразбира)
Накратко, искам да извърша някои дълги изчисления върху 4 3D вектора на опаковани плувки. Това изисква 4x3=12 xmm или ymm регистри за съхранение и 2 или 3 регистъра за временни резултати. IMHO това трябва да пасне плътно в 16-те налични SSE (или AVX) регистъра, налични за 64-битови цели. Въпреки това, GCC произвежда много неоптимален код с разпръскване на регистъра, като използва само регистри xmm0-xmm10
и разбърква данни от и в стека. Въпросът ми е:
Има ли начин да убедите GCC да използва всички регистри xmm0-xmm15
?
За да коригирате идеи, разгледайте следния SSE код (само за илюстрация):
void example(vect<__m128> q1, vect<__m128> q2, vect<__m128>& a1, vect<__m128>& a2) {
for (int i=0; i < 10; i++) {
vect<__m128> v = q2 - q1;
a1 += v;
// a2 -= v;
q2 *= _mm_set1_ps(2.);
}
}
Тук vect<__m128>
е просто struct
от 3 __m128
, с естествено събиране и умножение по скалар. Когато редът a2 -= v
е коментиран, т.е. имаме нужда само от 3x3 регистъра за съхранение, тъй като игнорираме a2
, произведеният код наистина е ясен без движения, всичко се изпълнява в регистри xmm0-xmm10
. Когато премахна коментара a2 -= v
, кодът е доста ужасен с много разбъркване между регистри и стек. Въпреки че компилаторът може просто да използва регистри xmm11-xmm13
или нещо подобно.
Всъщност все още не съм виждал GCC да използва някой от регистрите xmm11-xmm15
никъде в целия ми код. какво правя грешно Разбирам, че те са записани от извиквания регистри, но това допълнително натоварване е напълно оправдано чрез опростяване на кода на цикъла.