Copie du wikimiroir

Ceci est un miroir du wiki de pascal.chat. La modification, l’historique et la connexion se trouvent là-bas.

Whole Program Optimization/fr

English · Français

Généralités

Traditionnellement, les compilateurs optimisent un programme procédure par procédure, ou au mieux unité de compilation par unité de compilation.

L'optimisation globale de programme, en abrégé OGP, signifie que le compilateur considère toutes les unités de compilation qui compose un programme ou une bibliothèque et les optimise en utilisant une connaissance approfondie de comment ils sont utilisés ensemble dans un cas particulier.

La manière dont fonctionne l'OGP en général est comme suit :

Dans cetaines implémentations, le compilateur génère que sorte de code d'intermédiaire (p.ex., le byte code) et l'éditeur de lien réalise toutes les OGP tout au long de la traduction vers la cible ISA (NdT acronyme non compris). Dans le cas de FPC pourtant, le schéma suivi est celui décrit plus bas.

Principes généraux

Quelques principes généraux ont été suivis lors de la conception de l'implémentation par FPC de l'OGP:

Comment utiliser

Générer le fichier de rétroaction WPO (WPO feedback file)

En tout premier, compilez votre programme (ou bibliothèque) et toutes ses unités comme vous le feriez normalement, mais en compilant, vous ajoutez

bash
-FW/path/to/feedbackfile.wpo -OW<selected_wpo_options>

. Le compilateur va alors, juste après que votre programme a été lié, collecter toutes les informations nécessaires pour effectuer les OGP demandés lors d'une compilation successive, et stocker ces informations dans /path/to/feedbackfile.wpo.

Utiliser le fichier de rétroaction WPO

Pour appliquer réellement les WPO, recompilez le programme/bibliothèque et tout ou partie des unités qu'il utilise en employant

bash
-Fw/path/to/feedbackfile.wpo -Ow<selected_wpo_options>

, pointant ainsi le compilateur vers le fichier de rétroaction généré à l'étape précédente. Le compilateur lira alors l'information collectée sur le programme durant la précédente compilation, et l'utilise durant la compilation en cours des unités et/ou du programme/bibliothèque. Les unités non recompilées durant cette seconde passe ne seront bien évidemment pas optimisées, mais elle fonctionneront encore normalement si elle sont utilisées avec les unités et programme/bibliothèque optimisées.

Exemple concret

L'exemple ci-dessous fait référence à twpo4.pp.

Compilez le programme une première fois, en collectant les rétroactions dans twpo4-1.wpo dans le répertoire courant.

Le compilateur enregistrera les classes créées dans le programme (tchild1 et tchild2), et après l'étape de liaison également que notcalled n'est en fait pas appelée.

Ensuite, enregistrez le code assembleur généré dans twpo4.s1 pour une comparaison ultérieure.

bash
$ ppn37 -FWtwpo4-1.wpo -OWall -CX -XX -Xs- -al twpo4
Free Pascal Compiler version 2.3.1 [2008/12/11] for i386
Copyright (c) 1993-2008 by Florian Klaempfl
Target OS: Darwin for i386
Compiling twpo4.pp
Assembling program
Linking twpo4
66 lines compiled, 0.6 sec
$ mv twpo4.s twpo4.s1

Maintenant compilez le programme une seconde fois, en utilisant l'information dans twpo4-1.wpo et en collectant de nouvelles informations dans twpo4-2.wpo.

Arrivé à ce point, le compilateur sait qu'aucune instance de la classe tbase n'est créée dans le programme et par conséquent il remplace toutes les entrées normales dans sa table de méthodes virtuelles par des références à FPC_ABSTRACTERROR. Les méthodes de classes virtuelles ne peuvent pas être éliminées de cette façon, puisqu'elles peuvent être appelées sans construire d'instance de ce type.

Parce que le compilateur connaît depuis le précédent fichier de rétroaction généré que la procédure notcalled n'est jamais appelée, il enregistrera aussi que seule une instance de tchild1 est créée, comme l'instance tchild2 était seulement créée dans cette procédure notcalled. À des fins d'optimisation, il considérera cependant toujours qu'une instance de tchild2 peut être créée, car à des fins d'optimisation, il utilise toujours le fichier de rétroaction généré lors de la compilation précédente .

Ensuite, nous enregistrons à nouveau le code assembleur généré pour des comparaisons ultérieures.

