Le compilateur AVR-GCC rend le code douteux

9 Le compilateur AVR-GCC rend le code douteux 16 décembre 2022 | Catégorie : Seau à embouts | Auteur : Steve

La plupart des gens pensent que les compilateurs modernes génèrent un code assembleur mieux optimisé que les humains, mais regardez cet exemple d'AVR-GCC 5.4.0 avec le niveau d'optimisation -O2 :

7b96 : 10 92 34 37 m 0x3734, r1 ; 0x803734 7b9a : e0 e0 ldi r30, 0x00 ; 0 7b9c : f0 e0 ldi r31, 0x00 ; 0 7b9e : a0 91 35 37 lds r26, 0x3735 ; 0x803735 7ba2 : b0 91 36 37 lds r27, 0x3736 ; 0x803736 7ba6 : ae 1b sub r26, r30 7ba8: bf 0b sbc r27, r31 7baa : b0 93 89 00 mailles 0x0089, r27 ; 0x800089 7bae : a0 93 88 00 mailles 0x0088, r26 ; 0x800088 7bb2 : 10 92 95 00 mailles 0x0095, r1 ; 0x800095 7bb6 : 10 92 94 00 mailles 0x0094, r1 ; 0x800094 7bba : 32 2d mov r19, r2 7bbc : e0 e0 ldi r30, 0x00 ; 0 7bbe : f0 e0 ldi r31, 0x00 ; 0 7bc0 : f0 93 e3 33 m 0x33E3, r31 ; 0x8033e3 7bc4 : e0 93 e2 33 m 0x33E2, r30 ; 0x8033e2

Il s'agit d'un code linéaire sans ramification. Tous les registres et références mémoire sont 8 bits. Avec AVR-GCC, le registre r1 contient toujours la valeur 0, donc le code fait ceci : définissez tachFlutter sur 0, chargez driveTachHalfPeriod, définissez OCR1A sur driveTachHalfPeriod moins 0, définissez TCNT3 sur 0, définissez currentTrackBytePos sur 0. Il y a aussi un mouvement de r2 à r19, qui est utilisé plus tard, et je ne sais pas pourquoi le compilateur a localisé l'instruction ici. Il y a au moins trois inefficacités flagrantes :

le compilateur perd du temps à charger 0 dans r30 et r31, alors qu'il aurait pu simplement utiliser r1 il le fait DEUX FOIS, alors que nous savons que r30 et r31 étaient déjà à zéro après la première fois il soustrait une constante 0 de driveTachHalfPeriod

Je peux peut-être comprendre la soustraction de la constante 0, s'il y a un autre chemin de code qui saute à 7ba6 où la valeur dans r30:r31 n'est pas 0. Mais pourquoi le compilateur ne créerait-il pas un chemin complètement séparé pour cela, avec une vitesse d'exécution plus rapide lorsque la valeur soustraite est connue pour être 0, même si la taille du code est supérieure ? Après tout, c'est -O2, pas -OS.

Il semble également qu'il n'y ait pas d'optimisation pour définir des variables multi-octets telles que currentTrackBytePos sur zéro. Au lieu de simplement stocker r1 deux fois pour les octets bas et haut, le compilateur crée d'abord une variable temporaire 16 bits sans nom dans r30:r31 et définit sa valeur sur 0, puis stocke la variable sans nom dans currentTrackBytePos.

Ce bloc de code entier pourrait facilement être réécrit :

mailles 0x3734, r1 ; 0x803734 lds r26, 0x3736 ; 0x803736 mailles 0x0089, r26 ; 0x800089 lds r26, 0x3735 ; 0x803735 mailles 0x0088, r26 ; 0x800088 mailles 0x0095, r1 ; 0x800095 mailles 0x0094, r1 ; 0x800094 mov r19, r2 mailles 0x33E3, r1 ; 0x8033e3 mailles 0x33E2, r1 ; 0x8033e2

Ceci est beaucoup plus court et évite d'utiliser r27, r30 et r31, il y a donc plus de registres gratuits disponibles à d'autres fins.

Lisez 9 commentaires et rejoignez la conversation

