Difference between revisions of "Whole Program Optimization/fr"

From Lazarus wiki
m (Format de fichier de retour WPO)
m (Format de fichier de rétroaction WPO)
 
(10 intermediate revisions by the same user not shown)
Line 30: Line 30:
  
 
=== Exemple concret ===
 
=== Exemple concret ===
The example below refers to [http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/test/opt/twpo4.pp?revision=12341&pathrev=12341 <tt>twpo4.pp</tt>].
+
L'exemple ci-dessous fait référence à [http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/test/opt/twpo4.pp?revision=12341&pathrev=12341 <tt>twpo4.pp</tt>].
  
Compile the program a first time, collecting feedback in <syntaxhighlight lang="bash" enclose="none">twpo4-1.wpo</syntaxhighlight> in the current directory. v
+
Compilez le programme une première fois, en collectant les rétroactions dans <syntaxhighlight lang="bash" enclose="none">twpo4-1.wpo</syntaxhighlight> dans le répertoire courant.
The compiler will record which classes are created in the program (<tt>tchild1</tt> and <tt>tchild2</tt>), and after the linking step also that the <syntaxhighlight lang="pascal" enclose="none">notcalled</syntaxhighlight> procedure is in fact not called.
 
  
Afterwards, save the generated assembler code in <syntaxhighlight lang="bash" enclose="none">twpo4.s1</syntaxhighlight> for later comparison.
+
Le compilateur enregistrera les classes créées dans le programme (<tt>tchild1</tt> et <tt>tchild2</tt>), et après l'étape de liaison également que <syntaxhighlight lang="pascal" enclose="none"> notcalled </syntaxhighlight> n'est en fait pas appelée.
 +
 
 +
Ensuite, enregistrez le code assembleur généré dans <syntaxhighlight lang="bash" enclose="none">twpo4.s1</syntaxhighlight> pour une comparaison ultérieure.
  
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
Line 49: Line 50:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Now compile the program a second time, using the information in <syntaxhighlight lang="bash" enclose="none">twpo4-1.wpo</syntaxhighlight> and collecting new information in <syntaxhighlight lang="bash" enclose="none">twpo4-2.wpo</syntaxhighlight>.
+
Maintenant compilez le programme une seconde fois, en utilisant l'information dans <syntaxhighlight lang="bash" enclose="none">twpo4-1.wpo</syntaxhighlight> et en collectant de nouvelles informations dans <syntaxhighlight lang="bash" enclose="none">twpo4-2.wpo</syntaxhighlight>.
At this point, the compiler knows that no instance of the <syntaxhighlight lang="pascal" enclose="none">tbase</syntaxhighlight> class is created in the program, and therefore it replaces all regular entries in its virtual method table with references to <syntaxhighlight lang="pascal" enclose="none">FPC_ABSTRACTERROR</syntaxhighlight>.
+
 
Virtual class methods cannot be eliminated this way, since they can also be called without constructing an instance of this type.
+
Arrivé à ce point, le compilateur sait qu'aucune instance de la classe <syntaxhighlight lang="pascal" enclose="none">tbase</syntaxhighlight> 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 à <syntaxhighlight lang="pascal" enclose="none">FPC_ABSTRACTERROR</syntaxhighlight>.
 +
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.
  
Because the compiler knows from the previously generated feedback file that the <syntaxhighlight lang="pascal" enclose="none">notcalled</syntaxhighlight> procedure is never called, it will also record that only an instance of <syntaxhighlight lang="pascal" enclose="none">tchild1</syntaxhighlight> is created, as the <syntaxhighlight lang="pascal" enclose="none">tchild2</syntaxhighlight> instance was only created inside this <syntaxhighlight lang="pascal" enclose="none">notcalled</syntaxhighlight> procedure.
+
Parce que le compilateur connaît depuis le précédent fichier de rétroaction généré que la procédure <syntaxhighlight lang="pascal" enclose="none">notcalled</syntaxhighlight> n'est jamais appelée, il enregistrera aussi que seule une instance de <syntaxhighlight lang="pascal" enclose="none">tchild1</syntaxhighlight> est créée, comme l'instance <syntaxhighlight lang="pascal" enclose="none">tchild2</syntaxhighlight> était seulement créée dans cette procédure <syntaxhighlight lang="pascal" enclose="none">notcalled</syntaxhighlight>.
For optimization purposes, it will however still consider that an instance of <syntaxhighlight lang="pascal" enclose="none">tchild2</syntaxhighlight> may be created, as for optimization purposes it still uses the feedback file generated during the previous compilation.
+
À des fins d'optimisation, il considérera cependant toujours qu'une instance de <syntaxhighlight lang="pascal" enclose="none"> tchild2 </syntaxhighlight> 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 .
  
