Nombre minimum théorique de registres pour un ordinateur moderne?

10

J'ai suivi un cours sur les compilateurs dans mes études de premier cycle dans lequel nous avons écrit un compilateur qui compile les programmes source dans un langage Java similaire à un langage d'assemblage de jouets (pour lequel nous avions un interprète). Dans le projet, nous avons fait quelques hypothèses sur la machine cible étroitement liées aux "vrais" exécutables natifs, notamment:

  • une pile d'exécution, suivie par un registre de pointeur de pile dédié ("SP")
  • un tas pour l'allocation dynamique d'objets, suivi par un registre de pointeur de tas dédié ("HP")
  • un registre de compteur de programme dédié ("PC")
  • la machine cible a 16 registres
  • les opérations sur les données (par opposition aux sauts, par exemple) sont des opérations de registre à registre

Lorsque nous sommes arrivés à l'unité sur l'utilisation de l'allocation des registres comme optimisation, je me suis demandé: quel est le nombre minimum théorique de registres pour une telle machine? Vous pouvez voir par nos hypothèses que nous avons utilisé cinq registres (SP, HP, PC, plus deux pour utilisation comme stockage pour les opérations binaires) dans notre compilateur. Bien que les optimisations telles que l'allocation de registres puissent certainement utiliser plus de registres, existe-t-il un moyen de s'en sortir avec moins tout en conservant des structures comme la pile et le tas? Je suppose qu'avec l'adressage des registres (opérations de registre à registre), nous avons besoin d' au moins deux registres, mais en avons-nous besoin de plus de deux?

BlueBomber
la source
Un "pointeur de tas" semble une idée étrange. Parce que contrairement à la pile, le tas n'est pas LIFO et ne se réduit pas à la sémantique push / pop. Vous devriez plutôt voir l'allocation de mémoire dynamique comme des appels à des routines malloc / free.
Yves Daoust

Réponses:

14

Si vous autorisez l'accès direct à la mémoire par adresse mémoire, vous n'avez pas besoin de "registres" car vous pouvez utiliser des emplacements mémoire à la place. Par exemple, la mémoire à l'emplacement 0 peut être le compteur de programme, à l'emplacement 1, nous avons le pointeur de pile, etc. Mais c'est de la triche.

Donc, pour nous empêcher de tricher, supposons qu'il n'y ait pas d'accès direct à la mémoire, car nous pourrions utiliser des emplacements de mémoire fixes comme registres. Ensuite, nous pouvons nous en sortir avec deux registres, un compteur de programme et un pointeur de pile, comme expliqué dans l'article Wikipedia sur les machines à pile . La pile est uniquement accessible via le pointeur de pile, et le programme est uniquement accessible via le compteur de programme.

Une autre possibilité consiste à utiliser des guichets automatiques. Une machine à deux compteurs est Turing complète, c'est-à-dire qu'elle peut calculer n'importe quelle machine Turing. Ceci est à nouveau joliment expliqué dans l'article Wikipedia sur machines à sous .

Andrej Bauer
la source
Merci pour la réponse! L'article sur les machines à empiler mentionne, cependant, que la machine est capable d'accéder directement à la mémoire (pour effectuer des opérations sur les éléments de pile les plus élevés et repousser le résultat), de sorte que cela continue de tricher, non? Quant à la machine à compteur, j'ai lu cet article. J'ai également lu une preuve similaire de TC d'un 2-CM, mais les deux impliquent effectivement de stocker toute la RAM dans deux registres, ce qui me semble encore plus comme de la triche.
BlueBomber
Eh bien, à un moment donné, il ne triche plus. Les opérations de pile ne trichent pas, tant qu'elles interdisent l'accès direct à un emplacement fixe en mémoire. Il est correct de pouvoir, par exemple, faire pivoter les trois éléments les plus hauts de la pile. Votre question est un peu étrange, de toute façon, donc ça ne paie pas de devenir obsédé par ce qui est et ne triche pas.
Andrej Bauer
Merci encore pour la réponse. Chaque fois que le sujet concerne des limites théoriques, la tricherie est encore moins acceptable! Cela ne signifie pas pour autant que ce n'est pas instructif. Le point où ce n'est pas de la triche, c'est quand, eh bien, il n'y a pas de tricherie, je suppose. J'ai trouvé votre réponse initiale informative, mais le problème est que notre modèle chevauche tous les modèles Turing Machine, Counter Machine et Stack Machine, et compte tenu de nos hypothèses (y compris un nombre fini de registres finis et aucun accès direct à la mémoire), pouvons-nous passer avec seulement deux registres?
BlueBomber
1
Je trouve la question étrange car il est difficile de cerner des concepts du monde réel tels que processeur, registre, accès à la mémoire, etc., mais vous avez besoin de ceux-ci pour pouvoir prouver quoi que ce soit. Le résultat final sera donc que tout ce que vous prouvez est facile à prouver, mais cela dépend beaucoup de la façon dont vous formalisez la question (quelle est votre notion théorique de "processeur", "registre", "mémoire", etc.).
Andrej Bauer
1
Un manuel de compilation ne nous permet pas de prouver beaucoup, du moins pas au sens mathématique du mot "prouver". Vous devez aller plus loin dans la formalisation du matériel pour arriver à quelque chose qui permettra la preuve . Quoi qu'il en soit, nous séparons les cheveux, et je vous ai déjà donné ma meilleure réponse.
Andrej Bauer
1

L'architecture PIC qui a été introduite par General Instruments dans les années 1970 et qui est toujours utilisée aujourd'hui avait les registres suivants:

W register (not addressible)
01    Timer/Counter
02    Program Counter
03    Status
04    File-Select Register
05-07 One register for each I/O port
08-1F General-purpose registers/"memory"

Une instruction typique lira un registre, effectuera un calcul en utilisant la valeur lue et W, puis stockera le résultat du calcul dans W ou dans le registre qui a été lu. L'un des calculs disponibles donne "la valeur lue en ignorant W"; un autre est "prendre W, en ignorant la valeur lue". Les modèles de bits qui correspondraient à "lire XX, puis prendre W, en ignorant la valeur lue et stocker le résultat dans W" sont utilisés pour NOP ainsi que pour une variété d'instructions spéciales.

Pour permettre les calculs d'adresse, l'unité d'exécution du processeur surveillera les instructions qui codent une adresse de 00 et substituera le contenu du fichier File Register à l'adresse.

Bien que devoir fournir toutes les valeurs via le registre W puisse être un goulot d'étranglement, l'architecture PIC a un ensemble de travail plus grand que les autres architectures utilisant le même mot d'instruction de longueur. Sur le PIC16C54 (toujours fabriqué aujourd'hui, et très similaire aux PIC des années 1970), les instructions sont de 12 bits. Sur de nombreuses autres parties 16Cxx ou 16Fxx, les instructions ont une longueur de 14 bits et peuvent accéder directement à un espace d'adressage de 128 octets. Si l'ensemble de travail d'un programme correspond bien à l'ensemble de travail de l'ensemble d'instructions, une instruction comme "total + = valeur", où "total" et "valeur" sont de type unsigned char, serait compilée pour:

movf  value,w
addwf total,f

Sur quelque chose comme l'ARM, même si l'on a un registre préchargé avec l'adresse de base de ses variables, le code serait plus comme:

ldr    r0,[r7+value]
ldr    r1,[r7+total]
add    r1,r1,r0
str    r1,[r7+total]

Dans de nombreux cas, un compilateur serait en mesure d'éviter de faire des chargements et des stockages à chaque opération, mais sur quelque chose comme le PIC, les avantages d'un plus grand ensemble de travail peuvent parfois l'emporter sur les limitations d'avoir à passer par W tout le temps.

supercat
la source