9 Le compilateur AVR-GCC rend le code douteux 16 décembre 2022 | Catégorie : Seau à embouts | Auteur : Steve

La plupart des gens pensent que les compilateurs modernes génèrent un code assembleur mieux optimisé que les humains, mais regardez cet exemple d'AVR-GCC 5.4.0 avec le niveau d'optimisation -O2 :

7b96 : 10 92 34 37 m 0x3734, r1 ; 0x803734 7b9a : e0 e0 ldi r30, 0x00 ; 0 7b9c : f0 e0 ldi r31, 0x00 ; 0 7b9e : a0 91 35 37 lds r26, 0x3735 ; 0x803735 7ba2 : b0 91 36 37 lds r27, 0x3736 ; 0x803736 7ba6 : ae 1b sub r26, r30 7ba8: bf 0b sbc r27, r31 7baa : b0 93 89 00 mailles 0x0089, r27 ; 0x800089 7bae : a0 93 88 00 mailles 0x0088, r26 ; 0x800088 7bb2 : 10 92 95 00 mailles 0x0095, r1 ; 0x800095 7bb6 : 10 92 94 00 mailles 0x0094, r1 ; 0x800094 7bba : 32 2d mov r19, r2 7bbc : e0 e0 ldi r30, 0x00 ; 0 7bbe : f0 e0 ldi r31, 0x00 ; 0 7bc0 : f0 93 e3 33 m 0x33E3, r31 ; 0x8033e3 7bc4 : e0 93 e2 33 m 0x33E2, r30 ; 0x8033e2

Il s'agit d'un code linéaire sans ramification. Tous les registres et références mémoire sont 8 bits. Avec AVR-GCC, le registre r1 contient toujours la valeur 0, donc le code fait ceci : définissez tachFlutter sur 0, chargez driveTachHalfPeriod, définissez OCR1A sur driveTachHalfPeriod moins 0, définissez TCNT3 sur 0, définissez currentTrackBytePos sur 0. Il y a aussi un mouvement de r2 à r19, qui est utilisé plus tard, et je ne sais pas pourquoi le compilateur a localisé l'instruction ici. Il y a au moins trois inefficacités flagrantes :

le compilateur perd du temps à charger 0 dans r30 et r31, alors qu'il aurait pu simplement utiliser r1 il le fait DEUX FOIS, alors que nous savons que r30 et r31 étaient déjà à zéro après la première fois il soustrait une constante 0 de driveTachHalfPeriod

Je peux peut-être comprendre la soustraction de la constante 0, s'il y a un autre chemin de code qui saute à 7ba6 où la valeur dans r30:r31 n'est pas 0. Mais pourquoi le compilateur ne créerait-il pas un chemin complètement séparé pour cela, avec une vitesse d'exécution plus rapide lorsque la valeur soustraite est connue pour être 0, même si la taille du code est supérieure ? Après tout, c'est -O2, pas -OS.

Il semble également qu'il n'y ait pas d'optimisation pour définir des variables multi-octets telles que currentTrackBytePos sur zéro. Au lieu de simplement stocker r1 deux fois pour les octets bas et haut, le compilateur crée d'abord une variable temporaire 16 bits sans nom dans r30:r31 et définit sa valeur sur 0, puis stocke la variable sans nom dans currentTrackBytePos.

Ce bloc de code entier pourrait facilement être réécrit :

mailles 0x3734, r1 ; 0x803734 lds r26, 0x3736 ; 0x803736 mailles 0x0089, r26 ; 0x800089 lds r26, 0x3735 ; 0x803735 mailles 0x0088, r26 ; 0x800088 mailles 0x0095, r1 ; 0x800095 mailles 0x0094, r1 ; 0x800094 mov r19, r2 mailles 0x33E3, r1 ; 0x8033e3 mailles 0x33E2, r1 ; 0x8033e2

Ceci est beaucoup plus court et évite d'utiliser r27, r30 et r31, il y a donc plus de registres gratuits disponibles à d'autres fins.

Lisez 9 commentaires et rejoignez la conversation

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow