Как я могу сказать gcc не встраивать функцию?

Скажем, у меня есть эта небольшая функция в исходном файле

static void foo() {}

и я создаю оптимизированную версию моего двоичного файла, но я не хочу, чтобы эта функция была встроена (для целей оптимизации). есть ли макрос, который я могу добавить в исходный код, чтобы предотвратить inlining?

Ответ 1

Вам нужен атрибут gcc -специфический noinline.

Этот атрибут функции предотвращает функции от рассмотрения встраивание. Если функция не имеют побочные эффекты, есть оптимизации, кроме того, что вызывает оптимизацию вызовов функций хотя вызов функции жить. Чтобы такие звонки не были оптимизирован, поставлен           asm ("");

Используйте его следующим образом:

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

Ответ 2

GCC имеет переключатель под названием

-fno-inline-small-functions

Поэтому используйте это при вызове gcc. Но побочный эффект заключается в том, что все другие мелкие функции также не являются встроенными.

Ответ 3

Портативный способ сделать это - вызвать функцию через указатель:

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

Хотя это дает разные инструкции для ветки, что может и не быть вашей целью. Что вызывает хороший момент: какова ваша цель здесь?

Ответ 4

Если вы получите ошибку компилятора для __attribute__((noinline)), вы можете просто попробовать:

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

Ответ 5

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

}

Это то, что сработало для меня.

Ответ 6

Используйте noinline attribute:

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

Вероятно, вы должны использовать его как при объявлении функции для внешнего использования, так и при написании функции.

Ответ 7

Я знаю, что речь идет о GCC, но я подумал, что было бы полезно иметь некоторую информацию о компиляторах других компиляторов.

noinline функции noinline GCC довольно популярен и для других компиляторов. Он поддерживается как минимум:

  • Clang (проверьте с __has_attribute(noinline))
  • Компилятор Intel C/C++ (их документация ужасна, но я уверен, что он работает на 16. 0+)
  • Oracle Solaris Studio не менее 12,2
  • ARM C/C++ Компилятор вернется, по крайней мере, к 4.1
  • IBM XL C/C++ вернется, по крайней мере, к 10,1
  • TI 8. 0+ (или 7. 3+ с --gcc, который определит __TI_GNU_ATTRIBUTE_SUPPORT__)

Кроме того, MSVC поддерживает __declspec(noinline) обратно в Visual Studio 7.1. Intel, вероятно, поддерживает его (они пытаются быть совместимыми как с GCC, так и с MSVC), но я не потрудился проверить это. Синтаксис в основном тот же:

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

PGI 10. 2+ (и, вероятно, старше) поддерживает прагму noinline которая применяется к следующей функции:

#pragma noinline
static void foo(void) { }

TI 6. 0+ поддерживает прагму FUNC_CANNOT_INLINE которая (досадно) работает по-разному в C и C++. В C++ он похож на PGI:

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

В C, однако, требуется имя функции:

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

Cray 6. 4+ (и, возможно, раньше) использует аналогичный подход, требуя имя функции:

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

Oracle Developer Studio также поддерживает прагму, которая принимает имя функции, возвращаясь хотя бы к Forte Developer 6, но обратите внимание, что она должна появиться после объявления даже в последних версиях:

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

В зависимости от того, насколько вы выделены, вы можете создать макрос, который будет работать повсюду, но вам нужно будет иметь имя функции, а также объявление как аргументы.

Если, OTOH, вы в порядке с чем-то, что просто работает для большинства людей, вы можете уйти с чем-то, что немного более эстетично и не требует повторения. Это тот подход, который я использовал для Hedley, где выглядит текущая версия HEDLEY_NEVER_INLINE:

#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) && defined(__cplusplus)
#  define HEDLEY_NO_RETURN _Pragma("FUNC_CANNOT_INLINE;")
#else
#  define HEDLEY_NEVER_INLINE HEDLEY_INLINE
#endif

Если вы не хотите использовать Hedley (это единый заголовок с общим доменом /CC0), вы можете конвертировать макросы проверки версий без особых усилий, но больше, чем я готов поставить в ☺.

Ответ 8

Я работаю с gcc 7.2. Мне специально нужна была функция, которая не была бы встроена, потому что ее нужно было создать в библиотеке. Я попробовал ответ __attribute__((noinline)), а также ответ asm(""). Ни одна из них не решила проблему.

Наконец, я решил, что определение статической переменной внутри функции заставит компилятор выделить место для него в статическом блоке переменных и выдать ему инициализацию при первом вызове функции.

Это своего рода грязный трюк, но он работает.