Afterwards, we again save the generated assembler code for later comparisons.
+
Ensuite, nous enregistrons à nouveau le code assembleur généré pour des comparaisons ultérieures.
  
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
Line 70: Line 72:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Compile the program a final time, using the information collected in <syntaxhighlight lang="bash" enclose="none">twpo4-2.wpo</syntaxhighlight>.
+
Compilez le programme une dernière fois, en utilisant les informations collectées dans <syntaxhighlight lang="bash" enclose="none">twpo4-2.wpo</syntaxhighlight>.
This time, the compiler knows that only a <syntaxhighlight lang="pascal" enclose="none">tchild1</syntaxhighlight> instance is created, and will therefore turn the <syntaxhighlight lang="pascal" enclose="none">bb.test</syntaxhighlight> call from a virtual method call into a static method call (because it knows that even though the type of <syntaxhighlight lang="pascal" enclose="none">bb</syntaxhighlight> is <syntaxhighlight lang="pascal" enclose="none">tbase</syntaxhighlight>, in practice it can only be a <syntaxhighlight lang="pascal" enclose="none">tchild1</syntaxhighlight> since no <syntaxhighlight lang="pascal" enclose="none">tbaseh</syntaxhighlight> or other <syntaxhighlight lang="pascal" enclose="none">tbase</syntaxhighlight>-descendent class instance is created).
+
Cette fois, le compilateur sait que seul une instance de <syntaxhighlight lang="pascal" enclose="none">tchild1</syntaxhighlight> est créée, et va par conséquent remplacer l'appel <syntaxhighlight lang="pascal" enclose="none">bb.test</syntaxhighlight> depuis une méthode virtuelle par une méthode statique (car il sait que même si le type de <syntaxhighlight lang="pascal" enclose="none">bb</syntaxhighlight> est <syntaxhighlight lang="pascal" enclose="none">tbase</syntaxhighlight>, en pratique il ne peut être qu'un <syntaxhighlight lang="pascal" enclose="none">tchild1</syntaxhighlight> car aucune instance de <syntaxhighlight lang="pascal" enclose="none">tbase</syntaxhighlight> ou autre instance de classe descendant de <syntaxhighlight lang="pascal" enclose="none">tbase</syntaxhighlight> n'est créée.
  
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
Line 84: Line 86:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Now, let's have a look at the differences between the generated assembler files. After the first recompilation:
+
Maintenant, regardons les différences entre les fichiers assembleur générés. Après la première recompilation :
  
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
Line 118: Line 120:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
As you can see, all references to the virtual methods in the virtual method table of <syntaxhighlight lang="pascal" enclose="none">tbase</syntaxhighlight> have been removed, since the compiler knows they can never be referenced.
+
Comme vous pouvez le voir, toutes les références aux méthodes virtuelles dans la VMT de <syntaxhighlight lang="pascal" enclose="none">tbase</syntaxhighlight> ont été retirées, puisque le compilateur sait qu'elles ne peuvent pas être réféencées.
This allows the linker to throw away these methods if they are not referenced anywhere else either.
+
Cela permet à l'éditeur de liens de jeter ces méthodes si elles ne sont référencées nulle part ailleurs non plus.
In our example, that is only true for <syntaxhighlight lang="pascal" enclose="none">tbase.test</syntaxhighlight>.
+
 
 +
