Wie kann ich gcc anweisen, eine Funktion nicht zu inlinen?

Lesezeit: 5 Minuten

Benutzeravatar von vehomzzz
vehomzzz

Angenommen, ich habe diese kleine Funktion in einer Quelldatei

static void foo() {}

und ich baue eine optimierte Version meiner Binärdatei, aber ich möchte nicht, dass diese Funktion inline ist (aus Optimierungsgründen). Gibt es ein Makro, das ich in einen Quellcode einfügen kann, um das Inlining zu verhindern?

  • Danke für diese Frage! Ich habe mit oprofile ein Profil erstellt, als eine Funktion nicht angezeigt wurde. Die Antworten hier haben dies behoben.

    – Simon A. Eugster

    29. Oktober 2011 um 9:17 Uhr

  • c++: stackoverflow.com/questions/3329214/…

    – Ciro Santilli OurBigBook.com

    17. Februar 2020 um 14:06 Uhr

Benutzeravatar von alex tingle
Alex Kribbeln

Du willst die gcc-Spezifisch noinline Attribut.

Dieses Funktionsattribut verhindert, dass eine Funktion für das Inlining berücksichtigt wird. Wenn die Funktion keine Seiteneffekte hat, gibt es andere Optimierungen als Inlining, die dazu führen, dass Funktionsaufrufe wegoptimiert werden, obwohl der Funktionsaufruf live ist. Um zu verhindern, dass solche Aufrufe wegoptimiert werden, put
asm ("");

Verwenden Sie es wie folgt:

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

  • Wenn ich gcc 4.4.3 unter Arch Linux verwende, erhalte ich einen Syntaxfehler mit dem oben platzierten Attribut. Es funktioniert korrekt, wenn es der Funktion vorangestellt ist (z. B. Attribut ((noinline)) void foo() {})

    – mrkj

    16. April 2010 um 14:24 Uhr

  • Arduino wollte es auch vor der Funktion platzieren.

    – Peter N. Lewis

    24. Februar 2012 um 9:49 Uhr

  • Bearbeitet, um die Attributsyntax zu korrigieren.

    – Quuxplusone

    21. Juni 2013 um 20:59 Uhr

  • Das asm(“”)-Konstrukt ist eigentlich ziemlich plattformübergreifend und hat die Arbeit erledigt. Ich habe es für x86 Linux gemacht und es hat kein Build-Problem auf PowerPC AIX verursacht. Danke für diesen nützlichen Vorschlag!

    – Martin

    6. November 2014 um 23:58 Uhr

  • Der Ansatz, der überall Codeänderungen erfordert, kann vernünftigerweise nicht als akzeptable Antwort angesehen werden.

    – aje

    27. März 2018 um 14:59 Uhr

Benutzeravatar von lukmac
lukmac

GCC hat einen Schalter namens

-fno-inline-small-functions

Verwenden Sie das also, wenn Sie gcc aufrufen. Aber der Nebeneffekt ist, dass alle anderen kleinen Funktionen auch nicht inliniert sind.

  • Hat auf Compiler-Ebene nicht funktioniert. Verwendete gcc 5.2.1 20150902 (Red Hat 5.2.1-2)

    – John Greene

    16. Februar 2017 um 19:04 Uhr

  • Entweder ist der aktuelle GCC 6.4 kaputt, oder das und einfacher -fno-inline gar nicht funktionieren. gdb gibt immer noch Methoden beim Step-Over ein. Irgendetwas ist kaputt, und ich bezweifle es gdb.

    – aje

    27. März 2018 um 15:12 Uhr

  • Es wird die Inline-Optimierung für alle deaktivieren, nicht nur für eine bestimmte Funktion.

    – wo23

    6. Mai 2019 um 7:36 Uhr

  • @ajeh Das Nicht-Inlining von Funktionen bedeutet, dass sie normal aufgerufen werden, oder?

    – Melebios

    20. Juli 2020 um 9:12 Uhr

Benutzeravatar von nemequ
nemequ

Ich weiß, dass sich die Frage auf GCC bezieht, aber ich dachte, es könnte nützlich sein, auch einige Informationen über Compiler und andere Compiler zu haben.

GCCs
noinline

