Disons que j'ai cette petite fonction dans un fichier source
static void foo() {}
et je construis une version optimisée de mon binaire mais je ne veux pas de cette fonction en ligne (à des fins d'optimisation). y a-t-il une macro que je peux ajouter dans un code source pour empêcher l'inline?
Vous voulez l'attribut spécifique gcc
- noinline
.
Cet attribut de fonction empêche une fonction d'être prise en compte pour l'inline. Si la fonction n'a pas d'effets secondaires, il existe des optimisations autres que l'inline qui permettent d'optimiser les appels de fonction, bien que l'appel de fonction soit actif. Pour que ces appels ne soient pas optimisés, mettez
asm ("");
Utilisez-le comme ceci:
void __attribute__ ((noinline)) foo()
{
...
}
GCC a un commutateur appelé
-fno-inline-small-functions
Donc, utilisez cela lorsque vous appelez gcc. Mais l’effet secondaire est que toutes les autres petites fonctions ne sont pas non plus en ligne.
Une méthode portable consiste à appeler la fonction via un pointeur:
void (*foo_ptr)() = foo;
foo_ptr();
Bien que cela produise différentes instructions pour créer une branche, cela peut ne pas être votre objectif. Ce qui soulève un bon point: quel est votre objectif ici?
Si vous obtenez une erreur de compilation pour __attribute__((noinline))
, vous pouvez simplement essayer:
noinline int func(int arg)
{
....
}
Je sais que la question concerne GCC, mais j’ai pensé qu’il serait peut-être utile de disposer également d’informations sur les compilateurs.
L'attribut de fonction noinline
de GCC est également très populaire auprès des autres compilateurs. Il est soutenu par au moins:
__has_attribute(noinline)
)__TI_GNU_ATTRIBUTE_SUPPORT__
)De plus, 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+ prend en charge un pragma FUNC_CANNOT_INLINE
qui fonctionne (de manière gênante) différemment en C et C++. En C++, cela ressemble à l'IGP:
#pragma FUNC_CANNOT_INLINE;
static void foo(void) { }
En C, cependant, le nom de la fonction est requis:
#pragma FUNC_CANNOT_INLINE(foo);
static void foo(void) { }
Cray 6.4+ (et peut-être 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 et remonte à au moins Forte Developer 6 , mais notez que cela 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 niveau de spécialisation, vous pouvez créer une macro qui fonctionnerait partout, mais le nom de la fonction ainsi que la déclaration devraient être utilisés comme arguments.
Si, OTOH, vous êtes d'accord avec quelque chose qui ne fonctionne que pour la plupart des gens, vous pouvez vous en tirer avec quelque chose d'un peu plus esthétique et qui ne nécessite 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 à ceci:
#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 __attribute__((__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_NEVER_INLINE _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), vous pouvez convertir les macros de contrôle de version sans trop d'effort, mais plus que ce que je suis disposé à mettre dans.
static __attribute__ ((noinline)) void foo()
{
}
C'est ce qui a fonctionné pour moi.
Utilisez le noinline
attribut :
int func(int arg) __attribute__((noinline))
{
}
Vous devriez probablement l'utiliser à la fois lorsque vous déclarez la fonction pour une utilisation externe et lorsque vous écrivez la fonction.
Je travaille avec gcc 7.2. J'avais précisément besoin d'une fonction non intégrée, car elle devait être instanciée dans une bibliothèque. J'ai essayé la réponse __attribute__((noinline))
, ainsi que la réponse asm("")
. Ni l'un ni l'autre n'a résolu le problème.
Enfin, j’ai pensé que définir une variable statique dans la fonction obligerait le compilateur à lui allouer de l’espace dans le bloc de variable statique et à lui attribuer une initialisation lors du premier appel de la fonction.
C'est un peu un truc sale, mais ça marche.