Comment empêcher gcc d'optimiser certaines instructions en C?

107

Afin de rendre une page sale (en activant le bit sale dans l'entrée du tableau des pages), je touche les premiers octets de la page comme ceci:

pageptr[0] = pageptr[0];

Mais en pratique, gcc ignorera l'instruction par élimination du magasin mort. Afin d'empêcher gcc de l'optimiser, je réécris l'instruction comme suit:

volatile int tmp;
tmp = pageptr[0];
pageptr[0] = tmp;

Il semble que le truc fonctionne, mais un peu moche. Je voudrais savoir s'il existe des directives ou une syntaxe qui ont le même effet? Et je ne veux pas utiliser de -O0drapeau, car cela entraînera également une grande pénalité de performance.

ZelluX
la source
8
@Mark -O0 arrêtera l'optimisation, mais ralentira également les performances du programme. Je veux juste empêcher l'optimisation de cet extrait de code: P
ZelluX
Je voudrais ajouter que dans le passé, même l'utilisation -O0n'empêchait pas "l'optimisation" du code mort, par exemple, lorsque GCC détecte un code n'a aucun effet, il le supprime simplement. AFAIK c'est une étape avant même -O0... Mais c'est juste mon expérience
smoothware

Réponses:

91

La désactivation de l'optimisation résout le problème, mais ce n'est pas nécessaire. Une alternative plus sûre consiste à empêcher le compilateur d'optimiser le magasin en utilisant le volatilequalificateur de type.

// Assuming pageptr is unsigned char * already...
unsigned char *pageptr = ...;
((unsigned char volatile *)pageptr)[0] = pageptr[0];

Le volatilequalificateur de type indique au compilateur d'être strict sur les magasins et les charges de mémoire. L'un des objectifs de volatileest de faire savoir au compilateur que l'accès à la mémoire a des effets secondaires et doit donc être préservé. Dans ce cas, le magasin a pour effet secondaire de provoquer une erreur de page et vous souhaitez que le compilateur conserve l'erreur de page.

De cette façon, le code environnant peut toujours être optimisé, et votre code est portable vers d'autres compilateurs qui ne comprennent pas les GCC #pragmaou la __attribute__syntaxe.

Dietrich Epp
la source
2
Je dirais que c'est préférable à la désactivation des optimisations. Vous pouvez toujours bénéficier d'autres optimisations en utilisant cette méthode.
Ben S
3
La solution de Dietrich Epp ne fonctionne pas sous le compilateur ARM4.1 . Même la solution de ZelluX ne fonctionne pas. Une méthode alternative pour que cela fonctionne pour ARM4.1 est dans la solution de ZelluX, faites de « temp » une variable volatile globale .
Oculus Dexter
1
C'est assez mauvais pour ledit compilateur.
Alexey Frunze
1
@Shocker: GCC peut toujours optimiser la variable sans optimiser l'accès réel à la mémoire. Ce sont des problèmes différents.
Dietrich Epp
2
@jww: cette utilisation correspond à ce qui est décrit dans ce billet de blog. volatilesignifie que l'accès à la mémoire doit se produire tel qu'écrit, ce qui est exactement ce que nous voulons. En d'autres termes, nous y avons soigneusement réfléchi, et cela signifie ce que nous pensons que cela signifie.
Dietrich Epp
184

Vous pouvez utiliser

#pragma GCC push_options
#pragma GCC optimize ("O0")

your code

#pragma GCC pop_options

pour désactiver les optimisations depuis GCC 4.4.

Consultez la documentation GCC si vous avez besoin de plus de détails.

Charrue
la source
3
Il est à noter cependant que cela ne fonctionne que sur des fonctions entières, pas sur des états spécifiques: gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/… "Chaque fonction définie après ce point est comme si l'attribut (( optimiser ("STRING"))) a été spécifié pour cette fonction. ".
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
134

Au lieu d'utiliser les nouveaux pragmas, vous pouvez également utiliser __attribute__((optimize("O0")))pour vos besoins. Cela présente l'avantage de ne s'appliquer qu'à une seule fonction et non à toutes les fonctions définies dans le même fichier.

Exemple d'utilisation:

void __attribute__((optimize("O0"))) foo(unsigned char data) {
    // unmodifiable compiler code
}
FRob
la source
3
Que faire si je n'utilise pas une -Oleveloption mais que j'ai utilisé les options individuelles qu'elle active séparément? (Dans mon cas, je ne peux pas déterminer quelle est l'option d'optimisation individuelle qui brise le code) .
user2284570