2016-12-23 1 views
-2

La plupart des compilateurs n'optimisent pas le code d'assemblage en ligne (VS2015, gcc), cela nous permet d'écrire de nouvelles instructions qu'il ne supporte pas.Quand les compilateurs vont-ils optimiser le code d'assemblage en source C/C++?

Mais quand un compilateur C/C++ doit-il mettre en œuvre l'optimisation en ligne de l'assemblage en ligne?

+0

Cela peut être le cas lorsque vous demandez une optimisation globale. G ++ et MSVC prennent en charge l'optimisation globale. –

+4

J'espère que jamais! Si vous vous en souciez assez pour faire l'assemblage en ligne, vous ne voudrez probablement pas le voir jouer avec. Comment le compilateur sait-il que l'écriture apparemment inutile dans 0xbeefface n'est pas importante pour un périphérique embarqué? – John3136

+3

Lorsque vous utilisez l'assemblage en ligne, vous dites essentiellement au compilateur que vous savez ce que vous faites et que ce sera mieux que ce qu'il peut faire. Pourquoi le compilateur devrait-il tenter de l'optimiser? Si vous voulez que le compilateur optimise votre code, vous devez écrire dans la langue du compilateur, IMO. –

Répondre

6

En général, les compilateurs n'optimiseront pas le contenu de votre assemblage en ligne. Autrement dit, ils ne supprimeront pas ou ne changeront pas d'instructions dans votre bloc d'assemblage. En particulier, gcc passe simplement à travers le corps de votre assembly inline inchangé à l'assembleur sous-jacent (gas dans ce cas).

Cependant, les bons compilateurs peuvent optimiser autour de votre assembly en ligne, et dans certains cas, peuvent même omettre le code d'exécution en ligne! Gcc, par exemple, peut le faire s'il détermine que les sorties déclarées de l'assemblage sont mortes. Il peut également lever un bloc d'assemblage d'une boucle ou combiner plusieurs appels en un seul. Donc, il ne gâche jamais les instructions à l'intérieur du bloc, mais il est tout à fait raisonnable de changer le nombre de fois qu'un bloc serait exécuté. Bien sûr, ce comportement peut également être désactivé si le bloc a un autre effet secondaire important.

Les docs gcc sur la syntaxe ASM étendue ont quelques good examples de toutes ces choses.

6

Jamais. Cela irait à l'encontre du but de l'assemblage en ligne, qui est d'obtenir exactement ce que vous demandez.

Si vous souhaitez utiliser la pleine puissance de l'instruction du CPU cible définie d'une manière que le compilateur peut comprendre et optimiser, vous devez utiliser les fonctions intrinsèques , pas asm en ligne.

par exemple. au lieu de asm inline pour popcnt, utilisez int count = __builtin_popcount(x); (dans GNU C compilé avec -mpopcnt). Inline-asm est aussi spécifique au compilateur, donc si quelque chose d'intrinsèque est plus portable, surtout si vous utilisez les intrinsèques x86 d'Intel qui sont supportés par tous les principaux compilateurs qui peuvent cibler x86. Utilisez #include <x86intrin.h> et vous pouvez utiliser int _popcnt32 (int a) pour obtenir de façon fiable l'instruction popcnt x86. Voir , et d'autres liens dans le wiki tag .


int count(){ 
    int total = 0; 
    for(int i=0 ; i<4 ; ++i) 
    total += popc(i); 
    return total; 
} 

Compilé avec #define popc _popcnt32 par gcc6.3:

mov  eax, 4 
    ret 

clang 3.9 with an inline-asm definition of popc, on the Godbolt compiler explorer:

xor  eax, eax 
    popcnt eax, eax 
    mov  ecx, 1 
    popcnt ecx, ecx 
    add  ecx, eax 
    mov  edx, 2 
    popcnt edx, edx 
    add  edx, ecx 
    mov  eax, 3 
    popcnt eax, eax 
    add  eax, edx 
    ret 

Ceci est un exemple classique de asm en ligne défaisant la propagation constante, et pourquoi vous shouldn Ne l'utilisez pas pour la performance si vous pouvez l'éviter: https://gcc.gnu.org/wiki/DontUseInlineAsm.


C'était la définition inline-asm j'ai utilisé pour ce test:

int popc_asm(int x) { 
    // force use of the same register because popcnt has a false dependency on its output, on Intel hardware 
    // this is just a toy example, though, and also demonstrates how non-optimal constraints can lead to worse code 
    asm("popcnt %0,%0" : "+r"(x)); 
    return x; 
} 

Si vous ne saviez pas que popcnt has a false dependency on its output register on Intel hardware, c'est une autre raison, vous devez laisser au compilateur chaque fois que possible.


En utilisant des instructions spéciales que le compilateur ne connaît pas est un cas d'utilisation pour asm en ligne, mais si le compilateur ne connaît pas, il ne peut certainement pas l'optimiser. Avant que les compilateurs ne réussissent à optimiser les intrinsèques (par exemple pour les instructions SIMD), l'intégration en ligne pour ce genre de chose était plus courante. Mais nous en sommes à de nombreuses années au-delà, et les compilateurs sont généralement bons avec les intrinsèques, même pour les architectures non-x86 comme ARM.

+0

J'ai effectivement entendu parler d'un "optimiseur d'assemblage", bien que je n'en connaisse aucun pour x86 (Google est apparu [ceci] (https://github.com/hundt98847/mao), mais il semble être mort). La plupart sont soit pour des systèmes embarqués, soit des architectures de type RISC, où la programmation en assemblage est extrêmement fastidieuse à cause de tous les registres et des nuances de la programmation des instructions. Donc théoriquement, intégrer une telle chose dans l'assemblage en ligne d'un compilateur C serait possible. Je ne suis pas d'accord que cela irait à l'encontre du but si inline asm, en supposant que cela fonctionne vraiment bien! –

+0

Par exemple, écrire dans l'assemblage pour Itanium est une douleur géante à l'arrière, car vous devez faire attention à [bundles d'instruction et machines à sous] (https://blogs.msdn.microsoft.com/oldnewthing/20150728-00/?p = 90811), et un tas de règles étranges. L'ISA a été conçu pour un compilateur C/C++, et est si compliqué qu'un optimiseur est virtuellement requis pour avoir l'espoir d'obtenir un code objet à moitié décent. Un optimiseur d'assemblage serait plutôt cool. Bien que je suppose que la syntaxe de ASM le rendrait difficile à mettre en œuvre. Comment saurait-il quelles instructions peuvent être réorganisées? –

+0

Pourquoi utiliseriez-vous * inline * -asm en premier lieu (au lieu de intrinsics) si vous vouliez que le compilateur le gicle et émette des instructions différentes? La seule raison à laquelle je peux penser est que C ne peut pas exprimer de manière portative, par ex. un changement de droite arithmétique et diverses autres déficiences. Les intrinsèques sont la solution au problème que je pense que ce PO a vraiment, et ils sont bloqués dans un problème X-Y sur inline-asm optimisé par le compilateur. –