2011-03-03 3 views
5

Je suis intéressé par l'évaluation (partielle) à temps de compilation pour c/C++ (pas avec les paramètres de template comme en C++). Lets considérons le cas suivant (tiré de [1]):Évaluation partielle/spécialisation avec LLVM-gcc ou gcc

double mypower(double x, int n) { 
    int i; 
    double ret = x; 
    for (i = 1; i < n; i++) { 
    ret *= x; 
    } 
    return ret; 
} 

Ensuite, vous appelez cette fonction quelque part dans le code avec:

mypower(x,3); // y varies all the time, 

le compilateur peut optimiser ce (par exemple la boucle déroulage). Certaines fonctions que j'utilise souvent pourraient vraiment bénéficier de cette optimisation (testée manuellement par la fonction spécialisée de création). La présentation [1] décrit un processus dans lequel la fonction est recherchée et est remplacée par une version spécialisée de la fonction. Cela semble fonctionner. Mais il ne semble pas être très universel, le code doit être écrit pour les fonctions qui devraient être remplacées.

La présentation semble être à partir de 2008, je ne pouvais pas trouver quelque chose de plus substantiel que dans cette source. Alors, est-ce que quelque chose s'est amélioré depuis? Je préférerais une sorte d'automatisme, qui fait de même pour toutes les fonctions éventuellement contrôlées par la syntaxe d'attribut (par exemple __attribute__(peval) ...). En outre, je voudrais que la même chose fonctionne pour le code orienté objet, en créant des classes spécialisées pour différents objets ([2] semble suggérer que ce n'est pas possible).

En outre, je voudrais que cette spécialisation ne fonctionne pas seulement pour les constantes trouvées dans le code. Je pense à un programme compilé à LLVM IR (bytecode) peut effectuer les opérations suivantes:

  1. L'exécution du Programme au cours d'une phase d'initialisation dans un interprète, au cours de cette phase d'initialisation du programme pourrait lire une configuration à partir d'un fichier. Après l'initialisation, l'interpréteur est arrêté.

  2. Certaines variables (y compris les variables membres) sont fixées à partir de ce point. Extrayez ces variables (par exemple, marquées par un attribut lors de la compilation).

  3. Créez des fonctions et des classes spécialisées. Cloner ceux-ci dans le bytecode. Exécutez le JIT pour créer le code machine natif.

Ceci est beaucoup que je demande et seulement quelques programmes intensifs de calcul bénéficieraient d'une telle optimisation. Mais certaines personnes doivent travailler là-dessus. Je ne connais probablement pas les bons termes de recherche pour alimenter google.

Note: Veuillez ne pas suggérer des classes de template avec des paramètres non-typés ou une spécialisation manuelle, je le fais déjà. Je préférerais que le compilateur fasse le travail pour moi.

Liens:

[1] Presentation how to partial evaluate in LLVM

[2] Forum message about partial evaluation

+0

Un peu en rapport: http://stackoverflow.com/questions/2940367/what-is-more-efficient-using-pow-to-square-or-just-multiply-it-with-itself/2940800#2940800 –

Répondre

1

Ceci est en grande partie dans le domaine des optimisations interprocédurale. llvm en a quelques uns, en particulier la propagation constante IP qui ne serait utile que si vous utilisiez mypower (x, 3) sur tous les sites d'appel d'une unité de traduction. Ce que vous décrivez est possible, mais n'a pas encore été fait. L'amélioration de la passe IPCP est ce que vous voudriez faire en faisant cloner et spécialiser une fonction sur un site d'appel particulier.Cela pourrait, si vous avez assez d'unités de traduction, provoquer un gros bloat de code, ce qui explique pourquoi les gens n'ont pas vraiment cherché à le faire.

Cela aurait probablement plus d'utilisation au niveau LTO lorsque vous pouvez regarder tous les appels dans un programme.

0

Vous pouvez le faire en utilisant des transformations source-à-source.

Notre DMS Software Reengineering Toolkit pourrait être utilisé pour implémenter ceci. DMS utilise des définitions de langage explicites pour analyser le code source en AST, réimprime les AST en code source, fournit différents types de tables de symboles, capacités de contrôle/flux de données et fournit la capacité de transformation pour permettre la création de transformateurs de code source personnalisés. DMS a many front ends for differenct languages, y compris C et C++ avec des préprocesseurs complets. Pour accomplir votre tâche avec DMS, vous devez utiliser l'analyseur C pour analyser tout le code de votre système (car vous devez inspecter tous les sites d'appel pour les spécialisations partielles). Vous devez définir un moyen de spécifier l'évaluation partielle souhaitée. une façon, comme vous l'avez suggéré, est d'écrire un appel de fonction avec des arguments liés à des constantes, mais vous pouvez généraliser cela à des arguments liés à des expressions arbitraires. Une telle spécification peut être analysée par l'analyseur de modèle de DMS, qui peut traiter des non-terminaux arbitraires, par exemple, un appel de fonction: -} Vous devez parquer ces spécifications quelque part; peut-être en tant que fichier externe supplémentaire, ou en tant que commentaires sur ou à proximité des sites d'appel en question.

Avec une analyse de la spécification d'évaluation partielle, vous devez rechercher le nom de l'appel de fonction pour déterminer la fonction d'intérêt réelle; C'est quelque part dans cette pile de sources et la table des symboles rendra cela facile à trouver. Étant donné un site d'appel avec une spécialisation, l'AST pour la fonction identifiée peut être répliquée et les arguments remplacés; en utilisant probablement seulement un petit nombre de transformations mais vous devez faire attention à la capture d'un argument par une portée lexicale dans la fonction en cours de spécialisation. Se déplacer cela pourrait nécessiter des transformations supplémentaires. Après remplacement d'un nouveau nom et d'une liste d'arguments raccourcie pour la fonction spécifiée, vous devez réinsérer son AST près du site de définition de fonction d'origine, modifier le site d'appel de manière appropriée et cracher les ASTs modifiés. Que vous vouliez ajouter des transformations supplémentaires pour dérouler des boucles pour des cas particuliers, ou tout ce qui vous intéresse, est également pratique. Le DMS a été utilisé pour effectuer des transformations massives sur les codes C et C++; cela semble "techniquement" facile. Il y a la petite question de se familiariser avec un outil comme DMS; il y a une courbe d'apprentissage juste là-bas.