bash
$ ppn37 -FWtwpo4-2.wpo -OWall -Fwtwpo4-1.wpo -Owall -CX -XX -Xs- -al twpo4
Free Pascal Compiler version 2.3.1 [2008/12/11] for i386
Copyright (c) 1993-2008 by Florian Klaempfl
Target OS: Darwin for i386
Compiling twpo4.pp
Assembling program
Linking twpo4
66 lines compiled, 0.1 sec
$ mv twpo4.s twpo4.s2

Compilez le programme une dernière fois, en utilisant les informations collectées dans twpo4-2.wpo. Cette fois, le compilateur sait que seul une instance de tchild1 est créée, et va par conséquent remplacer l'appel bb.test depuis une méthode virtuelle par une méthode statique (car il sait que même si le type de bb est tbase, en pratique il ne peut être qu'un tchild1 car aucune instance de tbase ou autre instance de classe descendant de tbase n'est créée.

bash
$ ppn37 -Fwtwpo4-2.wpo -Owall -CX -XX -al twpo4
Free Pascal Compiler version 2.3.1 [2008/12/11] for i386
Copyright (c) 1993-2008 by Florian Klaempfl
Target OS: Darwin for i386
Compiling twpo4.pp
Assembling program
Linking twpo4
66 lines compiled, 0.1 sec

Maintenant, regardons les différences entre les fichiers assembleur générés. Après la première recompilation :

bash
$ diff -u twpo4.s1 twpo4.s2
diff
--- twpo4.s1    2008-12-11 18:59:55.000000000 +0100
+++ twpo4.s2    2008-12-11 19:00:15.000000000 +0100
@@ -214,15 +214,15 @@
    .long   0,0,0
    .long   FPC_EMPTYINTF
    .long   0
-   .long   _SYSTEM_TOBJECT_$__DESTROY
+   .long   FPC_ABSTRACTERROR
    .long   _SYSTEM_TOBJECT_$__NEWINSTANCE$$TOBJECT
-   .long   _SYSTEM_TOBJECT_$__FREEINSTANCE
-   .long   _SYSTEM_TOBJECT_$__SAFECALLEXCEPTION$TOBJECT$POINTER$$LONGINT
-   .long   _SYSTEM_TOBJECT_$__DEFAULTHANDLER$formal
-   .long   _SYSTEM_TOBJECT_$__AFTERCONSTRUCTION
-   .long   _SYSTEM_TOBJECT_$__BEFOREDESTRUCTION
-   .long   _SYSTEM_TOBJECT_$__DEFAULTHANDLERSTR$formal
-   .long   _P$PROGRAM_TBASE_$__TEST
+   .long   FPC_ABSTRACTERROR
+   .long   FPC_ABSTRACTERROR
+   .long   FPC_ABSTRACTERROR
+   .long   FPC_ABSTRACTERROR
+   .long   FPC_ABSTRACTERROR
+   .long   FPC_ABSTRACTERROR
+   .long   FPC_ABSTRACTERROR
    .long   0

 .const_data

Comme vous pouvez le voir, toutes les références aux méthodes virtuelles dans la VMT de tbase ont été retirées, puisque le compilateur sait qu'elles ne peuvent pas être réféencées. Cela permet à l'éditeur de liens de jeter ces méthodes si elles ne sont référencées nulle part ailleurs non plus.

Dans notre exemple, c'est seulement vrai pour tbase.test.

Maintenant regardons l'effet de la seconde recompilation:

bash
$ diff -u twpo4.s2 twpo4.s
diff
--- twpo4.s2    2008-12-11 19:00:15.000000000 +0100
+++ twpo4.s 2008-12-11 19:00:29.000000000 +0100
@@ -103,9 +103,7 @@
    movl    %eax,-4(%ebp)
 # [54] bb.test;
    movl    -4(%ebp),%eax
-   movl    -4(%ebp),%edx
-   movl    (%edx),%edx
-   call    *80(%edx)
+   call    L_P$PROGRAM_TCHILD1_$__TEST$stub
 # [55] bb.free;
    movl    -4(%ebp),%eax
    call    L_SYSTEM_TOBJECT_$__FREE$stub
@@ -139,10 +137,7 @@
 # [63] bb.test;
    movl    L_U_P$PROGRAM_BB$non_lazy_ptr-Lj2(%ebx),%eax
    movl    (%eax),%eax
