Comment puis-je dire à gcc de ne pas incorporer une fonction?

Dire que j’ai cette petite fonction dans un fichier source

static void foo() {} 

et je construis une version optimisée de mon fichier binary, mais je ne veux pas que cette fonction soit intégrée (à des fins d’optimisation). Y a-t-il une macro que je peux append dans un code source pour empêcher l’inline?

Vous voulez l’atsortingbut noinline spécifique à gcc .

Cet atsortingbut de fonction empêche une fonction d’être considérée pour l’inline. Si la fonction n’a pas d’effets secondaires, il existe des optimisations autres que l’inclusion qui optimisent les appels de fonctions, bien que l’appel de fonction soit actif. Pour éviter que de tels appels ne soient optimisés, mettez asm ("");

Utilisez-le comme ceci:

 void __atsortingbute__ ((noinline)) foo() { ... } 

GCC a un commutateur appelé

-fno-inline-small-functions

Donc, utilisez cela lorsque vous évoquez gcc. Mais l’effet secondaire est que toutes les autres petites fonctions ne sont pas non plus alignées.

Un moyen portable de le faire est d’appeler la fonction via un pointeur:

 void (*foo_ptr)() = foo; foo_ptr(); 

Bien que cela produise des instructions différentes à twigr, ce n’est peut-être pas votre objective. Ce qui soulève un bon point: quel est votre objective ici?

Si vous obtenez une erreur de compilation pour __atsortingbute__((noinline)) , vous pouvez simplement essayer:

 noinline int func(int arg) { .... } 
 static __atsortingbute__ ((noinline)) void foo() { } 

C’est ce qui a fonctionné pour moi.

Utilisez l’ atsortingbut noinline :

 int func(int arg) __atsortingbute__((noinline)) { } 

Vous devriez probablement l’utiliser à la fois lorsque vous déclarez la fonction pour un usage externe et lorsque vous écrivez la fonction.

Je sais que la question concerne GCC, mais j’ai pensé qu’il serait utile d’avoir des informations sur les compilateurs et autres compilateurs.

L’ noinline fonction noinline de GCC est également très populaire avec d’autres compilateurs. Il est soutenu par au moins:

  • Clang (vérifiez avec __has_atsortingbute(noinline) )
  • Intel C / C ++ Comstackr (leur documentation est terrible, mais je suis certain que cela fonctionne sur 16.0+)
  • Oracle Solaris Studio au moins 12.2
  • ARM C / C ++ Comstackr de retour au moins à 4.1
  • IBM XL C / C ++ au moins 10.1
  • TI 8.0+ (ou 7.3+ avec –gcc, qui définira __TI_GNU_ATTRIBUTE_SUPPORT__ )

En outre, MSVC prend en charge __declspec(noinline) dans Visual Studio 7.1. Intel le supporte probablement aussi (ils essaient d’être compatibles avec GCC et MSVC), mais je n’ai pas pris la peine de le vérifier. La syntaxe est fondamentalement la même:

 __declspec(noinline) static void foo(void) { } 

PGI 10.2+ (et probablement plus ancien) supporte un pragma noinline qui s’applique à la fonction suivante:

 #pragma noinline static void foo(void) { } 

TI 6.0+ supporte un pragma FUNC_CANNOT_INLINE qui fonctionne (de manière agaçante) différemment en C et C ++. En C ++, il est similaire aux IGP:

 #pragma FUNC_CANNOT_INLINE; static void foo(void) { } 

En C, cependant, le nom de la fonction est requirejs:

 #pragma FUNC_CANNOT_INLINE(foo); static void foo(void) { } 

Cray 6.4+ (et éventuellement plus tôt) adopte une approche similaire, nécessitant le nom de la fonction:

 #pragma _CRI inline_never foo static void foo(void) { } 

Oracle Developer Studio prend également en charge un pragma qui prend le nom de la fonction, en remontant au moins à Forte Developer 6 , mais notez qu’il doit venir après la déclaration, même dans les versions récentes:

 static void foo(void); #pragma no_inline(foo) 

En fonction de votre dévouement, vous pourriez créer une macro qui fonctionnerait partout, mais vous devriez avoir le nom de la fonction ainsi que la déclaration comme arguments.

Si, OTOH, vous êtes d’accord avec quelque chose qui fonctionne juste pour la plupart des gens, vous pouvez vous en sortir avec quelque chose d’un peu plus esthétique et ne nécessitant pas de vous répéter. C’est l’approche que j’ai adoptée pour Hedley , où la version actuelle de HEDLEY_NEVER_INLINE ressemble à:

 #if \ HEDLEY_GNUC_HAS_ATTRIBUTE(noinline,4,0,0) || \ HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \ HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ HEDLEY_TI_VERSION_CHECK(8,0,0) || \ (HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) # define HEDLEY_NEVER_INLINE __atsortingbute__((__noinline__)) #elif HEDLEY_MSVC_VERSION_CHECK(13,10,0) # define HEDLEY_NEVER_INLINE __declspec(noinline) #elif HEDLEY_PGI_VERSION_CHECK(10,2,0) # define HEDLEY_NEVER_INLINE _Pragma("noinline") #elif HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) # define HEDLEY_NO_RETURN _Pragma("FUNC_CANNOT_INLINE;") #else # define HEDLEY_NEVER_INLINE HEDLEY_INLINE #endif 

Si vous ne voulez pas utiliser Hedley (c’est un en-tête de domaine public / CC0 unique), vous pouvez convertir la version en vérifiant les macros sans trop d’effort, mais plus que ce que je suis prêt à mettre dans ☺.

Je travaille avec gcc 7.2. J’avais spécifiquement besoin d’une fonction pour ne pas être en ligne, car elle devait être instanciée dans une bibliothèque. J’ai essayé la __atsortingbute__((noinline)) , ainsi que la réponse asm("") . Aucun des deux n’a résolu le problème.

Enfin, j’ai pensé que la définition d’une variable statique dans la fonction obligerait le compilateur à lui allouer de l’espace dans le bloc de variables statiques et à lui en donner une initialisation lorsque la fonction est appelée pour la première fois.

C’est en quelque sorte un sale tour, mais ça marche.