Clang réciproque à 1 optimisations

Après une discussion avec des collègues, je me suis demandé si clang optimiserait deux divisions, avec une réciproque de 1, une division.

const float x = a / b; //x not used elsewhere const float y = 1 / x;

Théoriquement, clang pourrait optimiser const float y = b / a si x est utilisé uniquement comme valeur de pas temporaire, non?

Voici l’entrée et la sortie d’un cas de test simple: https://gist.github.com/Jiboo/d6e839084841d39e5ab6 (dans les deux sorties, vous pouvez voir qu’il effectue les deux divisions, au lieu d’optimiser)

Cette question connexe est derrière ma compréhension et semble se concentrer uniquement sur la raison pour laquelle une instruction spécifique n’est pas utilisée, alors que dans mon cas, c’est l’optimisation qui n’est pas effectuée: pourquoi GCC ou Clang n’optimisent-ils pas l’inverse lors de l’utilisation rapide -math

Merci, JB.

Non, Clang ne peut pas faire ça.

Mais d’abord, pourquoi utilisez-vous float? float a une précision de six chiffres, double a 15. Sauf si vous avez une bonne raison, que vous pouvez expliquer, utilisez double.

1 / (a ​​/ b) en arithmétique en virgule flottante n’est pas la même chose que b / a. Ce que le compilateur doit faire est dans le premier cas:

  1. Diviser a par b
  2. Arrondir le résultat au nombre en virgule flottante le plus proche
  3. Diviser 1 par le résultat
  4. Arrondissez le résultat au nombre en virgule flottante le plus proche.

Dans le second cas:

  1. Diviser b par a.
  2. Arrondissez le résultat au nombre en virgule flottante le plus proche.

Le compilateur ne peut modifier le code que s’il est garanti que le résultat est identique. Si le rédacteur du compilateur ne peut pas produire de preuve mathématique indiquant que le résultat est identique, il ne peut pas modifier le code. Il y a deux opérations d’arrondi dans le premier cas, arrondissant des nombres différents, il est donc peu probable que le résultat puisse être garanti identique.

Le compilateur ne pense pas comme un mathématicien. Là où vous pensez que simplifier l’expression est sortingvialement mathématique, le compilateur a beaucoup d’autres choses à prendre en compte. En fait, il est fort probable que le compilateur soit beaucoup plus intelligent que le programmeur et qu’il en sache beaucoup plus sur le standard C.

Quelque chose comme ceci est probablement ce qui passe par “l’esprit” du compilateur d’optimisation:

  • Ah, ils ont écrit a / b mais n’utilisent que x à un endroit, nous n’avons donc pas à allouer cette variable sur la stack. Je vais l’enlever et utiliser un registre de CPU.
  • Hmm, littéral entier 1 divisé avec une variable float. OK, nous devons invoquer l’équilibre ici avant toute chose et transformer ce littéral en un flottant 1.0f .
  • Le programmeur compte sur moi pour générer du code contenant l’inexactitude potentielle de la virgule flottante impliquée dans la division de 1.0f avec une autre variable float! Je ne peux donc pas simplement échanger cette expression avec b / a car cette inexactitude en virgule flottante que le programmeur semble vouloir ici serait perdue.

Etc. Il y a beaucoup de considérations. Il est difficile de prédire à l’avance le code machine que vous utilisez. Sachez simplement que le compilateur suit vos instructions à la lettre.