30

Kevin Kofler
:
Pollux
: Je doute vraiment de ça. [...] Mais avant d'avoir pris &x, je ne vois absolument pas ce qui empêcherait le compilo d'optimiser tout ce qu'il veut. La règle "as-if" est tout de même fondamentale : elle permet non seulement l'optimisation, mais aussi la portabilité.

Standard C99, paragraphes 5.1.2.3 [#2], [#3] et [#5], 6.7.3 [#6].
La partie 5.1.2.3 spécifie la règle as-if, et il y a écrit explicitement que volatile veut dire ce que j'ai décrit.

Tu rigoles? La règle 5.1.2.3 n'entre absolument pas en contradiction avec ce que j'ai dit. En particulier, ils ne contredisent pas la règle "as-if", et ils n'obligent pas à créer une "case mémoire". Ils disent juste qu'il faut mettre un agreement point à chaque modification d'un volatile, ce qui est effectivement le cas même si le compilo met la variable dans un registre. La règle 6.7.3 ne parle pas vraiment de la chose.

Non, franchement, cite-moi quelque chose qui prouve indubitablement qu'on n'a pas le droit de compiler :
void f() { volatile int i=0; i=1; g(i); }
en
f:
  moveq #1,d0
  bra g

Pour moi c'est parfaitement légal.

Quant à l'URL de Microsoft, elle est volontairement vague et dit juste "si vous voulez être sûr que ça écrit tout le temps, utilisez volatile". Ca n'a pas la vocation d'une règle infaillible. Ca marche comme si ça écrivait tout le temps.


Et je ne vois pas le rapport entre Microsoft et GTC, si ce n'est qu'on a choisi une syntaxe bien plus pratique que celle de GNU (qui, dois-je le rappeler, est plus ou moins justifiée par le nombre incalculable de plateformes qui doivent être supportées, mais n'est pas conçue pour un usage intensif...)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

31

La règle 5.1.2.3 [#2] dit clairement:
* que l'accès à un objet volatile est un "side effect".
* "At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place."
donc tu ne peux pas déplacer les écritures vers volatile en dehors de leur sequence point (et ; en est un!). Donc i=0;i=1 ne peut pas être optimisé si x est volatile, parce que les 2 écritures sont dans des sequence points différents.

La règle 5.1.2.3 [#5] confirme ceci: "At sequence points, volatile objects are stable in the sense that previous accesses are complete and subsequent accesses have not yet occurred."

La règle 6.7.3 [#5] dit: "Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3." Bref, la règle as-if ne s'applique pas. Puis: "Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously.". En d'autres mots, si aucun unknown factor externe au programme a modifié i, au sequence point ;, i doit valoir 0.

La référence de M$ dit: "The system always reads the current value of a volatile object at the point it is requested, even if the previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment." Il n'y a pas plus clair...
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

32

Thibaut B
: Kevin, réfléchit un petit peu quand tu réponds. La syntaxe de Pollux est mille fois plus claire que la vôtre, pleine de %.

Si tu as une pourcentophobie, je ne peux rien faire pour toi. La syntaxe de GCC:
* ressemble à du C (pas de syntaxe totalement invalide en C à l'intérieur de simples {...})
* est flexible (possibilité de spécifier des contraintes précises sur le placement des opérandes: immédiat, registre de données, registre d'adresses, ...)
ce qui n'est pas le cas de la syntaxe M$ (même si Pollux compte rajouter à son compilateur des trucs qui ne sont pas dans la syntaxe M$ d'origine pour spécifier des contraintes).
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

33

Kevin Kofler :
La règle 5.1.2.3 [#2] dit clairement:
* que l'accès à un objet volatile est un "side effect".
* "At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place."
donc tu ne peux pas déplacer les écritures vers volatile en dehors de leur sequence point (et ; en est un!). Donc i=0;i=1 ne peut pas être optimisé si x est volatile, parce que les 2 écritures sont dans des sequence points différents.

Et alors? La règle "as-if" convient parfaitement. Dans l'exemple donné plus haut, ma solution marche comme si tout avait été fait de cette façon, de manière infaillible. Explique moi ce qui fait que c'est faux.
La règle 5.1.2.3 [#5] confirme ceci: "At sequence points, volatile objects are stable in the sense that previous accesses are complete and subsequent accesses have not yet occurred."

La règle 6.7.3 [#5] dit: "Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3." Bref, la règle as-if ne s'applique pas. Puis: "Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously.". En d'autres mots, si aucun unknown factor externe au programme a modifié i, au sequence point ;, i doit valoir 0.

Oui, mais est-ce qu'on doit considérer qu'il doit y avoir une pile et qu'un de ces unknown factor pourrait être : "consulter le contenu de la pile sans connaître l'adresse de l'objet qui nous intéresse" ? Ca m'a l'air assez implementation-defined.
La référence de M$ dit: "The system always reads the current value of a volatile object at the point it is requested, even if the previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment." Il n'y a pas plus clair...

Oui, mais il ne dit pas où c'est. Si c'est dans un registre, le programme n'a pas vraiment moyen de le savoir (la question étant, en partie, est-ce qu'on peut le mettre dans un registre?)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

34

Kevin Kofler :
(possibilité de spécifier des contraintes précises sur le placement des opérandes: immédiat, registre de données, registre d'adresses, ...) ce qui n'est pas le cas de la syntaxe M$ (même si Pollux compte rajouter à son compilateur des trucs qui ne sont pas dans la syntaxe M$ d'origine pour spécifier des contraintes).

Oula, du calme, je n'ai jamais programmé avec les asm{} de MS, et je n'ai jamais vu de programme les utilisant. Donc je ne me suis pas "inspiré" de la chose, et ce ne sont pas des "rajouts". C'est tout simplement ce que j'ai pu imaginer de mieux, mais après on peut critiquer.

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

35

Pollux :
Et alors? La règle "as-if" convient parfaitement. Dans l'exemple donné plus haut, ma solution marche comme si tout avait été fait de cette façon, de manière infaillible. Explique moi ce qui fait que c'est faux.

Que le programme que tu compiles est trop rapide parce que tu as supprimé des écritures en mémoire dont la suppression était interdite. (La règle "as-if" est le paragraphe 5.1.2.3 qui justement t'interdit de faire ça.)
Oui, mais est-ce qu'on doit considérer qu'il doit y avoir une pile et qu'un de ces unknown factor pourrait être : "consulter le contenu de la pile sans connaître l'adresse de l'objet qui nous intéresse" ? Ca m'a l'air assez implementation-defined.

Justement, s'il n'y a pas de "unknown factor", tu n'as pas d'excuse pour ne pas mettre le contenu attendu lors d'un "sequence point". Relis le paragraphe.
La référence de M$ dit: "The system always reads the current value of a volatile object at the point it is requested, even if the previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment." Il n'y a pas plus clair...
Oui, mais il ne dit pas où c'est. Si c'est dans un registre, le programme n'a pas vraiment moyen de le savoir (la question étant, en partie, est-ce qu'on peut le mettre dans un registre?)

Non. Une variable volatile est obligatoirement en mémoire.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité