Size: a a a

Compiler Development

2021 January 08

Т8

Т-34 85 in Compiler Development
always_inline
источник

VK

Vladimir Kazanov in Compiler Development
Pavel Samolysov
Кажется с 92 года инлайнить стали существенно больше, но выглядит логично
Они уже тогда работали с архитектурами, где регистров было сильно больше, чем на x86-х той поры. В наши же дни и x86 тоже, в общем-то, не жадничает. 😊
источник

BD

Berkus Decker in Compiler Development
Т-34 85
always_inline
Который не гарантирует инлайн
источник

M

MaxGraey in Compiler Development
Berkus Decker
Который не гарантирует инлайн
Ну разве что только для рекурсивных и взаимно рекурсивных вызовов, а так вообще гарантирует, по крайней мере никаких ограничений по объему кода быть не должно
источник

BD

Berkus Decker in Compiler Development
MaxGraey
Ну разве что только для рекурсивных и взаимно рекурсивных вызовов, а так вообще гарантирует, по крайней мере никаких ограничений по объему кода быть не должно
не, в современных компиляторах эти флажки вообще влияют только на вес, а дальше компиль уже сам  все решает.

да, always_inline подвинет вес функции ближе в сторону инлайнинга, но инлайнинг он не гарантирует.
источник

M

MaxGraey in Compiler Development
Berkus Decker
не, в современных компиляторах эти флажки вообще влияют только на вес, а дальше компиль уже сам  все решает.

да, always_inline подвинет вес функции ближе в сторону инлайнинга, но инлайнинг он не гарантирует.
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/IPO/AlwaysInliner.cpp#L175

/// The always inliner *only* handles functions which are marked with the
/// attribute to force inlining. As such, it is dramatically simpler and avoids
/// using the powerful (but expensive) inline cost analysis. Instead it uses
/// a very simple and boring direct walk of the instructions looking for
/// impossible-to-inline constructs.

Хочу ззаметить, что always_inline даже пытется заинлайнить циклы
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/IPO/AlwaysInliner.cpp#L146

Ну и сюдя по этой весовой функции:
https://github.com/llvm/llvm-project/blob/8b0bd54d0ec968df28ccc58bbb537a7b7c074ef2/llvm/lib/Analysis/InlineCost.cpp#L2619

Инлайн не происходит по следующим причинам:
1) Наличие indirect branches (aka computed goto)
2) Не может вычислить адрес функции (indirect call)
3) Рекурсивные вызовы
4) ReturnsTwice (имеет аттрибут returns_twice)
5) Имеет всякую экзотику вроде va_start, @llvm.icall.branch.funnel и @llvm.localescape

В общем то все. И да, во всех случаях он должен выдать предупреждение
источник

M

MaxGraey in Compiler Development
Berkus Decker
не, в современных компиляторах эти флажки вообще влияют только на вес, а дальше компиль уже сам  все решает.

да, always_inline подвинет вес функции ближе в сторону инлайнинга, но инлайнинг он не гарантирует.
Вы наверное препутали с обычным inline аттрибутом. Тот действительно лишь немного увеличивает приоритет ао время cost analysis
источник

BD

Berkus Decker in Compiler Development
MaxGraey
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/IPO/AlwaysInliner.cpp#L175

/// The always inliner *only* handles functions which are marked with the
/// attribute to force inlining. As such, it is dramatically simpler and avoids
/// using the powerful (but expensive) inline cost analysis. Instead it uses
/// a very simple and boring direct walk of the instructions looking for
/// impossible-to-inline constructs.

Хочу ззаметить, что always_inline даже пытется заинлайнить циклы
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/IPO/AlwaysInliner.cpp#L146

Ну и сюдя по этой весовой функции:
https://github.com/llvm/llvm-project/blob/8b0bd54d0ec968df28ccc58bbb537a7b7c074ef2/llvm/lib/Analysis/InlineCost.cpp#L2619

Инлайн не происходит по следующим причинам:
1) Наличие indirect branches (aka computed goto)
2) Не может вычислить адрес функции (indirect call)
3) Рекурсивные вызовы
4) ReturnsTwice (имеет аттрибут returns_twice)
5) Имеет всякую экзотику вроде va_start, @llvm.icall.branch.funnel и @llvm.localescape

В общем то все. И да, во всех случаях он должен выдать предупреждение
Есть такие же цитаты кода для gcc и msvc?
источник

BD

Berkus Decker in Compiler Development
MaxGraey
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/IPO/AlwaysInliner.cpp#L175

/// The always inliner *only* handles functions which are marked with the
/// attribute to force inlining. As such, it is dramatically simpler and avoids
/// using the powerful (but expensive) inline cost analysis. Instead it uses
/// a very simple and boring direct walk of the instructions looking for
/// impossible-to-inline constructs.

Хочу ззаметить, что always_inline даже пытется заинлайнить циклы
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/IPO/AlwaysInliner.cpp#L146

Ну и сюдя по этой весовой функции:
https://github.com/llvm/llvm-project/blob/8b0bd54d0ec968df28ccc58bbb537a7b7c074ef2/llvm/lib/Analysis/InlineCost.cpp#L2619

