3
votes

Optimisation autorisée sur les objets volatils

De la section ISO / CEI 9899: 201x 5.1.2.3 Exécution du programme paragraphe 4 :

Dans la machine abstraite, toutes les expressions sont évaluées comme spécifié par la sémantique. Une mise en œuvre réelle n'a pas besoin d'évaluer une partie d'un expression s'il peut en déduire que sa valeur n'est pas utilisée et que non les effets secondaires nécessaires sont produits ( y compris ceux causés par l'appel d'un ou accéder à un objet volatil ).

Quelle est exactement l'optimisation autorisée ici concernant l'objet volatil? quelqu'un peut-il donner un exemple d'accès volatil qui PEUT être optimisé?

Étant donné que l’accès aux volatiles est un comportement observable (décrit au paragraphe 6 ), il semble qu’aucune optimisation ne puisse être nécessaire en ce qui concerne les volatiles, donc, je suis curieux de savoir quelle optimisation est autorisée dans la section 4 .


0 commentaires

5 Réponses :


1
votes

quelqu'un peut-il donner un exemple d'accès volatil qui PEUT être optimisé loin?

Je pense que vous avez mal interprété le texte, IMO ce paragraphe signifie que

volatile unsigned int bla = whatever();

if (bla < 0) // the code is not evaluated even if a volatile is involved

10 commentaires

partiellement lié - pensez-vous que cela peut être optimisé loin volatile int x = 3; x; ? l'expression x; est adaptée à l'optimisation?


Et dans ce cas, vous entrez dans un comportement non défini, (x est utilisé non initialisé)


@KeineLust a modifié le commentaire


@StoryTeller pouvez-vous expliquer pourquoi il ne devrait pas être évalué?


Dans ce cas, je pense que x ne peut pas être otimisé, voir godbolt dans cet exemple (compilé avec O2, y est optimisé mais x ne l'est pas): godbolt.org/z/08Q4Sb


@ user2162550 - L'évaluation des courts-circuits fait partie des modèles d'exécution de la machine abstraite. Doit être spécifié sous la spécification de ET logique.


@StoryTeller, oups, maintenant je vois ce que tu veux dire à propos du court-circuit, tu as raison, édité.


Ce n'est pas une interprétation correcte. L'expression «y compris…» modifie les «effets secondaires», ce qui signifie que les effets secondaires qui pourraient être nécessaires incluent l'accès à un objet volatil. S'il existe un accès à un objet volatil, il doit être effectué. L'expression aurait été plus claire si elle avait été écrite «aucun effet secondaire nécessaire (y compris celui causé par l'appel d'une fonction ou l'accès à un objet volatil) n'est produit».


De plus, cette réponse indique que dans if (bla <0) SomeCodeHere; , le SomeCodeHere n'a pas besoin d'être évalué. C'est vrai, mais ce n'est pas ce dont traite le passage cité de la norme C. Ce n'est pas ce que signifie le passage.


attendez, je pense qu'il y a un petit problème ici. Si un compilateur naïf et conforme évaluera if (bla <0) alors il récupérera la valeur de bla de la mémoire (car elle est volatile). Maintenant, si un autre compilateur conforme ne l'évalue pas, il ne récupérera pas le volatile en mémoire, ce qui entraînera des comportements observables différents (l'accès volatil est un comportement observable) pour les deux compilateurs conformes ce qui n'est pas possible selon le paragraphe 6.



1
votes

Ajout d'un autre exemple qui correspond à ce que je comprends:

volatile int vol_a;
....
int b = vol_a * 0; // vol_a is not evaluated


3 commentaires

Pour mémoire, cela ne reproduit pas la réponse acceptée car cette dernière est modifiée.


Idk, gcc et clang sur -03 font une lecture sur a s'il est volatil godbolt.org/z/3tADBK . Bien que ce ne soit évidemment pas la preuve qu'ils doivent agir ainsi.


d'accord sur la partie "must" :)



7
votes

Reformatage un peu:

An actual implementation must evaluate part of an expression if needed
side effects are produced (including accessing a volatile object).

Inverser la logique sans changer le sens:

An actual implementation must evaluate part of an expression if:

  a) it can't deduce that its value is not used; or

  b) it can't deduce that that no needed side effects are produced (including
      any caused by calling a function or accessing a volatile object).

Simplifier pour se concentrer sur la partie volatile:

An actual implementation need not evaluate part of an expression if:

  a) it can deduce that its value is not used; and

  b) it can deduce that that no needed side effects are produced (including any
     caused by calling a function or accessing a volatile object).


0 commentaires

3
votes

Les accès aux objets volatils doivent être évalués. L'expression «y compris tout…» modifie les «effets secondaires». Il ne modifie pas «s'il peut en déduire…». Il a la même signification que:

Une implémentation réelle n'a pas besoin d'évaluer une partie d'une expression si elle peut en déduire que sa valeur n'est pas utilisée et qu'aucun effet secondaire nécessaire (y compris celui causé par l'appel d'une fonction ou l'accès à un objet volatil) n'est produit.

Cela signifie que les «effets secondaires» incluent les effets secondaires causés par l'accès à un objet volatil. Afin de décider qu'elle ne peut pas évaluer une partie d'une expression, une implémentation doit en déduire qu'aucun effet secondaire nécessaire, y compris celui causé par l'appel d'une fonction ou l'accès à un objet volatil, n'est produit.

Cela ne signifie pas qu'une implémentation peut ignorer l'évaluation d'une partie d'une expression même si cette expression inclut des accès à un objet volatil.


3 commentaires

pouvez-vous s'il vous plaît ajouter un exemple? Je suppose que c'est parce que je ne suis pas un anglophone, mais je ne comprends pas entièrement la réponse


peut-être: int func () {int x = * volatile_ptr; return 0; } donc dans ce cas, l'accès au volatile doit être effectué, mais le stockage de la valeur dans x peut être supprimé?


@ user2162550: C'est exact. Dans int x = * volatile_ptr; , * volatile_ptr a un effet secondaire, qui est d'accéder à l'objet volatile vers lequel il pointe. Cet effet secondaire doit être effectué. Ensuite, int x = * volatile_ptr; initialise nominalement x . Mais cette initialisation n'a pas de comportement observable. Il peut donc être éliminé par optimisation.



0
votes

Dans les cas où un accès à un objet volatil affecterait le comportement du système d'une manière qui serait nécessaire pour qu'un programme atteigne son objectif, un tel accès ne doit pas être omis. Si l'accès n'avait aucun effet sur le comportement du système, alors l'opération pourrait être "exécutée" sur la machine abstraite sans avoir à exécuter aucune instruction. Il serait rare, cependant, pour un rédacteur de compilateur de savoir avec certitude que l'effet de l'exécution d'instructions pour effectuer les accès serait le même que celui de faire semblant de faire ces instructions sur la machine abstraite tout en les sautant sur la vraie.

Dans le scénario beaucoup plus courant où un rédacteur de compilateur n'aurait aucune connaissance particulière de tout effet qu'un accès volatil pourrait avoir, mais n'aurait pas non plus de raison particulière de croire que de tels accès ne pourraient pas avoir effets que l'auteur du compilateur ne connaît pas (par exemple à cause du matériel qui est déclenché par des opérations impliquant certaines adresses), un rédacteur de compilateur devrait prévoir la possibilité que de tels accès puissent avoir des effets «intéressants» en les exécutant dans l'ordre spécifié , sans se soucier de savoir si l'auteur du compilateur connaît une raison particulière pour laquelle la séquence d'opérations devrait avoir de l'importance.


0 commentaires