2016-03-25 2 views
1

J'ai trouvé que in Linux kernel, the clflush function est mis en œuvre commePourquoi ne besoins clflush + m constant

asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p)); 

Je ne comprends pas pourquoi + m est utilisé ici?

Dans ma compréhension, il ne devrait pas être mis en œuvre comme

asm volatile ("clflush (%0)" :: "r"(p)); 
+1

Si quoi que ce soit, la façon évidente de l'écrire serait 'asm volatile (" clflush% 0 "::" m "(* (char *) p))'. Il n'est pas nécessaire de forcer le compilateur à utiliser un simple mode d'adressage '(% reg)' sans déplacement ni index. ** La partie qui est surprenante et intéressante est le '+ ', pas le' m' **. –

Répondre

2

soit sous forme de travaux de l'instruction, car ils se réfèrent tous deux à la même adresse. Cependant, en utilisant +m comme contrainte, il garantit que toute optimisation effectuée avec le code (puisque la fonction est en ligne) ne suppose pas que les données stockées dans le pointeur __p sont préservées. En d'autres termes, il empêche l'optimisation invalide.

+1

Ou pour le dire autrement: Il (essaye de) s'assurer que le compilateur n'a pas encore une partie de la ligne de cache stockée dans les registres. Cela annulerait le but du flush si l'instruction suivante écrivait un registre dans la ligne de cache. –

+0

Je vois. Cela force le compilateur à recharger le contenu au lieu de réutiliser le contenu stroré dans le cache – Mike

+0

Sans le '+', je pense que vous auriez besoin d'un clobber '' memory '', ce qui serait pire pour l'optimiseur. Il est possible de le déclarer comme opérande de mémoire uniquement en entrée, mais l'utilisation d'un opérande d'entrée/sortie est plus sûre car cela force le compilateur à le traiter comme faisant partie de la chaîne de dépendances impliquant cette mémoire. 'asm volatile' n'est pas toujours suffisant pour éviter de réordonner. –