2014-07-18 10 views
7

Questa domanda si riferisce a gcc (4.6.3 Ubuntu) e al suo comportamento nei loop di srotolamento per gli intrinseci SSE con operandi immediati.Quale opzione gcc abilita lo srotolamento del loop per gli intrinsechi SSE con operandi immediati?

Un esempio di intrinseco con operando immediato è _mm_blend_ps. Si aspetta un numero intero immediato a 4 bit che può essere solo una costante. Tuttavia, usando l'opzione -O3, il compilatore apparentemente automaticamente srotola i loop (se i valori del contatore del ciclo possono essere determinati al momento della compilazione) e produce più istanze dell'istruzione di fusione corrispondente con diversi valori immediati.

Questo è un semplice codice di prova (blendsimple.c) che attraversa i 16 valori possibili della operando immediato della miscela:

#include <stdio.h> 
#include <x86intrin.h> 

#define PRINT(V)    \ 
    printf("%s: ", #V);    \ 
    for (i = 3; i >= 0; i--) printf("%3g ", V[i]); \ 
    printf("\n"); 

int 
main() 
{ 
    __m128 a = _mm_set_ps(1, 2, 3, 4); 
    __m128 b = _mm_set_ps(5, 6, 7, 8); 
    int i; 
    PRINT(a); 
    PRINT(b); 
    unsigned mask; 
    __m128 r; 
    for (mask = 0; mask < 16; mask++) { 
    r = _mm_blend_ps(a, b, mask); 
    PRINT(r); 
    } 
    return 0; 
} 

È possibile compilare il codice con

gcc -Wall -march=native -O3 -o blendsimple blendsimple.c 

e il codice funziona. Ovviamente il compilatore srotola il ciclo e inserisce le costanti per l'operando immediato.

Tuttavia, se si compila il codice con

gcc -Wall -march=native -O2 -o blendsimple blendsimple.c 

si ottiene il seguente errore per la miscela intrinseca:

error: the last argument must be a 4-bit immediate 

Ora ho cercato di scoprire quale specifica bandiera compilatore è attiva in - O3 ma non in -O2 che consente al compilatore di srotolare il ciclo, ma fallito. In seguito la documentazione on-line gcc a

https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Overall-Options.html

ho eseguito i seguenti comandi:

gcc -c -Q -O3 --help=optimizers > /tmp/O3-opts 
gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts 
diff /tmp/O2-opts /tmp/O3-opts | grep enabled 

che elenca tutte le opzioni abilitate da -O3 ma non da -O2. Quando aggiungo tutti i 7 bandiere elencati oltre a -O2

gcc -Wall -march=native -O2 -fgcse-after-reload -finline-functions -fipa-cp-clone -fpredictive-commoning -ftree-loop-distribute-patterns -ftree-vectorize -funswitch-loops blendsimple blendsimple.c 

mi aspetterei che il comportamento è esattamente lo stesso con -O3. Tuttavia, il compilatore si lamenta che "l'ultimo argomento deve essere un immediato a 4 bit".

Qualcuno ha un'idea di quale sia il problema? Penso che sarebbe bene sapere quale flag è necessario per abilitare questo tipo di srotolamento del loop in modo che possa essere attivato in modo selettivo usando #pragma GCC Optimize o tramite un attributo di funzione.

(Sono stato anche sorpreso dal fatto che -O3 ovviamente non abilita nemmeno l'opzione srotolamento loop).

Sarei grato per qualsiasi aiuto. Questo è per una lezione sulla programmazione SSE che do.

Modifica: Grazie mille per i vostri commenti. jtaylor sembra avere ragione. Ho avuto la mano su due versioni più recenti di gcc (4.7.3, 4.8.2) e 4.8.2 si lamentano del problema immediato indipendentemente dal livello di ottimizzazione. Moverover, in seguito ho notato che gcc 4.6.3 compila il codice con -O2 -funroll-loops, ma anche questo fallisce in 4.8.2. Quindi apparentemente non ci si può fidare di questa caratteristica e dovremmo sempre srotolare "manualmente" usando cpp o template, come ha sottolineato Jason R.

+0

ottengo l'errore 'l'ultimo argomento deve essere un 4-bit immediate' anche con -O3 . –

+0

Si può sempre implementare lo srotolamento manualmente usando l'elaborazione del preprocessore o la metaprogrammazione del modello (se si scrive in C++). –

+1

questo comportamento sembra più un bug del compilatore (che è stato risolto in 4.8) i compilatori non dovrebbero fornire errori su diversi livelli di ottimizzazione. gcc dovrebbe o supportare sempre non immediatamente (ad esempio tramite condizionali) o mai. Sembra che abbiano scelto la versione successiva nelle versioni successive. Il che ha senso, gli oggetti intrinseci dovrebbero essere involucri molto sottili attorno alle istruzioni della macchina – jtaylor

risposta

1

Non sono sicuro se questo si applica alla situazione, dal momento che non conosco le intrinseche di SSE.Ma in generale, si può dire al compilatore di ottimizzare specificamente una sezione di codice con:

#pragma GCC push_options 
#pragma GCC optimize ("unroll-loops") 

do your stuff 

#pragma GCC pop_options 

Fonte: Tell gcc to specifically unroll a loop

Problemi correlati