Dans notre exemple, c'est seulement vrai pour <syntaxhighlight lang="pascal" enclose="none">tbase.test</syntaxhighlight>.
  
Now let's look at the effect of the second recompilation:
+
Maintenant regardons l'effet de la seconde recompilation:
  
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
Line 155: Line 158:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
As you can see, the two virtual method calls to ''bb.test'' (one inside the never called ''notcalled'' procedure, and one in the main program) have been replaced with calls to ''tchild1.test''.
+
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''.
  
Note that you could also recompile the entire run time library for this particular program, if you want.
+
Remarquez que vous pourriez aussi recompiler la RTL pour ce programme particulier, si vous voulez.
  
 
== Quand utiliser ==
 
== Quand utiliser ==
  
Since whole program optimization requires multiple compilations, it is advisable to only use this functionality when compiling a final release version.
+
Puisque l'optimisation globale de programme demande de multiples compilation, il est recommandable de limiter son utilisation aux versions de livraison finale.
  
Also keep in mind that once a unit has been compiled using ''wpo'' for a particular program, it has to be recompiled if you want to use it in another program.
+
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 ==
 
== Optimisation disponible de programme entier ==
 
=== Toutes les optimisations ===
 
=== Toutes les optimisations ===
; parameter
+
; paramètre
 
: <syntaxhighlight lang="bash">
 
: <syntaxhighlight lang="bash">
 
-OWall/-Owall
 
-OWall/-Owall
 
</syntaxhighlight>
 
</syntaxhighlight>
; effect
+
; effet
: Enables all whole program optimizations described below.
+
: Active toutes les optimisations globlales de programme décrites ci-dessus.
 
; limitations
 
; limitations
: The combined limitations of all optimizations described below.
+
: Les limitations de toutes les optimisations décrites ci-dessus.
  
 
=== Dévirtualisation de programme entier ===
 
=== Dévirtualisation de programme entier ===
; parameter
+
; paramètre
 
: <syntaxhighlight lang="bash">
 
: <syntaxhighlight lang="bash">
 
-OWdevirtcalls/-Owdevirtcalls
 
-OWdevirtcalls/-Owdevirtcalls
 
</syntaxhighlight>
 
</syntaxhighlight>
; effect
+
; effet
: Changes virtual method calls into normal (static) method calls when the compiler can determine that a virtual method call will always go to the same static method. This makes such code both smaller and faster. In general, it's mainly an enabling optimization for other optimizations, because it makes the program easier to analyse due to the fact that it reduces indirect control flow.
+
: 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
 
; limitations
* The current implementation is context-insensitive. This means that the compiler only looks at the program as a whole and determines for each class type which methods can be devirtualised, rather than that it looks at each call statement and the surrounding code to determine whether or not this call can be devirtualised;
+
* L'implémentation actuelle est insensible au contexte. Cela signifie que le compilateur ne regarde que le programme dans son ensemble et détermine pour chaque type de classe quelles méthodes peuvent être dévirtualisées, plutôt que de regarder chaque instruction d'appel et le code environnant pour déterminer si cet appel peut être dévirtualisé ou non;
* The current implementation does not yet devirtualise interface method calls (not when calling them via an interface instance, nor when calling them via a class instance).
+
* L'implémentation actuelle ne dévirtualise pas encore les appels de méthode d'interface (ni lors de leur appel via une instance d'interface, ni lors de leur appel via une instance de classe).
 
 
  
 
=== Optimiser la table des méthodes virtuelles ===
 
=== Optimiser la table des méthodes virtuelles ===
; parameter
+
; paramètre
 
: <syntaxhighlight lang="bash">
 
: <syntaxhighlight lang="bash">
 
-OWoptvmts/-Owoptvmts
 
-OWoptvmts/-Owoptvmts
 
</syntaxhighlight>
 
</syntaxhighlight>
; effect
+
; effet
: This optimization looks at which class types can be instantiated and which virtual methods can be called in a program, and based on this information it replaces virtual method table (VMT) entries that can never be called with references to FPC_ABSTRACTERROR. This means that such methods, unless they are called directly via an ''inherited'' call from a child class/object, can be removed by the linker. It has little or no effect on speed, but can help reducing code size.
+
: 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
 
; limitations
* Methods that are ''published'', or getters/setters of published properties, can never be optimized in this way, because they can always be referred to and called via the RTTI (which the compiler cannot detect).
+
* Les méthodes qui sont ''published'', ou les getters/setters de propriétés publiées, ne peuvent jamais être optimisées de cette façon car elles peuvent toujours être référencées via la RTTI (ce que le compilateur ne peut pas détecter).
* Such optimizations are not yet done for virtual class methods (but it should not be that difficult to add)
+
* De telles optimisations ne sont pas encore faites pour les méthodes virtuelles de classe (mais cela ne devrait pas être difficile à ajouter).
  
=== Vivacité de symbole ===
+
=== Vivacité de symbole (Symbol liveness)===
; parameter
+
; paramètre
 
: <syntaxhighlight lang="bash">
 
: <syntaxhighlight lang="bash">
 
-OWsymbolliveness/-Owsymbolliveness
 
-OWsymbolliveness/-Owsymbolliveness
 
</syntaxhighlight>
 
</syntaxhighlight>
; effect
+
; effet
: This parameter does not perform any optimization by itself. It simply tells the compiler to record which functions/procedures were kept by the linker in the final program. During a subsequent ''wpo'' pass, the compiler can then ignore the removed functions/procedures as far as ''wpo'' is concerned (e.g., if a particular class type is only constructed in one unused procedure, then ignoring this procedure can improve the effectiveness of the previous two optimizations).
+
: 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
 
; limitations
* This optimization requires that the <tt>nm(1)</tt> utility is installed on the system. For Linux binaries, <tt>objdump(1)</tt> will also work. In the future, this information could also be extracted from the internal linker for the platforms that it supports.
+
* Cette optimisation demande que l'utilitaire <tt>nm(1)</tt> soit installé sur le système. Pour les binaires linux, <tt>objdump(1)</tt> marchera aussi. Dans le futur, cette information pourra être extraite aussi de l'éditeur de lien interne pour les plateformes qui le supporte.
* Collecting information for this optimization (using -OWsymbolliveness) requires that smart linking is enabled  (-XX) and that symbol stripping is disabled (-Xs-). When only using such previously collected information (using -OwSymbolliveness or -Owall), these limitations do not apply.
+
* La collection d'information pour cette optimisation (en utilisant -OWsymbolliveness) demande que la liaison intelligente soit activée (-XX) et que l'élimination de symbole ne le soit pas (-Xs-). Lorsque vous utilisez uniquement ces informations précédemment collectées (en utilisant -OwSymbolliveness ou -Owall), ces limitations ne s'appliquent pas.
  
 
== Format de fichier de rétroaction WPO ==
 
== Format de fichier de rétroaction WPO ==
This information is mainly interesting if you want to add external data to the WPO feedback file, e.g. from a profiling tool. If you are just a user of the WPO functionality, you can ignore what follows.
+
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.
  
The file consists of comments and a number of sections.
+
Le fichier consiste en commentaires et un nombre de sections.
Comments are lines that start with a <syntaxhighlight lang="bash" enclose="none">#</syntaxhighlight>.
+
Les commentaires sont des lignes qui commencent avec un "<tt>#</tt>".
Each section starts with <syntaxhighlight lang="bash" enclose="none">% </syntaxhighlight> (percent sign and space) followed by the name of the section (e.g.,<tt>% contextinsensitive_devirtualization</tt>).
+
Chaque section commence avec "<tt>% </tt>" (signe pourcent et espace) suivi du nom de la section (p.ex. "<tt>% contextinsensitive_devirtualization</tt>").
After that, until either the end of the file or until the next line starting with with "<tt>% </tt>", first a human readable description follows of the format of this section (in comments), and then the contents of the section itself.
+
Après cela, jusqu'à la fin du fichier ou jusqu'à la ligne suivante commençant par "<tt>% </tt>", 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.
  
There are no rules for how the contents of a section should look, except that lines starting with <syntaxhighlight lang="bash" enclose="none">#</syntaxhighlight> are reserved for comments and lines starting with <syntaxhighlight lang="bash" enclose="none">% </syntaxhighlight> are reserved for section markers.
+
Il n'y a pas de règles sur l'apparence du contenu d'une section, sauf que les lignes commençant par "<tt>#</tt>" sont réservées pour les commentaires et les lignes commençant par "<tt>% </tt>" sont réservés aux marqueurs de section.

Latest revision as of 13:15, 15 December 2020

English (en) français (fr)

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 :

  • vous compilez le programme normalement, en disant au compilateur d'enregistrer divers bits d'information dans un fichier de rétroaction.
  • vous recompilez the programme (et facultativement toutes les unités qu'il utilise) avec les OGP, en fournissant le fichier de rétroaction comme une entrée supplémentaire au compilateur.

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:

  • Toute l'information nécessaire pour générer le fichier de rétroaction OGP pour un programme est toujours enregistré dans les fichiers PPU. Ce qui signifie que vous pouvez utiliser une RTL pour l'OGP (même si la RTL elle-même ne sera alors pas optimisée, votre programme et ses unités peuvent être correctement optimisés car le compilateur sait tout ce qu'il doit savoir sur toutes les unités RTL);
  • Le fichier de rétroaction OGP généré est du texte brut. L'idée est qu'il devrait facile d'inspecter ce fichier à la main et d'y ajouter de l'information produite par des outils externes si désiré (p.exe. des informations de profilage);
  • L'implémentation du sous-système OGP dans le compilateur est très modulaire, donc il devrait être facile d'y adjoindre des fournisseurs d'informations OGP additionnels ou de choisir à l'exécution entre différents forunisseurs d'informations pour la même sorte d'information. En même temps, l'interaction avec le reste du compilateur est réduite au strict minimum pour améliorer la maintenabilité;
  • Il est possible de générer un fichier de rétroaction WPO tout en en utilisant un autre comme entrée. Dans certains cas, l'utilisation de ce deuxième fichier de rétroaction comme entrée lors d'une troisième compilation peut encore améliorer les résultats.

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

-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

-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.

$ 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.

$ 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.

$ 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 :

$ diff -u twpo4.s1 twpo4.s2
--- 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:

$ diff -u twpo4.s2 twpo4.s
--- 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
-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
-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
  • L'implémentation actuelle est insensible au contexte. Cela signifie que le compilateur ne regarde que le programme dans son ensemble et détermine pour chaque type de classe quelles méthodes peuvent être dévirtualisées, plutôt que de regarder chaque instruction d'appel et le code environnant pour déterminer si cet appel peut être dévirtualisé ou non;
  • L'implémentation actuelle ne dévirtualise pas encore les appels de méthode d'interface (ni lors de leur appel via une instance d'interface, ni lors de leur appel via une instance de classe).

Optimiser la table des méthodes virtuelles

paramètre
-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
  • Les méthodes qui sont published, ou les getters/setters de propriétés publiées, ne peuvent jamais être optimisées de cette façon car elles peuvent toujours être référencées via la RTTI (ce que le compilateur ne peut pas détecter).
  • De telles optimisations ne sont pas encore faites pour les méthodes virtuelles de classe (mais cela ne devrait pas être difficile à ajouter).

Vivacité de symbole (Symbol liveness)

paramètre
-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
  • Cette optimisation demande que l'utilitaire nm(1) soit installé sur le système. Pour les binaires linux, objdump(1) marchera aussi. Dans le futur, cette information pourra être extraite aussi de l'éditeur de lien interne pour les plateformes qui le supporte.
  • La collection d'information pour cette optimisation (en utilisant -OWsymbolliveness) demande que la liaison intelligente soit activée (-XX) et que l'élimination de symbole ne le soit pas (-Xs-). Lorsque vous utilisez uniquement ces informations précédemment collectées (en utilisant -OwSymbolliveness ou -Owall), ces limitations ne s'appliquent pas.

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.