Даже с LTO, компилятор все еще должен использовать эвристику, чтобы определить, следует ли встроить функцию для каждого вызова (обратите внимание, что он принимает решение не по функции, а по вызову). Эвристика учитывает такие факторы, как - находится ли он в цикле, развернут ли цикл, насколько велика функция, как часто она вызывается глобально и т. Д. Компилятор, безусловно, никогда не сможет точно определить, как часто вызывается код, и может ли расширение кода уничтожить кэши инструкций / трассировки / цикла / микрокода конкретного процессора во время компиляции.
Оптимизация профиля, как предполагается, является шагом к решению этой проблемы, но если вы когда-либо пробовали это сделать, вы, вероятно, заметили, что вы можете получить скачок в производительности порядка 0-2%, и это может быть в любом направлении! :-) Это все еще в стадии разработки.
Если производительность является вашей конечной целью, и вы действительно знаете, что делаете, и действительно проводите тщательный анализ своего кода, то на самом деле нужен способ указать компилятору встроенный или не встроенный при каждом вызове не подсказка для каждой функции. На практике я справился с этим, используя специфичные для компилятора подсказки типа «force_no_inline» для случаев, которые я не хочу вставлять, и отдельную копию «force_inline» (или макрос в редких случаях, когда это не удается) функции, когда я хочу, чтобы она была встроенной , Если кто-нибудь знает, как сделать это более понятным способом с помощью специальных подсказок компилятора (для любых компиляторов C / C ++), пожалуйста, дайте мне знать.
Чтобы конкретно адресовать ваши очки:
1.Код становится менее кратким и несколько менее понятным.
Как правило, нет - это просто подсказка для ключевого слова, которая управляет тем, как оно встроено. Однако, если вы прыгаете через обручи, как я описал в предыдущем абзаце, тогда да.
2. Иногда встраивание может значительно увеличить производительность во время выполнения.
Когда вы оставляете компилятор на своих собственных устройствах - да, он, конечно, может, но в основном это не так. Компилятор имеет хорошую эвристику, которая делает хорошие, хотя и не всегда оптимальные решения по встраиванию. В частности, для ключевого слова компиляторы могут полностью игнорировать ключевое слово или использовать ключевое слово в качестве слабого намека - в общем, они, кажется, не любят вставлять код, который помечает красную эвристику (как встраивание функции 16k в цикл, развернутый 16x).
3. Вкладка решается в определенный момент времени, может быть, без предвидения ее использования или без учета всех (будущих) окружающих обстоятельств.
Да, он использует статический анализ. Динамический анализ может исходить из вашей проницательности и , которую вы вручную управляете встраиванием для каждого вызова, или теоретически из PGO (который все еще отстой).