0
votes

GCC optimise-t-il le fichier source de l'assemblage?

Je peux utiliser GCC pour convertir des fichiers de code d'assemblage en fichiers réallouables.

gcc -c source.S -o object.o -O2

L'option d'optimisation est-elle efficace? Puis-je m'attendre à ce que GCC optimise mon code d'assemblage?


9 commentaires

Que s'est-il passé lorsque vous avez essayé? Lorsque vous avez examiné l'entrée et la sortie?


Oui j'ai remarqué quelques petits changements entre la source et le démontage. Mais je ne sais pas si c'est à des fins d'optimisation.


Par exemple, les sources lgdt gdtdesc \n movl %cr0,%eax \n orl $0x1,%eax ont été traduites en cinq instructions lgdtl (%esi) \n insb (%dx),%es:(%edi) \n jl <addr> \n and %al,%al \n or $0x1,%ax


@old_timer Après un moment, j'ai pensé que cela pouvait être un problème d'affichage d'un désassembleur que les deux codes aient la même expression binaire. Le binaire des instructions disas: 0f 01 16 6c 7c 0f 20 c0 66 83 c8 01


et quand vous avez utilisé comme au lieu de gcc vous avez vu quelque chose de différent?


et quand vous n'avez pas utilisé -O2, vous avez vu quelque chose de différent?


aucun gcc n'optimise asm, ld pourrait mais vous devez préparer les objets correctement


Maintenant, je suis presque sûr que c'est un problème d'affichage. J'ai utilisé -O0 et cela m'a donné le même résultat.


Pas gcc en soi, mais il n'y a aucune garantie qu'un optimiseur de temps de liaison de nouvelle génération; ou plus correctement un optimiseur inter-module, pourrait ne pas avoir un aperçu de votre code et le réparer pour vous.


3 Réponses :


5
votes

Non.

GCC transmet votre source d'assemblage via le préprocesseur, puis à l'assembleur. A aucun moment aucune optimisation n'est effectuée.


10 commentaires

Qu'en est-il des optimisations de temps de liaison? (pas dans le cas d'OP, mais en général)


@EugeneSh. Que veux-tu dire par là?


@EugeneSh.: Je m'attendrais à ce que la plupart, sinon la totalité, des optimisations au moment de la liaison reposent sur les informations transmises par le compilateur (via des structures de données spéciales dans les fichiers objets ou dans les fichiers qui leur sont associés, similaires aux informations de débogage) ou des structures particulières ou des paramètres dans ou avec le code d'assemblage qui indiquent certaines optimisations, comme l'identification de sous-sections potentiellement séparables par des symboles globaux, sont disponibles.


@EricPostpischil Cela a du sens.


J'ai une idée très vague d'un souvenir d'un langage d'assemblage frontal pour GCC ou Clang, de sorte qu'il lirait l'assembly comme n'importe quel autre langage de programmation, construirait son arbre sémantique interne habituel et ainsi de suite, l'optimiserait et générerait un nouvel assemblage. Mais je ne me souviens pas de détails, même pas si c'était une idée ou si quelqu'un faisait réellement quelque chose à ce sujet ou si cela avait déjà été fait quelque part. (Hmm, on pouvait identifier les entrées d'une routine par laquelle les registres étaient utilisés sans initialisation évidente. Mais les sorties ne pouvaient pas être correctement déterminées automatiquement.)


C'est décevant. Je pensais qu'il y en avait encore beaucoup si des optimisations pouvaient être effectuées lors de la phase d'assemblage, comme les optimisations de niveau d'instruction et l'intégration d'appels, etc.


@willswordpath En fait, cela semble être une bonne chose. Vous pouvez écrire des éléments que vous ne souhaitez pas optimiser dans l'assemblage. Je veux dire quelle est l'autre raison d'écrire en assemblage?


@EugeneSh. Ils peuvent toujours ajouter une option volatile quelque chose comme -fasm-volatile je suppose? Il doit y avoir quelqu'un qui a déjà travaillé sur l'optimisation de la scène d'assemblage quelque part, car c'est un aspect énorme des industries du logiciel.


@willswordpath: La plupart du code n'est pas écrit à la main dans asm. Si vous voulez un ASM optimisé, optimisez-le vous-même de manière à ce que les outils automatiques ne soient pas assez intelligents, ou laissez les compilateurs le générer à partir d'un code source de plus haut niveau. Mais il existe des optimiseurs binaires à binaires qui pourraient, je suppose, être utiles si vous aviez du code produit par un mauvais vieux compilateur qui ne connaissait pas les processeurs modernes. (le code machine et asm sont faciles à traduire). Voir Existe-t-il des compilateurs ASM? . J'ai entendu parler des optimiseurs binaires à binaires. Mais ce n'est pas ce que la plupart des gens veulent que GAS fasse.


@willswordpath Historiquement, il existe des chaînes d'outils qui optimisaient le code d'assemblage. L'un d'eux est la chaîne d'outils Plan 9 qui survit dans les rudiments en tant que partie de la chaîne d'outils Go. Les pièces d'optimisation de l'assemblage ont cependant été découpées; ce n'est plus une approche à la mode. En effet, il est beaucoup plus facile d'optimiser le code avant qu'il ne soit transformé en assemblage et très peu de gens écrivent de toute façon l'assembly.



2
votes

so.s

ldr r0,=0x12345678
ldr r0,=0x1000
ldr r0,=0xFFFFFF12

00000000 <.text>:
   0:   e59f0004    ldr r0, [pc, #4]    ; c <.text+0xc>
   4:   e3a00a01    mov r0, #4096   ; 0x1000
   8:   e3e000ed    mvn r0, #237    ; 0xed
   c:   12345678    .word   0x12345678

Il n'a même pas prétraité la définition.

renommer so.s en so.S

gcc -flto -O2 so.c -save-temps -o so.o
cat so.s

.file   "so.c"
.section    .gnu.lto_.profile.3f5dbe2a70110b8,"e",@progbits
.string "x\234ca`d`a`"
.string "\222L\214"
.string ""
.string "o"
.ascii  "\016"
.text
.section    .gnu.lto_.icf.3f5dbe2a70110b8,"e",@progbits
.string "x\234ca`d"
.string "\001\016\006\004`d\330|\356\347Nv\006"
.ascii  "\017\243\003I"
.text
.section    .gnu.lto_.jmpfuncs.3f5dbe2a70110b8,"e",@progbits
.string "x\234ca`d"
.string "\001V\006\004"
.string "\213"
.string ""
.string ""
.string "\356"
.ascii  "\f"
.text
.section    .gnu.lto_.inline.3f5dbe2a70110b8,"e",@progbits
.string "x\234ca`d"
.string "\001\021\006\004"
.string "\21203120\001\231l\013\344\231\300b"
.string "\n\031"
.ascii  "\352"
.text
.section    .gnu.lto_.pureconst.3f5dbe2a70110b8,"e",@progbits
.string "x\234ca`d`f`"
.string "\222\f"
.string ""
.string "X"
.ascii  "\n"
.text
.section    .gnu.lto_main.3f5dbe2a70110b8,"e",@progbits
.ascii  "x\234\035\216\273\016\001a\020\205\347\314\277\313\026\210\236"
.ascii  "B\253\3610^\301\003(<\300\376\330B\024\262\005\211\210r\223-"
.ascii  "\334[\3256\n\005\2117\020\n\211NH(\0043&9\2319\231o.\016\201"
.ascii  "4f\242\264\250 \202!p\270'jz\fha=\220\317\360\361bkp\b\226c\363"
.ascii  "\344\216`\216\330\333nt\316\251\005Jb/Qo\210rl%\216\233\276\327"
.ascii  "\r\3211L-\201\247(b\202\242^\230\241L\302\236V\237A6\025([RD"
.ascii  ":s\244\364\243E5\261\337o\333&q\336e\242\273H\037y0k6W\264\362"
.ascii  "\272`\033\255\337\031\275\315p\261\370\357\026\026\312\310\204"
.ascii  "\333\250Wj\364\003\t\210<\r"
.text
.section    .gnu.lto_.symbol_nodes.3f5dbe2a70110b8,"e",@progbits
.string "x\234ca`d\020f"
.string "\002&\206z\006\206\t\347\030@\324\256\206@\240\b"
.ascii  "'\370\004\002"
.text
.section    .gnu.lto_.refs.3f5dbe2a70110b8,"e",@progbits
.string "x\234ca`\004B "
.string ""
.string ""
.string "9"
.ascii  "\007"
.text
.section    .gnu.lto_.decls.3f5dbe2a70110b8,"e",@progbits
.string "x\234\205PMK\002Q\024\275\347\315h\222\021R-\\\270\020\027\355\222\244\020\367A\355b6A\264\013\261p\221AmZ^\377\200DB\340N\004)\320j~A\bA\021\371\007J!\241e\277@\b\354\276y3\216\320\242\013\367\343\335w\3369\367]\233@\332\372\222V%\357\213O\304\224\344\003\nM\243\\\372k\272g\211/\211\257\210;\377\340\331\302w{\370\025\031\340\035\242\201D\202\022\004xC\350\344\225\306\275\243\024\312\213\024\266\020"
.ascii  "\375\263\nJ_\332\300u\317\344I`\001\211O\345\253i\006\302tB\363"
.ascii  "\b\360X\303\247Se\005\337h\226\330\260\316\360\032q\177\023A"
.ascii  "\224\337\337<\266\027\207\370\2502s\223\331\301T\322[#Q\224\331"
.ascii  "\326\373\204\2058\321\302S\203\235+\301\266\270\247\367%\004"
.ascii  "\215\376[\335\262\226\241\353\317\361\355v\266+\327|\311\254"
.ascii  "\n\341\216;?\265\227x\362Z\337\214\252\234\006\234yl\244\260"
.ascii  "\236\022\261\007$%\036\331\0069~\346V4\323d\327\345Q\375U\325"
.ascii  "\270\247GS\032\205;\031\342\036Y=\241\224\022\273\030\002\035"
.ascii  "\fd`\027\031\232\273(\344\327\362\233\024;.UJg\345\"\331'\207"
.ascii  "\345Jlgw/\275\225\313Q\344\3744[\244_\320\267k~"
.text
.section    .gnu.lto_.symtab.3f5dbe2a70110b8,"e",@progbits
.string "main"
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string ""
.string "\260"
.string ""
.string ""
.text
.section    .gnu.lto_.opts,"e",@progbits
.string "'-fmath-errno' '-fsigned-zeros' '-ftrapping-math' '-fno-trapv' '-fno-openmp' '-fno-openacc' '-mtune=generic' '-march=x86-64' '-O2' '-flto' '-fstack-protector-strong'"
.text
.comm   __gnu_lto_v1,1,1
.comm   __gnu_lto_slim,1,1
.ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
.section    .note.GNU-stack,"",@progbits

Il pré-traite la définition mais aucune optimisation ne se produit.

En regardant un peu plus profondément et ce qui est passé comme

gcc -flto -O2 so.S -save-temps -o so.o
cat so.s

# 1 "so.S"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "so.S"


mov $0x5, %eax
mov $0x5,%eax
mov $0x5,%eax
mov $0x5,%eax
retq

Et

int main ( void )
{
    return(5);
}
gcc -O2 so.c -save-temps -o so.o
cat so.s

    .file   "so.c"
    .section    .text.unlikely,"ax",@progbits
.LCOLDB0:
    .section    .text.startup,"ax",@progbits
.LHOTB0:
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    movl    $5, %eax
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .section    .text.unlikely
.LCOLDE0:
    .section    .text.startup
.LHOTE0:
    .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
    .section    .note.GNU-stack,"",@progbits

toujours pas d'optimisation.

Devrait être plus que suffisant pour démontrer. Il existe des optimisations de temps de liaison que vous pouvez faire, vous devez créer les objets correctement, puis en informer l'éditeur de liens. Mais je soupçonne qu'il ne le fait pas au niveau du code machine mais à un niveau élevé et recrée le code.

gcc -O2 -c -save-temps so.S -o so.o
[0][as]
[1][--64]
[2][-o]
[3][so.o]
[4][so.s]

cat so.s
# 1 "so.S"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "so.S"


mov $0x5, %eax
mov $0x5,%eax
mov $0x5,%eax
mov $0x5,%eax
retq

Utilisation du so.S d'en haut

gcc -O2 -c -save-temps so.s -o so.o
[0][as]
[1][--64]
[2][-o]
[3][so.o]
[4][so.s]

cat so.s

#define HELLO 0x5
mov $HELLO, %eax
mov $0x5,%eax
mov $0x5,%eax
mov $0x5,%eax
retq

Utiliser le so.c d'en haut

gcc -O2 -c so.S -o so.o
objdump -d so.o

0000000000000000 <.text>:
   0:   b8 05 00 00 00          mov    $0x5,%eax
   5:   b8 05 00 00 00          mov    $0x5,%eax
   a:   b8 05 00 00 00          mov    $0x5,%eax
   f:   b8 05 00 00 00          mov    $0x5,%eax
  14:   c3                      retq 

Il ne semble donc toujours pas que gcc fasse une optimisation en supprimant ces instructions dupliquées qui n'ont aucun avantage fonctionnel et sont fondamentalement du code mort. Cela montre que gcc pré-traitera le code si le fichier a le .S mais pas si .s (peut expérimenter ou lire les documents sur d'autres .asm?). Ceux-ci ont été exécutés sous linux, gcc est gcc, binutils est binutils, la sensibilité spécifique à l'extension des noms de fichiers peut varier selon l'hôte cible.

L'optimisation du temps de liaison semble être liée au code de haut niveau, car on ne s'attend pas au code du langage assembleur. On s'attend à ce que l'optimisation du temps de liaison soit basée sur le code intermédiaire et non sur le backend.

Nous savons que gcc n'est pas un assembleur, il le transmet simplement même s'il est généré à partir de C, il le transmet donc il aurait besoin d'un analyseur d'assembleur, puis d'une logique pour gérer ce langage pour ensuite choisir les choses à transmettre pour le temps de liaison optimisation.

Vous pouvez en savoir plus sur l'optimisation du temps de liaison et voir s'il existe un moyen de l'appliquer à l'assembleur ... Je suppose que non, mais toute votre question porte sur comment utiliser les outils et comment ils fonctionnent.

L'optimisation du langage d'assemblage n'est pas nécessairement une chose, c'est un peu le point, maintenant il y a des choses pseudo-code pour les pseudo instructions que l'assembleur peut choisir une implémentation optimisée

#define HELLO 0x5
mov $HELLO, %eax
mov $0x5,%eax
mov $0x5,%eax
mov $0x5,%eax
retq

gcc -O2 -c so.s -o so.o
objdump -d so.o

0000000000000000 <.text>:
   0:   b8 00 00 00 00          mov    $0x0,%eax
   5:   b8 05 00 00 00          mov    $0x5,%eax
   a:   b8 05 00 00 00          mov    $0x5,%eax
   f:   b8 05 00 00 00          mov    $0x5,%eax
  14:   c3                      retq  

Mais c'est du pseudo code, donc l'assembleur qui le prend en charge est libre de faire ce qu'il veut. (les assembleurs définissent le langage d'assemblage (pas la cible) donc, par définition, ils peuvent faire ce qu'ils veulent). Sur cette note, l'utilisation d'un compilateur en tant qu'assembleur lorsque la chaîne d'outils a également un assembleur le transforme en un autre langage d'assemblage, car le langage d'assemblage est défini par l'outil. Ainsi, lorsque vous autorisez gcc à prétraiter le code, vous utilisez essentiellement un langage d'assemblage différent de as. Tout comme l'assemblage en ligne pour le compilateur est encore un autre langage d'assemblage. Au moins trois langages d'assemblage par cible pour la chaîne d'outils gnu.


0 commentaires

3
votes

Si vous ne voulez pas optimiser manuellement votre asm, le langage d'assemblage est le mauvais choix de langue source pour vous. Considérez peut-être LLVM-IR si vous voulez quelque chose de semblable à asm mais qui est en fait une entrée pour un compilateur d'optimisation. (Et indépendant de l'ISA.)

Pour être honnête, il existe des recompilateurs / optimiseurs binaires à binaires qui essaient de déterminer les détails de l'implémentation et la logique importante, et d'optimiser en conséquence. (La lecture à partir de la source asm au lieu du code machine serait également possible; asm et le code machine sont faciles à convertir d'avant en arrière et ont un mappage presque 1: 1). Mais ce n'est pas ce que font les assembleurs.

Le travail d'un assembleur consiste normalement à traduire fidèlement ce que vous écrivez en asm. Avoir un outil pour faire cela est nécessaire pour expérimenter pour découvrir ce qui est réellement plus rapide, sans l'ennui d'écrire le code machine réel à la main.


Il est intéressant de GAS, l'assembleur GNU a quelques options d'optimisation limitées pour x86 qui ne sont pas activés par le frontal GCC, même si votre course gcc -O2 . (Vous pouvez exécuter gcc -v ... pour voir comment le front-end appelle d'autres programmes pour faire le vrai travail, avec quelles options.)

Utilisez gcc -Wa,-Os -O3 foo.c bar.S pour activer l'optimisation complète de votre C et les optimisations mineures du judas de GAS pour votre asm. (Ou -Wa,-O2 , malheureusement le manuel est faux et -Os manque certaines des optimisations de -O2 ) -Wa,... passe ... sur la ligne de commande as , tout comme -Wl,... passe les options de l'éditeur de liens via l'interface GCC.

GCC n'active normalement pas les optimisations de as car il alimente normalement le système ASM déjà optimisé de GAS.


Les optimisations de GAS ne concernent que des instructions uniques isolées , et donc uniquement lorsqu'une instruction peut être remplacée par une autre qui a exactement le même effet architectural (à l'exception de la longueur, donc l'effet sur RIP diffère). L'effet micro- architecturale (performance) peut également être différent; c'est le but des optimisations sans taille.

De la as(1) page de manuel , donc noter que ce sont as options, non gcc options.

-O0 | -O | -O1 | -O2 | -Os

Optimisez l'encodage des instructions avec une taille d'instruction plus petite. -O et -O1 codent les instructions de chargement de registre 64 bits avec 64 bits immédiat comme instructions de chargement de registre 32 bits avec 31 bits ou 32 bits immédiats, codent les instructions d'effacement de registre 64 bits
avec des instructions d'effacement de registre 32 bits, encoder des instructions d'effacement de registre vectoriel VEX / EVEX 256 bits / 512 bits avec des instructions d'effacement de registre vectoriel VEX 128 bits, encoder des instructions de chargement / stockage de registre vectoriel EVEX 128 bits / 256 bits avec VEX les instructions de chargement / stockage de registre vectoriel, et codent des instructions logiques d'entiers compressés EVEX 128 bits / 256 bits avec des entiers condensés VEX 128 bits / 256 bits logiques.

-O2 inclut l'optimisation -O1 plus encode des instructions d'effacement de registre vectoriel EVEX 256 bits / 512 bits avec des instructions d'effacement de registre vectoriel EVEX 128 bits. En mode 64 bits, les instructions codées en VEX avec des opérandes de source commutative verront également leurs opérandes de source échangés si cela permet d'utiliser la forme de préfixe VEX à 2 octets au lieu de celle à 3 octets. Certaines formes de ET ainsi que OU avec le même opérande (registre) spécifié deux fois seront également changées en TEST.

-Os inclut -O2 optimisation plus encode 16 bits, 32 bits et
Tests de registre 64 bits avec test immédiat de registre 8 bits avec
immédiat. -O0 désactive cette optimisation.

(re: certaines de ces optimisations de taille d'opérande et de taille de code VEX / EVEX: la mise à zéro de vxorps sur AMD Jaguar / Bulldozer / Zen est-elle plus rapide avec des registres xmm que ymm? et la section vers la fin de ma réponse sur les longueurs d'instructions re: Préfixes VEX 2 contre 3 octets)

Malheureusement, les conflits -O2 et -Os et -Os n'incluent pas réellement tout ce qui vient de -O2 . Vous ne pouvez pas l'obtenir pour optimiser test [re]dx, 1 pour test dl,1 ( -Os ) et optimiser or al,al pour test al,al ( -O2 ).

test r/m32, imm8 n'est pas encodable donc la version edx a besoin d'un imm32.
or al,al est un idiome 8080 obsolète qui n'est pas utile pour x86 , sauf parfois sur la famille P6 pour éviter les blocages de lecture de registre où la réécriture intentionnelle du registre est en fait préférable d'éviter d'allonger la chaîne dep.

0000000000000000 <.text>:
.intel_syntax noprefix

shufps xmm0, xmm0, 0                  # -msse2avx just for fun
   0: c5 f8 c6 c0 00        vshufps xmm0,xmm0,xmm0,0x0
vxorps zmm31, zmm31, zmm31            # avoids triggering AVX512 frequency limit
   5: 62 01 04 00 57 ff     vxorps xmm31,xmm31,xmm31
vxorps zmm1, zmm1, zmm1               # shorter, using VEX
   b: c5 f0 57 c9           vxorps xmm1,xmm1,xmm1
vxorps ymm15, ymm15, ymm15            # missed optimization, could vxorps xmm15, xmm0, xmm0 for a 2-byte VEX and still be a zeroing idiom
   f: c4 41 00 57 ff        vxorps xmm15,xmm15,xmm15
vpxord zmm15, zmm15, zmm15            # AVX512 mnemonic optimized to AVX1, same missed opt for source operands.
  14: c4 41 01 ef ff        vpxor  xmm15,xmm15,xmm15

vpxord ymm3, ymm14, ymm15             # no optimization possible
  19: c4 c1 0d ef df        vpxor  ymm3,ymm14,ymm15
vpxord ymm3, ymm4, ymm15              # reversed operands to allow 2-byte VEX
  1e: c5 85 ef dc           vpxor  ymm3,ymm15,ymm4
vmovd  xmm16, [rdi + 256]         # uses EVEX scaled disp8 because xmm16 requires EVEX anyway
  22: 62 e1 7d 08 6e 47 40  vmovd  xmm16,DWORD PTR [rdi+0x100]
vmovd  xmm0, [rdi + 256]          # could use EVEX scaled disp8 but doesn't even with a -march enabling AVX512
  29: c5 f9 6e 87 00 01 00 00  vmovd  xmm0,DWORD PTR [rdi+0x100]

xor  rax, rax                     # dropped REX prefix
  31: 31 c0                 xor    eax,eax
or  al,al
  33: 84 c0                 test   al,al
cmp dl, 0                         # optimization to test dl,dl not quite legal: different effect on AF
  35: 80 fa 00              cmp    dl,0x0
test rdx, 1                       # partial optimization: only to 32-bit, not 8-bit
  38: f7 c2 01 00 00 00     test   edx,0x1

mov  rax, 1
  3e: b8 01 00 00 00        mov    eax,0x1
mov  rax, -1                         # sign-extended imm8 required
  43: 48 c7 c0 ff ff ff ff  mov    rax,0xffffffffffffffff
mov  rax, 0xffffffff80000000
  4a: 48 c7 c0 00 00 00 80  mov    rax,0xffffffff80000000

.att_syntax
movabs $-1, %rax                    # movabs forces imm64, despite -O2
  51: 48 b8 ff ff ff ff ff ff ff ff    movabs rax,0xffffffffffffffff
movq   $1, %rax                     # but explicit q operand size doesn't stop opt
  5b: b8 01 00 00 00        mov    eax,0x1
movabs $1, %rax
  60: 48 b8 01 00 00 00 00 00 00 00    movabs rax,0x1

Assemblé avec gcc -g -Wa,-msse2avx -Wa,-O2 -Wa,-march=znver2+avx512dq+avx512vl -c foo.s (Pour une raison insensée, as a fait -march= prise en charge des processeurs AMD modernes, mais pour Intel uniquement jusqu'à corei7 et certains Xeon Phi, pas Skylake-avx512 comme le fait GCC.J'ai donc dû activer AVX512 manuellement pour tester cela.

objdump -dwrC -Mintel -S source + démontage

.intel_syntax noprefix

shufps xmm0, xmm0, 0
vxorps zmm31, zmm31, zmm31
vxorps zmm1, zmm1, zmm1
vxorps ymm15, ymm15, ymm15
vpxord zmm15, zmm15, zmm15

vpxord ymm3, ymm14, ymm15
vpxord ymm3, ymm4, ymm15
vmovd  xmm16, [rdi + 256]    # can use EVEX scaled disp8
vmovd  xmm0, [rdi + 256]     # could use EVEX scaled disp8 but doesn't even with a -march enabling AVX512

xor  rax, rax
or  al,al
cmp dl, 0
test rdx, 1

mov  rax, 1
mov  rax, -1
mov  rax, 0xffffffff80000000

.att_syntax
movabs $-1, %rax
movq   $1, %rax
movabs $1, %rax

Donc, malheureusement, même l'activation explicite de AVX512VL et AVX512DQ n'a pas permis à GAS de choisir un encodage EVEX plus court pour vmovd alors qu'un EVEX n'était pas déjà nécessaire. C'est peut-être encore intentionnel: vous voudrez peut-être que certaines fonctions utilisent AVX512, d'autres pour l'éviter. Si vous utilisez les limites d'option ISA pour détecter l'utilisation accidentelle des extensions ISA, vous devrez activer AVX512 pour l'ensemble d'un tel fichier. Il peut être surprenant de trouver l'assembleur utilisant EVEX là où vous ne vous attendiez pas.

Vous pouvez le forcer manuellement avec {evex} vmovd xmm0, [rdi + 256] . (Qui , malheureusement , CCG ne le fait pas lors de la compilation C, où -march=skylake-avx512 ne certainement donner libre cours à utiliser AVX512 instructions partout.)


0 commentaires