
Envoyé par
Obsidian
Imparable pour GCC, mais l'essentiel demeure : il reste difficile de faire proprement une transmission de bits d'un champs à l'autre et surtout, il n'y a pas moyen de l'exprimer proprement en C (ni dans d'autres langages).
En C
En Ada
Et même si on n'utilise pas les champs comme ça,
x = (x & NOT_X_MASK) | ((y & Y_MASK) >> XY_OFFSET);
est très proche de ce que j'écrirais en assembleur.
Une chose qui est plus compliquée, ce sont les rotations (bien que compilateurs les détectent généralement quand elles sont constantes).
Une autre c'est l'utilisation de résultats annexes des opérations qui ont généralement plusieurs résultats en assembleur (carry, partie haute d'une multiplication, reste d'une division, ...).
Ici, on s'est démerdé pour que le résultat final extraie un bit et GCC a été suffisamment performant pour le comprendre et appliquer la bonne technique, mais il n'est pas du tout certain qu'il soit capable de s'y retrouver dans une équation un peu plus compliquée.
Sémantiquement, c'est génant : dire que l'on fait un calcul qui se traduit dans les faits par un décalage de bits ne permet pas du tout d'affirmer clairement que c'est cela qu'on cherche à faire au final.
Bizarre, j'ai quatres expressions qui la traduction directe en C des quatres sémantiques que je vois à la chose de plus bas niveau.
Et puis SHRL $31, c'est ce que je cherche à éviter : ça tient en une instruction mais le nombre de cycles est probablement élevé, et ça ne marche pas sur tous les CPU : bon nombre d'entre eux ne proposent qu'un décalage au niveau du bit et il faut alors 31 opcodes pour arriver à ses fins.
L'optimiseur fait son boulot: tu écris x < 0, il génère un décalage parce que sur cette cible c'est le plus efficace et tu n'es pas content parce que sur une autre cible ça pourrait ne pas convenir?
Partager