Может ли компилятор (gcc) гарантировать выполнение циклов С++?

Мне нужно выполнить следующие операции AVX:

__m256 perm, func;
__m256 in = _mm256_load_ps(inPtr+x);
__m256 acc = _mm256_setzero_ps();

perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(3,2,1,0));
func = _mm256_load_ps(fPtr+0);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));

perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(2,3,0,1));
func = _mm256_load_ps(fPtr+1);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));

perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(1,0,3,2));
func = _mm256_load_ps(fPtr+2);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));

perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(0,1,2,3));
func = _mm256_load_ps(fPtr+3);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));

Это можно было бы переписать так:

__m256 perm, func;
__m256 in = _mm256_load_ps(inPtr+x);
__m256 acc = _mm256_setzero_ps();
for(int i=0;i<4;++i)
{
    perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(3^i,2^i,1^i,0^i));
    func = _mm256_load_ps(fPtr+i);
    acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
}

Это компилируется в gcc 4.9.1, несмотря на то, что _mm256_shuffle_ps принимает только непосредственные целочисленные значения в качестве третьего параметра. Это означает, что i принимается как немедленная, и, таким образом, цикл развёрнут.

Поэтому мне любопытно: гарантируется ли это компилятором или это может вызвать ошибки компиляции при изменении флагов оптимизации или при изменении версии gcc? Как насчет использования других компиляторов (msvc, icc, clang...)


person galinette    schedule 03.03.2016    source источник
comment
Вы пробовали -O0? Что просходит?   -  person mindriot    schedule 03.03.2016
comment
Кроме того, как вы пришли к выводу, что поддерживается только немедленное? реализация GCC, кажется, требует const int и спецификации Intel, похоже, утверждает то же самое.   -  person mindriot    schedule 03.03.2016
comment
сигнатура const int ничего не говорит, так как в языке нет ничего, что указывало бы, является ли параметр непосредственным. Кроме того, любой параметр imm в документации по внутренним компонентам Intel означает немедленный. Это яснее в документации MSDN. И, наконец, использование не немедленного значения в gcc вызывает ошибку: последний аргумент должен быть 8-битным немедленным   -  person galinette    schedule 03.03.2016


Ответы (1)


Внутреннее требует немедленного значения. Компиляция работает только потому, что она была оптимизирована как константа путем развертывания цикла, а компиляция с параметром -O0 вызывает следующую ошибку:

(...)\lib\gcc\x86_64-w64-mingw32\4.9.2\include\avxintrin.h:331: ошибка: последний аргумент должен быть 8-битным немедленным

      __mask);
            ^

Об аналогичном случае сообщалось с icc здесь:

https://software.intel.com/en-us/forums/intel-c-compiler/topic/287217

person galinette    schedule 03.03.2016