Précédent : Résultats nouveaux Remonter :
Résultats nouveaux
Suivant : Gestion de la mémoire
Une analyse de dépendances pour programmes récursifs manipulant des structures des données en arbre a tout d'abord été proposée [[22]]. Puis, une analyse des définitions visibles à granularité très fine (par instance d'instruction) a été mise au point pour une classe assez large de programmes récursifs et/ou itératifs manipulant des tableaux. Ce travail a été présenté dans [[16]], présentation qui a été récompensée par le prix IEEE ``Best Student Presentation''. Ces deux travaux sont en cours d'unification [[29]].
Ce travail, en coopération avec Jens Knoop de l'université de Passau, Allemagne (à présent à l'université de Dortmund) a eu pour but de comparer la terminologie, les buts, les outils et la précision de diverses analyses des définitions visibles existantes. Ce travail [[30]] est soumis à publication.
Le formalisme Array SSA a été présenté récemment comme une extension aux tableaux du célèbre formalisme SSA. Notre étude a tout d'abord cherché à détailler quel degré d'expansion était utile [[18]], puis à montrer en quoi les analyses de définitions visibles par instances sont importantes pour l'obtention de codes Array SSA efficaces [[17]].
Dans les compilateurs, l'analyse de flot de données est traditionnellement réalisée sur le programme source et exploitée dans les différentes étapes menant à la génération du code. L'analyse de code assembleur, qui a des applications évidentes en reverse engineering, nous intéresse pour deux raisons. La première est l'analyse a priori des performances d'un code assembleur, la seconde est le réordonnancement des instructions et la réallocation de registres dans le code assembleur; cet aspect revêt une importance accrue avec le développement des architectures de type VLIW, pour lesquelles la portabilité des codes reste une question ouverte. Ces différents aspects requièrent une étude fine des conflits possibles entre différents accès mémoire. Cette étude est réalisée en collaboration avec l'Université de Iéna (Allemagne) et a débuté en 1997 par un travail de bibliographie. Une première implémentation a été réalisée dans l'environnement SALTO (System for Assembly Language Tools and Optimisation), développé dans le projet CAPS de l' IRISA[[11]]. Cette action fait l'objet d'un projet PROCOPE démarrant en janvier 1999.
Dans cette étude [[21]], réalisée en commun avec l'UPC de Barcelone, on analyse les instructions participant au calcul des conditions de branchement. On montre que la fonction correspondante possède souvent des propriétés de régularité assimilables à une boucle. On explique également les principales causes de mauvaises prédictions des branchements conditionnels. Ensuite, on développe une architecture de processeur superscalaire qui exploite ces propriétés en sautant des itérations de la boucle afin d'anticiper le calcul du branchement.
Ce travail [[40]] est destiné à comprendre les performances d'un code sur une architecture à parallélisme d'instructions et hiérarchie mémoire. En général, les performances globales d'un code semblent peu satisfaisantes comparées aux capacités des machines. La question est de savoir si ce problème est dû à une mauvaise utilisation des ressources du processeur ou s'il est intrinsèque au programme considéré. Dans un processus d'optimisation, aussi bien automatique que manuel, les questions qui se posent sont : est-ce que le code est bien optimisé? Ne peut-on pas optimiser d'avantage ? Faut-il arrêter là ou bien chercher encore à améliorer la performance?
Nous analysons le code source du programme et essayons d'évaluer une borne supérieure des performances que l'on peut obtenir, que nous appelons performance optimiste. Ceci est fait en examinant en premier lieu le flot de données du programme, pour calculer a priori le plus petit temps d'exécution possible du calcul. Pour cela, nous simulons un changement de l'ordre des opérations du programme. Le programme est instrumenté pour extraire au vol (durant l'exécution du programme) les opérations réellement exécutées (nous éliminons les opérations de contrôle et les branchements non exécutés). Ces opérations sont ensuite réordonnancées grâce à un algorithme par liste, ce qui permet d'avoir un nouvel ordonnancement au plus tôt qui donne ainsi une borne optimiste à la performance du programme. L'ordonnancement est calculé en se basant sur trois contraintes.