Das Funktionsattribut ist auch bei anderen Compilern ziemlich beliebt. Es wird mindestens unterstützt von:

  • Clang (überprüfen Sie mit __has_attribute(noinline))
  • Intel C/C++ Compiler (ihre Dokumentation ist schrecklich, aber ich bin mir sicher, dass sie auf 16.0+ funktioniert)
  • Oracle Solaris Studio zurück auf mindestens 12.2
  • ARM C/C++ Compiler zurück auf mindestens 4.1
  • IBM XL C/C++ zurück auf mindestens 10.1
  • TI 8.0+ (oder 7.3+ mit –gcc, das definiert __TI_GNU_ATTRIBUTE_SUPPORT__)

Darüber hinaus unterstützt MSVC
__declspec(noinline)

zurück zu Visual Studio 7.1. Intel unterstützt es wahrscheinlich auch (sie versuchen, sowohl mit GCC als auch mit MSVC kompatibel zu sein), aber ich habe mich nicht darum gekümmert, das zu überprüfen. Die Syntax ist im Grunde dieselbe:

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

PGI 10.2+ (und wahrscheinlich älter) unterstützt a noinline Pragma, das für die nächste Funktion gilt:

#pragma noinline
static void foo(void) { }

TI 6.0+ unterstützt a
FUNC_CANNOT_INLINE

Pragma, das (ärgerlicherweise) in C und C++ unterschiedlich funktioniert. In C++ ist es ähnlich wie bei PGI:

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

In C wird jedoch der Funktionsname benötigt:

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

Cray 6.4+ (und möglicherweise früher) verfolgt einen ähnlichen Ansatz und erfordert den Funktionsnamen:

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

Oracle Developer Studio unterstützt auch ein Pragma, das den Funktionsnamen nimmt und zurückgeht auf mindestens Forte Developer 6aber beachten Sie, dass es kommen muss nach die Erklärung, auch in neueren Versionen:

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

Je nachdem, wie engagiert Sie sind, könnten Sie ein Makro erstellen, das überall funktioniert, aber Sie müssten den Funktionsnamen sowie die Deklaration als Argumente haben.

Wenn Sie, OTOH, mit etwas einverstanden sind, das für die meisten Menschen funktioniert, können Sie mit etwas davonkommen, das ein wenig ästhetisch ansprechender ist und keine Wiederholung erfordert. Das ist der Ansatz, den ich gewählt habe Hedleywo die aktuelle Version von
HEDLEY_NEVER_INLINE
sieht aus wie:

#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_CHECK(6,0,0)
#  define HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
#else
#  define HEDLEY_NEVER_INLINE HEDLEY_INLINE
#endif

Wenn Sie Hedley nicht verwenden möchten (es ist ein einziger Public Domain / CC0-Header), können Sie die Makros zur Versionsprüfung ohne allzu großen Aufwand konvertieren, aber mehr, als ich bereit bin zu investieren ☺.

  • Danke für den Link zu deinem Projekt @nemequ. Ich habe unsere anderen Entwickler gebeten, es für unsere Verwendung zu evaluieren. Wir haben unterschiedliche Architekturen.

    – Daisuke Aramaki

    20. März 2019 um 12:31 Uhr

  • Mich würde sehr interessieren, was sie sagen, besonders wenn sie kein Interesse haben. Und natürlich bin ich da, um Fragen zu beantworten (GitHub Issue Tracker, E-Mail, was auch immer…).

    – nemequ

    21. März 2019 um 3:08 Uhr

Eine portable Möglichkeit, dies zu tun, besteht darin, die Funktion über einen Zeiger aufzurufen:

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

Dies erzeugt jedoch andere Anweisungen zum Verzweigen, was möglicherweise nicht Ihr Ziel ist. Was einen guten Punkt aufwirft: was ist Ihr Ziel hier?

Benutzeravatar von Sam Liao
Sam Liao

Falls Sie einen Compiler-Fehler für __attribute__((noinline))du kannst es einfach versuchen:

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

static __attribute__ ((noinline))  void foo()
{

}

Das hat bei mir funktioniert.

Benutzeravatar von Chris Lutz
Chris Lutz

Verwenden Sie die noinline Attribut:

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

Sie sollten es wahrscheinlich sowohl beim Deklarieren der Funktion für die externe Verwendung als auch beim Schreiben der Funktion verwenden.

1424470cookie-checkWie kann ich gcc anweisen, eine Funktion nicht zu inlinen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy