7
votes

MIPS (curiosité) Un moyen plus rapide de nettoyer un registre?

Quel est le moyen le plus rapide de nettoyer un registre (= 0) dans l'assemblage MIPS?

Quelques exemples: xxx

Quelle est la plus efficace?


0 commentaires

6 Réponses :


1
votes

Étant donné que toutes ces instructions prennent un seul cycle de pipeline, il ne devrait pas y avoir beaucoup de différence entre eux.

Le cas échéant, je m'attendais à ce que le xor $ t0, $ t0, $ t0 soit le meilleur pour la vitesse, car il n'utilise aucun autre registre, les gardant gratuitement pour d'autres valeurs et éventuellement réduire la conflit de fichiers du registre.

La méthode XOR est également traitée comme une idiome spécifique sur certains processeurs, ce qui lui permet d'utiliser encore moins de ressources (par exemple, de ne pas avoir besoin de faire l'opération Alu XOR.


1 commentaires

Les concepteurs de la CPU optimisent X86 CPU pour l'idiome de zéro XOR, car il a la plus petite taille de code dans le codage variable de X86. Cela à son tour a fait XOR-Zeroing plus efficace que MOV EAX, 0 Même à part de la taille de code . Comme ce n'est pas un facteur pour MIPS, je ne m'attendrais pas à ce que les CPU de MIPS dépenseraient des transistors détectant que les deux opérandes sont identiques pour XOR ou SUB. J'attendrais aussi que la lecture 0 $ est au moins aussi bon marché pour lire tout autre REG.



0
votes

sur la plupart des implémentations de l'architecture MIPS, toutes ces personnes devraient offrir la même performance. Cependant, on peut envisager un système Superscalar qui pourrait exécuter plusieurs instructions simultanément, à condition qu'ils utilisent des unités internes distinctes. Je n'ai aucun exemple réel de système MIPS qui fonctionne comme ça, mais c'est ainsi que cela se passe sur les systèmes PowerPC. Un xor $ t0, $ t0, $ t0 OPCODE serait exécuté sur l'unité "Computions entier" (car il s'agit d'un xor ) pendant que déplace $ T0, 0 $ n'utiliserait pas cette unité; conceptuellement, ce dernier pourrait être exécuté en parallèle avec un autre opcode qui effectue des calculs entier.

en bref, si vous trouvez un système où toutes les façons que vous listez ne sont pas aussi efficaces, alors je m'attendrais à ce que le déplace $ t0, $ 0 < / code> méthode pour être le plus efficace.


4 commentaires

Je pense que dans la plupart des implémentations MOV est également sur l'unité INTEGER - MOV x, y est généralement synonyme de ou x, y, 0 . C'était le cas sur l'EE quand même.


Pas de famille avec MIPS, mais est l'instruction de déplacement plus longtemps? Sur X86, des instructions plus longues peuvent souvent finir de fonctionner plus longtemps que le nombre de tiques "officiel" en raison de problèmes de mémoire / pipeline. Les instructions courtes sont préférées ...


@Brian Knoblauch Nope - Tout le point de MIPS (et RISC en général) est que chaque instruction est exactement la même longueur.


Je ne dirais pas que c'est le "point entier", mais c'est en effet l'un des avantages des architectures de RISC (bien qu'il s'agisse d'un peu moins prononcé avec l'ajout de sous-ensembles de 16 bits tels que Mips16e et le pouce).



0
votes

Cela dépend probablement de quelles autres instructions seront dans le pipeline en même temps: lorsque le registre a été utilisé lorsqu'il sera utilisé ensuite et quelles unités internes sont actuellement utilisées.

Je ne connais pas la structure de pipeline d'un processeur MIPS en particulier, mais votre compilateur devrait être et je m'attendrais à ce qu'il choisirait celui qui serait le plus rapide d'une séquence de code donnée.


1 commentaires

Il existe des options qui ne dépendent pas de l'ancienne valeur du registre, le meilleur choix que pas dépend du code environnant. ou $ T1, $ zéro, $ zéro est probablement toujours aussi bon que tout autre choix sur n'importe quel MIPS. Il est probablement sûr de supposer qu'un MIPS Superscalar peut exécuter addu ou ou sur n'importe quelle unité d'exécution afin que la pression portuaire à terme, le code environnant ne comporte probablement pas d'importance.



5
votes

Dans de nombreuses implémentations de MIPS, ces ops compilent tous les deux à la même instruction, car généralement «MOV $ A, $ B 'est un idiome pour ou $ A, $ B, $ 0 et Li $ R, x est sténographique pour ori $ r, $ 0, x : xxx

et ceux-ci se dérouleront tous les deux sur le même pipeline, Être équivalent architectural: xxx

et dans chaque mise en œuvre de RISC, l'ajoute est sur le même tuyau que XOR / et / NOR / etc.

Fondamentalement, il est tout particulier à la mise en œuvre d'une puce particulière, mais ils doivent tous être une horloge unique. Si la puce est hors de commande, li ou et x, 0 $ 0, $ 0 peut être le plus rapide car ils minimisent de fausses dépendances sur d'autres registres.


1 commentaires

Si MIPS est comme ARM ou PPC, Les instructions sont architecturales pour se propager Une dépendance sur leurs registres d'entrée (pour des raisons liées à memory_order_consume ) . Donc, vous voulez absolument utiliser 0 $ comme votre seul registre source d'entrée, quel que soit ce que vous faites avec cela. IDK Si des implémentations de MIPS hors de commande reconnaissent des idiomes de zéro spécifiques et même d'utiliser une unité d'exécution ( comme x86 cpus do )



2
votes

Je semble vous rappeler que 0 $ était créé spécifiquement pour ce cas, je m'attendrais donc à ce que MOVE $ T0 $ 0 devrait être recommandé pour effacer un registre. Mais je n'ai pas fait MIPS pendant presque 10 ans ...


0 commentaires

0
votes

Vous pouvez simplement utiliser le registre $ zéro comme référence et écrire sa valeur 0 ou 0B00000000, dans le registre que vous souhaitez effacer.

Si vous travaillez avec des flotteurs ou des doubles, vous pouvez simplement déclarer Un flotteur et une double variable dans .Data en tant que 0.0 et écrivez-le dans le registre que vous souhaitez effacer quand vous le souhaitez. P>

Exemple: P>

.data
     PI:       .float   3.14
     clear:    .float   0.0
.text
     main:
          lwc1 $f0, PI
          lwc1 $f0, clear

     li $v0, 10
     syscall


1 commentaires

Ne serait-il pas tout aussi efficace ni plus efficace de transférer ou de convertir $ zéro au FPU avec une instruction alu, au lieu de faire une charge de la mémoire? Ou sont des instructions de transfert GP-> FP lentement?