-   movl    L_U_P$PROGRAM_BB$non_lazy_ptr-Lj2(%ebx),%edx
-   movl    (%edx),%edx
-   movl    (%edx),%edx
-   call    *80(%edx)
+   call    L_P$PROGRAM_TCHILD1_$__TEST$stub
 # [64] a:=2;
    movl    L_U_P$PROGRAM_A$non_lazy_ptr-Lj2(%ebx),%eax
    movl    $2,(%eax)

Comme vous pouvez le voir, les deux appels de méthode virtuelle à bb.test (un dans la procédure notcalled, jamais appelée, et un dans le programme principal) ont été remplacé par des appels à tchild1.test.

Remarquez que vous pourriez aussi recompiler la RTL pour ce programme particulier, si vous voulez.

Quand utiliser

Puisque l'optimisation globale de programme demande de multiples compilation, il est recommandable de limiter son utilisation aux versions de livraison finale.

Gardez aussi à l'esprit qu'une fois que l'unité a été compilée en utilisant wpo pour un programme particulier, elle doit être à nouveau compilée pour un autre programme.

Optimisation disponible de programme entier

Toutes les optimisations

paramètre

:

bash
-OWall/-Owall

effet
Active toutes les optimisations globlales de programme décrites ci-dessus.

limitations
Les limitations de toutes les optimisations décrites ci-dessus.

Dévirtualisation de programme entier

paramètre

:

bash
-OWdevirtcalls/-Owdevirtcalls

effet
Transforme les appels de méthode virtuelle en appels de méthode statique quand le compilateur peut déterminer que l'appel de méthode virtuelle ira toujours à la même méthode statique. Cela rend le code plus petit et plus rapide. En général, il s'agit principalement d'une optimisation permettant d'autres optimisations, car elle facilite l'analyse du programme en réduisant le flux de contrôle indirect.

limitations

Optimiser la table des méthodes virtuelles

paramètre

:

bash
-OWoptvmts/-Owoptvmts

effet
Cette optimisation examine quels types de classe peuvent être instanciés et quelles méthodes virtuelles peuvent être appelées dans un programme, et sur la base de ces informations, il remplace les entrées de la VMT qui ne peuvent jamais être appelées avec des références vers FPC_ABSTRACTERROR. Ce qui signifie que de telles méthodes, qu'elles ne soient appelées directement via un appel inherited depuis une classe/objet enfant, peuvent être retirées par l'éditeur de lien. Cela a peu ou pas d'effet que la vitesse, mais peut aider à réduire la taille du code.

limitations

Vivacité de symbole (Symbol liveness)

paramètre

:

bash
-OWsymbolliveness/-Owsymbolliveness

effet
Ce paramètre ne réalise aucune optimisation en lui-même. Il dit simplement au compilateur d'enregistrer quelles fonctions/procédures seront conservées dans le programme final. Lors d'une passe wpo ultérieure, le compilateur peut alors ignorer les fonctions/procédures aussi loin que le wpo est concerné (p.ex. si une classe particulière est seulement construite dans une procédure inutilisée, alors en ignorant cette procédure, on peut améliorer l'efficacité des deux optimisations précédentes).

limitations

Format de fichier de rétroaction WPO

Cette information est principalement intéressante si vous voulez ajouter des données externes au fichier de rétroaction WPO, p.ex. depuis un outil de profilage. Si vous êtes juste un utilisateur de la fonctionnalité WPO, vous pouvez ignorer ce qui suit.

Le fichier consiste en commentaires et un nombre de sections. Les commentaires sont des lignes qui commencent avec un "#". Chaque section commence avec "%" (signe pourcent et espace) suivi du nom de la section (p.ex. "% contextinsensitive_devirtualization"). Après cela, jusqu'à la fin du fichier ou jusqu'à la ligne suivante commençant par "%", suit d'abord une description lisible par l'homme du format de cette section (dans les commentaires), puis le contenu de la section elle-même.

Il n'y a pas de règles sur l'apparence du contenu d'une section, sauf que les lignes commençant par "#" sont réservées pour les commentaires et les lignes commençant par "%" sont réservés aux marqueurs de section.


From the Free Pascal wiki, page "Whole Program Optimization/fr", as it stood on 2022-08-06 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Version 1, dernière modification par WikiArchive .