Инлайн не происходит по следующим причинам:
1) Наличие indirect branches (aka computed goto)
2) Не может вычислить адрес функции (indirect call)
3) Рекурсивные вызовы
4) ReturnsTwice (имеет аттрибут returns_twice)
5) Имеет всякую экзотику вроде va_start, @llvm.icall.branch.funnel и @llvm.localescape

В общем то все. И да, во всех случаях он должен выдать предупреждение
> Instead it uses
/// a very simple and boring direct walk of the instructions looking for
/// impossible-to-inline constructs.

это значит именно то что я сказал - always_inline не гарантирует инлайнинг.
источник

M

MaxGraey in Compiler Development
Berkus Decker
Есть такие же цитаты кода для gcc и msvc?
Я дкмаю что в GCC примерно тоже самое, просто лишь в его исходниках копаться. MSVC вообще не хочу рассматривать, кроме того у них там нестандартный __force_inline который может как угодно быть реализован
источник

M

MaxGraey in Compiler Development
Berkus Decker
> Instead it uses
/// a very simple and boring direct walk of the instructions looking for
/// impossible-to-inline constructs.

это значит именно то что я сказал - always_inline не гарантирует инлайнинг.
Так а как ты можешь заинлайнить рекурсивную функцию или indirect call к примеру?) Например если ппоробовать заинлайнить функцию аккермана или даже просто фибоначчи с константным параметром то получишь компбинаторный взрыв. Ясное дело, что компилятор пытается тебя уберечь от этого
источник

M

MaxGraey in Compiler Development
Но никаких других ограничений там нету)
источник

BD

Berkus Decker in Compiler Development
MaxGraey
Вы наверное препутали с обычным inline аттрибутом. Тот действительно лишь немного увеличивает приоритет ао время cost analysis
https://github.com/llvm/llvm-project/blob/8b0bd54d0ec968df28ccc58bbb537a7b7c074ef2/llvm/lib/Analysis/InlineCost.cpp#L2619

ссылка которую вы дали - на InlinerLEGACYPASS, но он ровно как и текущий AlwaysInliner в итоге  использует  ту же весовую функцию что и inline
источник

M

MaxGraey in Compiler Development
Функция то одна, а вот анализ разный
источник

BD

Berkus Decker in Compiler Development
MaxGraey
Так а как ты можешь заинлайнить рекурсивную функцию или indirect call к примеру?) Например если ппоробовать заинлайнить функцию аккермана или даже просто фибоначчи с константным параметром то получишь компбинаторный взрыв. Ясное дело, что компилятор пытается тебя уберечь от этого
я не придираюсь (хотя придираюсь), но моя фраза звучала именно так - “always_inline не гарантирует инлайнинг” что, с этим сложно согласиться?
источник

M

MaxGraey in Compiler Development
у обчного инлайна намного больше проверок и взвешиваний происходит прежде чем будет вызвана isInlineViable. Но в случае always_inline веь этот анализ упрощается по сути лишь до последовательного вызова этой функции, в случае обычного inline это не так
источник

BD

Berkus Decker in Compiler Development
MaxGraey
у обчного инлайна намного больше проверок и взвешиваний происходит прежде чем будет вызвана isInlineViable. Но в случае always_inline веь этот анализ упрощается по сути лишь до последовательного вызова этой функции, в случае обычного inline это не так
> у обчного инлайна намного больше проверок и взвешиваний происходит прежде чем будет вызвана isInlineViable.

Одного негативного ответа достаточно чтобы не инлайнить.

Для ответа на вопрос “всегда инлайнит или не всегда” достаточно одной негативной проверки.
источник

M

MaxGraey in Compiler Development
Berkus Decker
я не придираюсь (хотя придираюсь), но моя фраза звучала именно так - “always_inline не гарантирует инлайнинг” что, с этим сложно согласиться?
В мире вообще очень мало чего есть абсолютно. Например материал вроде сажи поглощает лишь 99% света и ему далеко до абсолютно черное тела, но тем не менее мы не говорим что сажа имеет почти черный цвет) Мы просто говорим - это черного цвета материал
источник

BD

Berkus Decker in Compiler Development
MaxGraey
В мире вообще очень мало чего есть абсолютно. Например материал вроде сажи поглощает лишь 99% света и ему далеко до абсолютно черное тела, но тем не менее мы не говорим что сажа имеет почти черный цвет) Мы просто говорим - это черного цвета материал
Давай перефразируем, ты со мной споришь сейчас потому что не согласен или потому что согласен?
источник

M

MaxGraey in Compiler Development
Berkus Decker
> у обчного инлайна намного больше проверок и взвешиваний происходит прежде чем будет вызвана isInlineViable.

Одного негативного ответа достаточно чтобы не инлайнить.

Для ответа на вопрос “всегда инлайнит или не всегда” достаточно одной негативной проверки.
Все относительно) Если сравнивать обычный inline и always_inline, то второй намного строже. Он инлайнит всегда, если только это не приводит к комбинаторному взрыву или это вообще выполнимо. Инлайн же это лишь рекомендация (хинт)

Опять же все дело в формулировке. Это как говрить у вас компилятор оптимизирующий или нет? Так он же не умеет векторизировать (к примеру) - значит не оптимизирующий;)
источник