At -O3
, gcc will emit:
int mul37(int a) { return a*37; }
leal (%rdi,%rdi,8), %eax
leal (%rdi,%rax,4), %eax
ret
C'est en utilisant 37 = 9*4 + 1
Vous êtes en bonne compagnie en ne notant pas celui-ci, cependant: clang récent utilisera normalement 2 instructions lea
au lieu d'un imul
(par ex. pour *15
), mais il manque celui-ci et utilise:
imull $37, %edi, %eax
ret
Il ne fait *21
avec le même schéma que les usages gcc, comme 5*4 + 1
. (Clang3.6 et toujours utilisé plus tôt imul
moins qu'il y ait une alternative simple instruction shl
ou lea
)
CPI et MSVC utilisent également imul, mais ils ne semblent pas aimer à l'aide en utilisant 2 lea
instructions, de sorte que le imul
est "à dessein" là-bas.
Voir le lien godbolt pour une variété de multiplicateurs avec gcc7.2 vs clang5.0. Il est intéressant d'essayer gcc -m32 -mtune=pentium
ou même pentium3
pour voir combien d'instructions supplémentaires gcc voulait utiliser à l'époque. Bien que P2/P3 ait une latence de 4 cycles pour imul r, r, i
, c'est un peu fou. Pentium a 9 imul cycle et pas de OOO pour cacher la latence, il est donc logique d'essayer de l'éviter.
mtune=silvermont
devrait probablement être prêt à remplacer 32 bits imul
avec une seule instruction, car il a une latence/débit de 3 1c cycle de multiplication, mais décodage est souvent le goulot d'étranglement (selon Agner Fog, http://agner.org/optimize/). Vous pouvez même envisager imul $64, %edi, %eax
(ou d'autres puissances de 2) au lieu de mov
/shl
, car imul-immédiat est une copie-et-multiplier.
Paradoxalement, gcc
manque le x45
cas, et utilise imul
, tandis que clang utilise 2 lea
s. Supposons qu'il est temps de déposer des rapports de bug d'optimisation manquée. Si 2 leas sont meilleurs que 1 imul, ils devraient être utilisés autant que possible.
Avez-vous essayé de demander à un compilateur? https://godbolt.org/g/nMbujJ. Astuce: vous devez changer plus que les facteurs d'échelle. Le 2ème LEA utilise l'entrée originale + le premier résultat LEA. –
De plus, compte tenu de votre choix de registres, cela ressemble à l'utilisation d'un code 64 bits pour l'ABI System V. Il n'y a aucun avantage à utiliser un préfixe de remplacement de taille d'adresse pour obtenir des modes d'adressage 32 bits en mode 64 bits. Il est toujours prudent de laisser 'lea' tronquer un mode d'adressage 64 bits sur 32 bits. https://stackoverflow.com/questions/34377711/which-2s-complement-integer-operations-can-be-used-with-zeroing-high-bits-in –