En essayant de comprendre gcc avec l'option -fomit-frame-pointer
J'ai demandé à Google de me donner la signification de la gcc
option -fomit-frame-pointer
, qui me redirige vers la déclaration ci-dessous.
-fomit-frame-pointer
Ne pas garder le pointeur de cadre dans un registre pour les fonctions qui n'en a pas besoin. Cela évite les instructions pour enregistrer, à configurer et à restaurer l'image des pointeurs; il rend également un supplément de registre disponible dans de nombreuses fonctions. Il rend également impossible de débogage sur certaines machines.
Que par ma connaissance de chaque fonction, une activation de l'enregistrement va être créé dans la pile de la mémoire du processus à garder toutes les variables locales et certains plus d'informations. J'espère que ce pointeur de cadre moyen de l'adresse de l'activation de l'enregistrement d'une fonction.
Dans ce cas, quels sont les types de fonctions, pour lesquelles il n'a pas besoin de garder le pointeur de cadre dans un registre? Si je peux obtenir cette information, je vais essayer de la conception de la nouvelle fonction sur la base que (si possible) parce que si le pointeur de l'image n'est pas conservé dans les registres, des instructions seront omis dans le binaire. Cela va vraiment améliorer les performances sensiblement dans une application où il y a beaucoup de fonctions.
- Devoir de débogage juste un crash dump de code qui a été compilé avec cette option sera suffisant pour vous rendre à l'accise cette option à partir de votre makefiles. Elle ne supprime pas toutes les instructions btw, il donne juste l'optimiseur d'un s'inscrire pour travailler avec pour le stockage.
- En fait, c'est assez utile pour la release. Avoir deux cibles dans un Makefile -
Release
etDebug
est en fait très utile, prendre cette option comme un exemple.
Vous devez vous connecter pour publier un commentaire.
La plupart des petites fonctions n'ont pas besoin d'un pointeur de l'image - les grandes fonctions PEUVENT avoir besoin d'un.
C'est vraiment sur la façon dont le compilateur gère pour suivre la façon dont la pile est utilisée, et où les choses sont sur la pile (les variables locales, les arguments passés à la fonction en cours et les arguments de se préparer à une fonction sur le point d'être appelé). Je ne pense pas que c'est facile à caractériser les fonctions qui ont besoin ou n'a pas besoin d'un pointeur de cadre (techniquement, PAS de fonction doit avoir un pointeur de l'image - c'est plus une affaire de "si le compilateur considère nécessaire de réduire la complexité du code").
Je ne pense pas que tu doivent "s'efforcer de faire les fonctions pas un pointeur de l'image" dans le cadre de votre stratégie de codage - comme je l'ai dit, les fonctions simples n'en avez pas besoin, donc, d'utiliser
-fomit-frame-pointer
, et vous obtiendrez un registre plus disponible pour l'allocateur de registres, et enregistrer 1-3 instructions d'entrée/sortie de fonctions. Si votre fonction a besoin d'un pointeur de l'image, c'est parce que le compilateur décide que c'est mieux que de ne pas utiliser un pointeur de l'image. Ce n'est pas un objectif pour les fonctions sans un pointeur de l'image, c'est un but pour avoir un code qui fonctionne à la fois correctement et rapidement.Note que "ne pas avoir un pointeur de cadre" devrait donner de meilleurs performances, mais ce n'est pas une balle magique qui donne d'énormes améliorations - et surtout pas sur x86-64, qui a déjà 16 registres pour commencer. Sur 32-bit x86, comme il n'a que 8 registres, dont l'un est le pointeur de pile, et l'autre, comme le pointeur de cadre moyen de 25% de s'inscrire-espace est pris. Pour changer cela, à 12,5% est tout à fait une amélioration. Bien sûr, la compilation 64 bits aidera beaucoup trop.
alloca
qui se déplace le pointeur de pile par une quantité variable. Pointeur de cadre omission n'faciliter le débogage beaucoup plus difficile. Les variables locales sont plus difficiles à localiser et les traces de pile sont beaucoup plus difficiles à reconstruire sans un pointeur de cadre pour les aider. Aussi, l'accès aux paramètres peuvent obtenir de plus cher, car ils sont loin du sommet de la pile et peut exiger plus cher modes d'adressage.alloca
[qui le fait? - Je suis sûr à 99% que je n'ai jamais écrit un code qui utilisealloca
] ouvariable size local arrays
[qui est la forme moderne dealloca
], alors le compilateur PEUT toujours décider que l'utilisation de frame-pointer est une meilleure option, car les compilateurs sont écrit à ne pas suivre aveuglément les options, mais vous donner le meilleur choix.alloca
: ils sont jetés dès que vous quittez le cadre dans lequel elles sont déclarées, alors quealloca
l'espace n'est libérée que lorsque vous quittez la fonction. Cela fait VLA beaucoup plus facile à suivre quealloca
, je pense.-fomit-frame-pointer
sur par défaut pour x86-64.alloca
'ed l'espace) est inconnu à compiler de temps. Habituellement, le compilateur va utiliser le pointeur de l'image pour obtenir l'adresse des variables locales, si la taille de la frame de pile ne change pas, il peut localiser fixe à un décalage à partir du pointeur de pile.Ce est tout au sujet de la BP/EBP/RBP s'inscrire sur les plates-formes Intel. Ce registre par défaut segment de pile (n'a pas besoin d'un préfixe d'accès au segment de pile).
( source - http://css.csail.mit.edu/6.858/2017/readings/i386/s02_03.htm )
Puisque sur la plupart des plates-formes 32 bits, les données de segment et le segment de pile sont les mêmes, cette association de EBP/RBP avec la pile n'est plus un problème. Donc, est sur les plates-formes 64 bits: Le x86-64 architecture, introduit par AMD en 2003, a largement abandonné la prise en charge de la segmentation en mode 64 bits: quatre des registres de segment: CS, SS, DS, ES et sont forcés à 0. Ces circonstances de x86 32-bit et 64-bit plateformes signifie essentiellement que EBP/RBP registre peut être utilisé, sans préfixe, dans les instructions du processeur que l'accès à la mémoire.
De sorte que le compilateur option vous écrit à ce sujet permet à l'BP/EBP/RBP être utilisé pour d'autres moyens, par exemple, avoir une variable locale.
Par “Cela évite les instructions pour enregistrer, à configurer et à restaurer l'image des pointeurs” s'entend, en évitant le code suivant à l'entrée de chaque fonction:
ou la
enter
instruction, qui a été très utile sur des processeurs Intel 80286 et 80386.Aussi, avant le retour de la fonction, le code suivant est utilisé:
ou la
leave
instruction.Outils de débogage peut parcourir la pile de données et l'utilisation de ces poussé EBP données lors de la localisation d'
call sites
, c'est à dire d'afficher les noms de la fonction et les arguments dans l'ordre où ils ont été appelés de façon hiérarchique.Les programmeurs peuvent avoir des questions sur la pile d'images pas dans un terme général (qu'il est une entité unique dans la pile qui sert juste d'un appel de fonction et garde l'adresse de retour, les arguments et les variables locales), mais dans un sens étroit – lorsque le terme
stack frames
est mentionné dans le contexte des options du compilateur. À partir du compilateur, point de vue, un cadre de pile est juste le d'entrée et de sortie code de la routine, qui pousse un point d'ancrage pour la pile, qui peut également être utilisé pour le débogage et la gestion des exceptions. Outils de débogage peut parcourir la pile de données et l'utilisation de ces ancres pour le traçage, lors de la localisation d'call sites
dans la pile, c'est à dire d'afficher les noms de la fonction dans l'ordre où ils ont été appelés de façon hiérarchique.C'est pourquoi il est très important à comprendre pour un programmeur de ce qu'est un cadre de pile est en fonction des options de compilation – car le compilateur ne peut contrôler si pour générer ce code ou pas.
Dans certains cas, la trame de pile (d'entrée et de sortie code de la routine) peut être omise par le compilateur, et les variables seront directement accessibles via le pointeur de pile (SP/ESP/RER) plutôt que la pratique de base du pointeur (BP/ESP/RER).
Conditions pour un compilateur pour omettre la pile d'images pour certaines fonctions peuvent être différents, par exemple: (1) la fonction est une feuille de la fonction (c'est à dire la fin de l'entité qui ne fait pas appel à d'autres fonctions); (2) aucune des exceptions sont utilisés; (3) pas de routines sont appelées avec les paramètres sur la pile; (4) la fonction n'a pas de paramètres.
Omettant pile d'images (d'entrée et de sortie code de la routine) peut rendre le code plus petit et plus rapide, mais peut aussi affecter négativement les débogueurs capacité à remonter la chaîne des données dans la pile et de l'afficher pour le programmeur. Ce sont les options du compilateur que de déterminer dans quelles conditions une fonction doit satisfaire afin que le compilateur prix avec le frame de pile d'entrée et de sortie de code. Par exemple, un compilateur peut avoir des options pour ajouter l'entrée et à la sortie de code pour les fonctions dans les cas suivants: (a) toujours b) jamais, (c) en cas de besoin (préciser les conditions).
Le retour de généralités particularités: si vous utilisez la
-fomit-frame-pointer
compilateur GCC option, vous pouvez gagner à la fois l'entrée et la sortie du code de la routine, et sur un registre (sauf s'il est déjà activé par défaut, soit par lui-même ou implicitement par d'autres options, dans ce cas, vous êtes déjà bénéficié d'un gain à l'aide de l'EBP/RBP vous inscrire et aucun gain supplémentaire sera obtenu en spécifiant explicitement cette option si elle est déjà sur implicitement). Veuillez noter, toutefois, que dans les 16-bits et 32-bits modes, le registre BP n'a pas une capacité d'accès de 8 pièces peu comme AX a (AL et AH).Depuis cette option, en plus de permettre au compilateur d'utiliser EBP comme un usage général s'inscrire dans optimisations, empêche également la génération d'entrée et de sortie de code pour le frame de pile qui complique le débogage -- c'est pourquoi la La documentation de GCC indique explicitement (exceptionnellement en soulignant avec un style audacieux) que l'activation de cette option rend le débogage impossible sur certaines machines
S'il vous plaît être conscient que d'autres options du compilateur, liés à débogage ou d'optimisation, peut implicitement tourner la
-fomit-frame-pointer
option on ou OFF.Je n'ai trouvé aucune information officielle à gcc.gnu.org sur la façon de faire d'autres options affectent
-fomit-frame-pointer
sur les plates-formes x86,le https://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Optimize-Options.html seuls les états suivants:
De sorte qu'il n'est pas clair à partir de la documentation en soi si
-fomit-frame-pointer
sera activée si vous venez de compiler avec un seul-O
option sur plate-forme x86. Il peut être testé empiriquement, mais dans ce cas il n'y a aucun engagement de la GCC aux développeurs de ne pas modifier le comportement de cette option à l'avenir sans préavis.Cependant, Peter Cordes l'a souligné dans les commentaires qu'il y a une différence pour les paramètres par défaut de la
-fomit-frame-pointer
entre x86-16 plates-formes et x86-32/64 plates-formes.Cette option --
-fomit-frame-pointer
-- est également pertinents pour le Compilateur Intel C++ 15.0, non seulement de la GCC:Pour le Compilateur Intel, cette option a un alias
/Oy
.Voici ce que Intel a écrit à ce sujet:
S'il vous plaît être conscient que la citation ci-dessus n'est pertinente que pour les Intel C++ 15 compilateur, pas de GCC.
gcc -m16
existe, mais c'est une drôle de spécial qui le rend fondamentalement 32 bits de code qui s'exécute en mode 16 bits à l'aide de préfixes de tous sur la place. Notez également que-fomit-frame-pointer
a été activé par défaut depuis des années sur x86-m32
, et plus long que sur x86-64 (-m64
).