Я ' m пытается написать некоторый ресурсоемкий код для целевой платформы Windows x64 с SSE или новыми инструкциями AVX, компилируя в GCC 4.5.2 и 4.6.1, MinGW64 (сборка TDM GCC и некоторая пользовательская сборка). Мои параметры компилятора: -O3 -mavx
. (Подразумевается -m64
)
Короче говоря, я хочу выполнить несколько длительных вычислений на 4 трехмерных векторах упакованных чисел с плавающей запятой. Для этого требуется 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>
- это просто структура
из 3 __ m128
, с естественным сложением и умножением на скаляр. Когда строка a2 - = v
закомментирована, то есть нам нужно только 3x3 регистра для хранения, поскольку мы игнорируем a2
, полученный код действительно прост, без ходов, все выполняется в регистрах xmm0-xmm10
. Когда я удаляю комментарий a2 - = v
, код получается довольно ужасным с большим количеством перемещений между регистрами и стеком. Хотя компилятор может просто использовать регистры xmm11-xmm13
или что-то в этом роде.
На самом деле я еще не видел, чтобы GCC использовал какие-либо регистры xmm11-xmm15
где-либо во всем моем коде. Что я делаю неправильно? Я понимаю, что это регистры, сохраненные вызываемым пользователем, но эти накладные расходы полностью оправдываются упрощением кода цикла.