Kevin Kofler
:Pollux
:Kevin KoflerSi, ce sont des taux d'erreur pour un gain d'une 20aine d'octets [en admettant que le gain ne soit que d'une 20aine d'octets, ce dont je parle plus bas]. Et même mieux : l'erreur est encore plus grave dans le cas de tes "optimisations".
:PolluxTu compares des pourcentages qui ne sont pas comparables.
: Et aussi que tu préfères la "validité" d'un programme à la taille qu'il prend (même si cette "validité" consiste à faire gagner 1 bit de seed pour prendre une 30aine d'octets en plus). Bizarrement, cette fois-ci c'est le contraire, alors que 99.000% est très inférieur à 99.994%
Désolé, je ne comprends pas du tout d'où tu sors ces chiffres. Si tu pouvais expliciter... Parce que les chiffres qui "tombent du ciel", je ne vois vraiment pas quoi y répondre.
Je détaille : ton 99% vient de toi et est censé être la proportion de progs ASM correctement compilés. Le 99.994% est la probabilité qu'il y n'ait pas la moindre collision dans la génération de 500 seeds différents avec un seed de 31 bits... Et l'ordre de grandeur est le même.
Cf. le dernier paragraphe de ma réponse d'avant: se limiter à l'assembleur n'a aucun sens pour les raisons déjà évoquées.et que la place gagnée par les optimisations ASM ne doit jamais dépasser les 20 octets même sur le plus complexe des programmes
Relis les messages ci-dessus. J'ai gagné plusieurs KO sur CC rien qu'avec les optimisations du linker!
Putain, Kevin!Ca t'arrive de lire les posts en entier? Mon post précédent excluait explicitement le cas des optimisations sur le code C
Ce paragraphe-là n'explique rien, mais par contre le paragraphe suivant de ce post donne un semblant de raison...
pour le code C, on est d'accord, tu fais ce que tu veux (et tu as parfaitement le droit de le faire dans le linker si ça te fait plaisir, ce n'est pas ça que je critique). Je dis que pour le code ASM, le rapport gain de place / taux d'erreur est plus faible que pour le remplacement de ta fonction randomize() "mathématiquement idéale" () par ma fonction.
Grave erreur. Je peux écrire un code ASM qui sera optimisable exactement autant que CC! C'est même trivial de le faire: tigcc -S *.c.
Ce n'est pas une raison pour transformer les bsr/rts en bra, parce que ça change carrément la sémantique... Normalement, la sémantique de "tigcc *.s" devrait être la même que "cat *.s > $$.s && tigcc $$.s && rm -f $$.s" (modulo le nom du fichier de sortie, et modulo les éventuels conflits de macro). Et c'est largement faisable : sauf qu'il ne faut pas utiliser un format objet hacké dans tous les sens, il faut utiliser un code intermédiaire gardant toutes les infos sémantiques du fichier assembleur de départ...
Si on ne remarque pas les optimisations dans la plupart des programmes actuels en assembleur, c'est parce qu'ils ont été écrits pour des linkers débiles (parfois même pour des non-linkers qui ne prenaient qu'un seul fichier objet!) et utilisent donc des hacks affreux de style les include de code (comme déjà dit: à mort ce hack!). On peut tout à fait programmer proprement, c'est-à-dire en suivant les principes de la programmation modulaire (compilation séparée etc.) en assembleur, et là, on aura besoin des optimisations du linker pour que le style propre ait exactement la même efficacité que le style sale et obsolète. Un des grands points forts des optimisations du linker est d'encourager la programmation modulaire propre en éliminant totalement la pénalité de l'utilisation de plusieurs fichiers objet, rendant ainsi le hack des include de code totalement inutile et obsolète. Et c'est valable pour l'assembleur autant que pour le C.
Mon "million" était un chiffre au hasard (d'où l'écriture en lettres, pas en chiffres), et ici, j'ai même opté pour "suffisamment de fois" qui est encore plus clair. 2 milliards de fois, c'est un nombre fini d'essais, donc qualifie très bien comme "suffisamment de fois".Si tu te mets à parler d'inévitable, ça veut dire que tu fais des tests successifs; alors tu n'auras une collision qu'au bout de 2 milliards de tests (et pas 16000 en prenant des tests aléatoires).(sans compter que l'impact d'une collision de générateur aléatoire est quasi-nul, alors que celui d'un programme qui se comporte anormalement est très grave et fait perdre un temps précieux au programmeur).Je vois ça autrement: les collisions (ou autres problèmes) causé(e)s par un mauvais générateur de nombres aléatoires sont inévitables. En exécutant le programme suffisamment de fois, on atteint forcément le cas "mauvais".
Qui parle de million?
En revanche, pour les programmes détruits par un optimisateur, il suffit de vérifier que le programme a été compilé correctement (par exemple en le testant, ou idéalement en comparant les sources avec ce que sort ttdasm) et puis il restera correct, qu'on l'exécute une fois ou des millions de fois. Une fois la correction vérifiée, on ne peut jamais produire l'erreur rien qu'en exécutant le programme, même si on passe toute sa vie à exécuter le programme en boucle. C'est donc un problème de nature totalement différente.Sauf que _personne_ n'a _jamais_ fait la vérification avec ttdasm de son programme,
Sauf moi.C'est la meilleure manière de voir si la sortie correspond à l'entrée. Mais bon, j'avoue que je ne l'ai fait que pour des très petits programmes, et c'était souvent pour déboguer le linker.
Bah oui, en dehors de testcases simples, c'est complètement impraticable.
et pour cause : si j'assemble un truc, je suppose que l'assembleur va faire son boulot et pas le modifier en faisant des suppositions trop fortes sur la signification de "bsr", par exemple. En plus, c'est pas du tout viable : le formattage est très différent (sans même parler des macros!), et ttdasm n'est pas parfait.
Le formattage différent n'a aucune importance, vu qu'il s'agit de comparer à la main, pas automatiquement.

La seule méthode réellement employée, et ça tu ne peux pas le nier, c'est le débogage à la main. Ca veut dire que l'erreur peut se manifester une fois sur 50, ou bien seulement dans des cas particuliers
Dans ces cas, tout dépend de la qualité des tests effectués. Avec un bon whiteboxing, on teste tous les chemins d'exécution. Mais comme déjà dit, l'idéal est de comparer avec ce que sort ttdasm.
Bah dans les deux cas c'est gore, et tout sauf sûr.
(par exemple le bug de mon exemple de fonction de détection de ghost space pourrait ne foirer que si le programme avait déjà été appelé par un prog basic et que donc le programme n'a pas été rechargé par le TIOS, etc... : typiquement, c'est le genre de truc difficilement reproductible et donc difficilement testable). Et crois-moi, ça fait perdre un temps précieux.
Il est vrai que des fois les tests sont vraiment durs à faire. D'où mon conseil d'utiliser ttdasm.
Toujours aussi impraticable, ça n'a pas changé depuis les 3 paragraphes précédents

Et d'ailleurs, pour le cas des problèmes avec l'optimisation tailcall des bsr, il suffit de regarder la source pour voir s'il y a un problème, on n'a même pas besoin de désassembler ou tester le résultat! C'est simple: S'il y a un bsr ou jsr label suivi d'un rts sans aucun label entre les 2, ça sera optimisé.
Bah oui mais on n'a pas forcément toutes les optimisations en tête, et rien ne dit que tu ne vas pas en rajouter de nouvelles...
Et il suffit d' "upgrader" sa version de TIGCC pour introduire des nouveaux bugs, c'est ça le plus gênant
Non, il "suffit" de mettre à jour TIGCC et d'activer de nouvelles optimisations.Et il ne faut vraiment pas faire semblant de ne pas être au courant, vu que toutes mes annonces des bêtas parlent à chaque fois des nouvelles optimisations (dans les "rappels").
Sauf qu'en pratique on les active qd même, ces optimisations parce que sans, TIGCC génère du code très largement moins bon que GTC...
Actuellement, on a obligatoirement besoin des optimisations du linker aussi pour le C. GCC 3.4 pourra changer ça un peu (il permet de compiler plusieurs .c en même temps). Mais pas entièrementCa, c'est un autre pb : si vous ne savez pas implémenter ça, tant pis. Mais tel que c'est implémenté, c'est complètement immonde, ça favorise les bugs, et je comprends qu'on veuille rester à TIGCC 0.94 si on veut utiliser plus d'une centaine de lignes de code ASM...
Ben, moi, je ne comprends pas vraiment. Ce qui règne ici, c'est une grosse paranoia appuyée sur des exemples construits (pas tirés du monde réel) pour des cas totalement improbables, ainsi que sur des exemples réels (ceux de Flanker) qui ne boguent pas à cause d'une erreur fondamentale des optimisations du linker, mais à cause d'un problème de switches qui peut être résolu par l'utilisateur en RTFM et par les versions futures de TIGCC en mettant le bon switch automatiquement. Je répète: les exemples réels cités par Flanker ne sont pas des victimes inévitables des optimisations du linker! Toutes les victimes inévitables citées étaient des exemples construits spécialement pour ça (dont je connaissais déjà l'existance théorique), qui n'existent pas en pratique.
Ca, ça m'étonnerait énormément...
les librairies statiques, qui chez nous sont de vraies librairies statiques, pas des archives de sources.Et vive les approximations foireuses ... Il y a bcp moins de différence entre le code intermédiaire et votre code objet avec tous les labels locaux qu'entre la source et le code intermédiaire...
Personnellement, je trouve que le mode all-relocs est le seul mode d'assemblage raisonnable. L'assembleur n'a pas à essayer de faire le travail du linker en supprimant les labels locaux et en prérésolvant les références PC-relatives locales. La résolution des relogements et la gestion des labels font partie du boulot du linker. Je trouve que ce n'est vraiment pas malin de mettre la résolution des relogements dans l'assembleur, ça ne fait que dupliquer le travail du linker. Si jamais j'écris un nouvel assembleur pour TIGCC, il n'utilisera que le mode all-relocs.

EDIT : oublié un [/ cite]