Rosetta 2 semble optimiser le code généré

Rendering VT-100 émulant l'affichage DOS
J'écris des moteurs d'échecs, ou d'autres comme pour le Reversi/Othello, depuis plusieurs décennies.
Je suis en train de travailler sur un moteur sorti fin 1994 pour le Minitel, écrit en C-Ansi, Borland C 3.1 pour DOS à l'époque et gcc maintenant pour Posix dans un terminal VT-100, 32 bits pour Pentium [1] à l'époque et 64 bits pour x86 et ARM aujourd'hui.
Du vieux code monothread, c'est à noter.
Et pour m'amuser, sur mon Mac mini M4, je ne fais non pas tourner une version compilée pour ARM mais celle compilée pour x86 64 bits. Le même exact code, grâce à Rosetta 2.
Ce code x86 sort de gcc, avec l'option -O3 : optimisé mais en limitant les risques.
Je viens de m'apercevoir que si en moyenne un cœur Performance du M4 est 3,3 fois plus rapide que chaque cœur de mon MBP 15" 2017, ce qui devrait amener ce code x86 monothread à tourner près de 3 fois plus vite sous ARM via Rosetta 2, il tourne en fait 4 fois plus vite!
Je soupçonne que Rosetta 2 s'est vu amélioré et pourrait utiliser les 16 registres généraux en plus de l'architecture ARM 64 bits pour optimiser le code x86 quand il le transcrit pour nos Mac Apple Silicon.
Ce code simple (non-vectoriel, non fpu) tourne 30% plus vite qu'il le devrait !
Une limitation du Amd64 (ou x86 64 bit, ou x86-64) créé par AMD, c'est que son architecture ne contient que 16 registres généraux (entiers et pointeurs), contre 32 pour ARM 64bits (AArch64).
Ça permet évidemment à nos Mac ARM d'émuler facilement les 16 registres du x86, mais en laisse beaucoup inutilisés, et je pense que Rosetta 2 en profite pour limiter les relectures après écriture dans la pile (les écritures étant probablement conservées).
Une autre optimisation peut être d'éliminer les copies de registres inutiles, puisque en ARM 64 bits les opérations ont souvent 3 opérandes (2 sources et 1 destination), contre 2 en x86 64 bits (1 source, 1 destination).
Par exemple a=b+c en x86 64 bits consiste à "copier" (créer un alias) b dans a puis à lui ajouter c (2 opérations), quand en ARM 64 bits, on ajoute b et c dans a en une seule opération.
L'aliasing de registres (ex-copie) est "gratuite" en x86 maintenant, mais nécessite de décoder une instruction de plus, donc plus de charge coté décodeur (front end) qui est déjà un problème en x86 avec des instructions de longueur variable et le travail pour créer les micro-instructions et macro-instructions depuis les Core™ 2.
Je vais vous revenir avec une comparaison avec du code ARM natif (même compilo mêmes options). Mais ce résultat est très surprenant, Apple fait un travail incroyable sur Rosetta 2 !














