Почему компилятор XC16 удаляет встроенную функцию, если определение приходит после использования?

В руководстве по компилятору XC16 говорится следующее:

Компилятор исключает встроенные функции только в том случае, если они объявлены как статические и если определение функции предшествует всем ее применениям.

На вершине foo.c я объявил

 static inline void nop_10_times(void);

Затем в определении для ISR определяется как:

void _CNInterrupt(void)
{
    nop_10_times();

    // rest of function
}

Затем, в качестве теста, я положил определение nop_10_times внизу файла.

static inline void nop_10_times(void)
{
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();

    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
}

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

Кто-нибудь знает, как это удалось сделать? Согласно определению, приведенному в руководстве, было сказано, что устранит встроенную функцию, если "определение функции предшествует всем ее применениям".

2 ответа

Оба ручных ограничения кажутся разумными. Они, вероятно, были верны для более ранней версии компилятора или, по крайней мере, были верны в спецификации в какой-то момент.

  1. Если функция не объявлена ​​как статическая, то она может быть вызвана извне текущего модуля перевода (исходного файла). Для этого нужно разместить не встроенную функцию.

  2. Если функция вызывается где-то до ее определения, то у компилятора в точке использования недостаточно информации, чтобы встроить функцию, только чтобы сгенерировать вызов функции.

Похоже, ребята из оптимизатора опередили ребят из документации. Текущий оптимизатор, вероятно, работает над деревом разбора для полной единицы перевода и видит, что он может удалить последовательность вызова / возврата.

Сначала запомните эту директиву inline это просто подсказка для компиляторов. Компиляторы могут встраивать или нет, когда они хотят.

Кто-нибудь знает, как это удалось сделать?

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

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

Кажется, что "если и только если" теперь заменяется простым "если", так что, если определение следует за вызовом, оно иногда может быть встроенным... Или это эффект оптимизатора, так что встраивание может быть рассматривается как пограничный эффект.

Другие вопросы по тегам