Sign in Join
Wiki copytemporary

Whole Program Optimization/fr: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Whole Program Optimization/fr

OldNewLine
1+## Généralités
2+
3+Traditionnellement, les compilateurs optimisent un programme procédure par procédure, ou au mieux unité de compilation par unité de compilation.
4+
5+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.
6+
7+La manière dont fonctionne l'OGP en général est comme suit :
8+
9+- vous compilez le programme normalement, en disant au compilateur d'enregistrer divers bits d'information dans un *fichier de rétroaction*.
10+- 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.
11+
12+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.
13+
14+## Principes généraux
15+
16+Quelques principes généraux ont été suivis lors de la conception de l'implémentation par FPC de l'OGP:
17+
18+- 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);
19+- 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);
20+- 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é;
21+- 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.
22+
23+## Comment utiliser
24+
25+### Générer le fichier de rétroaction WPO (WPO feedback file)
26+
27+En tout premier, compilez votre programme (ou bibliothèque) et toutes ses unités comme vous le feriez normalement, mais en compilant, vous ajoutez
28+
29+``` bash
30+-FW/path/to/feedbackfile.wpo -OW<selected_wpo_options>
31+```
32+
33+. 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`.
34+
35+### Utiliser le fichier de rétroaction WPO
36+
37+Pour appliquer réellement les WPO, recompilez le programme/bibliothèque et tout ou partie des unités qu'il utilise en employant
38+
39+``` bash
40+-Fw/path/to/feedbackfile.wpo -Ow<selected_wpo_options>
41+```
42+
43+, 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.
44+
45+### Exemple concret
46+
47+L'exemple ci-dessous fait référence à [`twpo4.pp`](http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/test/opt/twpo4.pp?revision=12341&pathrev=12341).
48+
49+Compilez le programme une première fois, en collectant les rétroactions dans `twpo4-1.wpo` dans le répertoire courant.
50+
51+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.
52+
53+Ensuite, enregistrez le code assembleur généré dans `twpo4.s1` pour une comparaison ultérieure.
54+
55+``` bash
56+$ ppn37 -FWtwpo4-1.wpo -OWall -CX -XX -Xs- -al twpo4
57+Free Pascal Compiler version 2.3.1 [2008/12/11] for i386
58+Copyright (c) 1993-2008 by Florian Klaempfl
59+Target OS: Darwin for i386
60+Compiling twpo4.pp
61+Assembling program
62+Linking twpo4
63+66 lines compiled, 0.6 sec
64+$ mv twpo4.s twpo4.s1
65+```
66+
67+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`.
68+
69+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.
70+
71+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 .
72+
73+Ensuite, nous enregistrons à nouveau le code assembleur généré pour des comparaisons ultérieures.
74+
75+``` bash
76+$ ppn37 -FWtwpo4-2.wpo -OWall -Fwtwpo4-1.wpo -Owall -CX -XX -Xs- -al twpo4
77+Free Pascal Compiler version 2.3.1 [2008/12/11] for i386
78+Copyright (c) 1993-2008 by Florian Klaempfl
79+Target OS: Darwin for i386
80+Compiling twpo4.pp
81+Assembling program
82+Linking twpo4
83+66 lines compiled, 0.1 sec
84+$ mv twpo4.s twpo4.s2
85+```
86+
87+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.
88+
89+``` bash
90+$ ppn37 -Fwtwpo4-2.wpo -Owall -CX -XX -al twpo4
91+Free Pascal Compiler version 2.3.1 [2008/12/11] for i386
92+Copyright (c) 1993-2008 by Florian Klaempfl
93+Target OS: Darwin for i386
94+Compiling twpo4.pp
95+Assembling program
96+Linking twpo4
97+66 lines compiled, 0.1 sec
98+```
99+
100+Maintenant, regardons les différences entre les fichiers assembleur générés. Après la première recompilation :
101+
102+``` bash
103+$ diff -u twpo4.s1 twpo4.s2
104+```
105+
106+``` diff
107+--- twpo4.s1 2008-12-11 18:59:55.000000000 +0100
108++++ twpo4.s2 2008-12-11 19:00:15.000000000 +0100
109+@@ -214,15 +214,15 @@
110+ .long 0,0,0
111+ .long FPC_EMPTYINTF
112+ .long 0
113+- .long _SYSTEM_TOBJECT_$__DESTROY
114++ .long FPC_ABSTRACTERROR
115+ .long _SYSTEM_TOBJECT_$__NEWINSTANCE$$TOBJECT
116+- .long _SYSTEM_TOBJECT_$__FREEINSTANCE
117+- .long _SYSTEM_TOBJECT_$__SAFECALLEXCEPTION$TOBJECT$POINTER$$LONGINT
118+- .long _SYSTEM_TOBJECT_$__DEFAULTHANDLER$formal
119+- .long _SYSTEM_TOBJECT_$__AFTERCONSTRUCTION
120+- .long _SYSTEM_TOBJECT_$__BEFOREDESTRUCTION
121+- .long _SYSTEM_TOBJECT_$__DEFAULTHANDLERSTR$formal
122+- .long _P$PROGRAM_TBASE_$__TEST
123++ .long FPC_ABSTRACTERROR
124++ .long FPC_ABSTRACTERROR
125++ .long FPC_ABSTRACTERROR
126++ .long FPC_ABSTRACTERROR
127++ .long FPC_ABSTRACTERROR
128++ .long FPC_ABSTRACTERROR
129++ .long FPC_ABSTRACTERROR
130+ .long 0
131+
132+ .const_data
133+```
134+
135+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.
136+
137+Dans notre exemple, c'est seulement vrai pour `tbase.test`.
138+
139+Maintenant regardons l'effet de la seconde recompilation:
140+
141+``` bash
142+$ diff -u twpo4.s2 twpo4.s
143+```
144+
145+``` diff
146+--- twpo4.s2 2008-12-11 19:00:15.000000000 +0100
147++++ twpo4.s 2008-12-11 19:00:29.000000000 +0100
148+@@ -103,9 +103,7 @@
149+ movl %eax,-4(%ebp)
150+ # [54] bb.test;
151+ movl -4(%ebp),%eax
152+- movl -4(%ebp),%edx
153+- movl (%edx),%edx
154+- call *80(%edx)
155++ call L_P$PROGRAM_TCHILD1_$__TEST$stub
156+ # [55] bb.free;
157+ movl -4(%ebp),%eax
158+ call L_SYSTEM_TOBJECT_$__FREE$stub
159+@@ -139,10 +137,7 @@
160+ # [63] bb.test;
161+ movl L_U_P$PROGRAM_BB$non_lazy_ptr-Lj2(%ebx),%eax
162+ movl (%eax),%eax
163+- movl L_U_P$PROGRAM_BB$non_lazy_ptr-Lj2(%ebx),%edx
164+- movl (%edx),%edx
165+- movl (%edx),%edx
166+- call *80(%edx)
167++ call L_P$PROGRAM_TCHILD1_$__TEST$stub
168+ # [64] a:=2;
169+ movl L_U_P$PROGRAM_A$non_lazy_ptr-Lj2(%ebx),%eax
170+ movl $2,(%eax)
171+```
172+
173+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*.
174+
175+Remarquez que vous pourriez aussi recompiler la RTL pour ce programme particulier, si vous voulez.
176+
177+## Quand utiliser
178+
179+Puisque l'optimisation globale de programme demande de multiples compilation, il est recommandable de limiter son utilisation aux versions de livraison finale.
180+
181+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.
182+
183+## Optimisation disponible de programme entier
184+
185+### Toutes les optimisations
186+
187+paramètre
188+
189+:
190+
191+``` bash
192+-OWall/-Owall
193+```
194+
195+effet
196+Active toutes les optimisations globlales de programme décrites ci-dessus.
197+
198+limitations
199+Les limitations de toutes les optimisations décrites ci-dessus.
200+
201+### Dévirtualisation de programme entier
202+
203+paramètre
204+
205+:
206+
207+``` bash
208+-OWdevirtcalls/-Owdevirtcalls
209+```
210+
211+effet
212+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.
213+
214+limitations
215+
216+- 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;
217+- 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).
218+
219+### Optimiser la table des méthodes virtuelles
220+
221+paramètre
222+
223+:
224+
225+``` bash
226+-OWoptvmts/-Owoptvmts
227+```
228+
229+effet
230+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.
231+
232+limitations
233+
234+- 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).
235+- De telles optimisations ne sont pas encore faites pour les méthodes virtuelles de classe (mais cela ne devrait pas être difficile à ajouter).
236+
237+### Vivacité de symbole (Symbol liveness)
238+
239+paramètre
240+
241+:
242+
243+``` bash
244+-OWsymbolliveness/-Owsymbolliveness
245+```
246+
247+effet
248+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).
249+
250+limitations
251+
252+- 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.
253+- 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.
254+
255+## Format de fichier de rétroaction WPO
256+
257+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.
258+
259+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.
260+
261+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.
262+
263+---
264+*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](/wiki-contact).*

Back to history