Зачем указывать адрес переменной в ASM, а не просто копировать его в регистр?

В своем стремлении изучить ассемблер (используя GCC на x86_64) я столкнулся с некоторыми примерами SSE, где вместо простого копирования переменной C в регистр вместо этого адрес копируется в EAX. Зачем это делать, когда можно просто сделать это:

typedef float v4sf __attribute__((vector_size(16)));

typedef union {
    v4sf v;
    float f[4];
} Vec4;

Vec4 vector.v = (v4sf){ 64.1,128.2,256.3,512.4 };
float blah = 2.2;

__asm__("movups %0, %%xmm0 \n\t"
    "movups %1, %%xmm1 \n\t"
    "shufps $0x00, %%xmm1, %%xmm1 \n\t"
    "mulps %%xmm1, %%xmm0 \n\t"
    "movups %%xmm0, %0 \n\t"
    : "+m"(vector)
    : "m"(blah)
    : "%xmm0","%xmm1"
);

Копирование вектора в xmm0 (вместо сохранения его в памяти) приводит к снижению производительности?

Вот пример того, о чем я говорю (это синтаксис Intel):

void powf_schlickSSE(const float * a, const float b, float * result){

    __asm {
        mov         eax, a              //load address of vector
        movss       xmm0, dword ptr [b] //load exponent into SSE register
        movups      xmm1, [eax]         //load vector into SSE register
        shufps      xmm0, xmm0, 0       //shuffle b into all floats
        movaps      xmm2, xmm1          //duplicate vector
        mov         eax, result         //load address of result
        mulps       xmm1, xmm0          //xmm1 = a*b
        subps       xmm0, xmm1          //xmm0 = b-a*b
        addps       xmm0, xmm2          //xmm2 = b-a*b+a
        rcpps       xmm0, xmm0          //xmm1 = 1 / (b-a*b+a)
        mulps       xmm2, xmm0          //xmm0 = a * (1 / (b-a*b+a))
        movups      [eax], xmm2         //store result
    }
}

person Synthetix    schedule 25.10.2011    source источник
comment
Можете ли вы показать нам исходный код/сборку с описанным вами поведением? Трудно точно сказать, о чем вы спрашиваете.   -  person Mysticial    schedule 25.10.2011
comment
Конечно, я добавил пример в синтаксисе Intel.   -  person Synthetix    schedule 25.10.2011
comment
Такая сборка определенно далека от оптимальной. В настоящее время предпочтительнее просто использовать встроенные функции, если вы не уверены, что сможете победить компилятор.   -  person Mysticial    schedule 25.10.2011
comment
Вы спрашиваете, медленнее ли использовать регистры xmm, чем иметь вектор в памяти?   -  person user786653    schedule 25.10.2011
comment
Есть ли функция pow(), которая будет работать с векторами? Если нет, то не нужно ли мне писать это вручную?   -  person Synthetix    schedule 25.10.2011
comment
@Synthetix: Даже если вам нужно написать это вручную, зачем использовать asm вместо встроенных функций sse для соответствующих коммандос sse? Таким образом, компилятор не пропустит его оптимизацию. И я все еще не уверен, о чем ваш вопрос. Вы спрашиваете, быстрее ли загрузить переменную в регистр перед ее использованием, чем использовать инструкции, которые добавляют переменную, загруженную из памяти, в регистр?   -  person Grizzly    schedule 18.11.2011


Ответы (1)


Я вижу несколько причин

  • MSVC (из которого исходит этот код синтаксиса Intel, верно?) не поддерживает передачу значений __m128 в ассемблерные блоки, или, по крайней мере, версия, для которой был написан код, не поддерживает. Или, может быть, эта версия вообще не поддерживала SSE, кроме встроенной сборки.

  • Остальная часть программы не работала с векторными типами, поэтому передача по указателю была самым простым решением.

person fgp    schedule 02.10.2012