Я строю систему времени выполнения, которая позволяет программисту указывать обратный вызов, который вызывается в определенных точках. Я использую Clang 7.0.1 / -std=c++17
. Обратный вызов регистрируется во время выполнения, сохраняя лямбду как std::function
. Когда среда выполнения позже вызывает обратный вызов std::function
, она передает 6 аргументов (необходимость, учитывая общность среды выполнения). Обратите внимание, что std::function
создается в приложении, но используется статически связанной библиотекой, которая компилируется отдельно. Тем не менее, я использую LTO (через -flto
и LLD 7.0.1), поэтому я надеялся, что он все еще сможет выполнить эту оптимизацию. Я новичок в некоторых из этих вещей, так что, надеюсь, это возможно.
Когда я компилирую с -O3
и указываю __attribute__((flatten))
в объявлении вызывающей функции, лямбда не является встроенной. Когда я запускаю свою систему, используя события perf, я вижу, что функция не встроена:
return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
mov -0x90(%rbp),%rdi
lea -0x48(%rbp),%rsi
mov %rbx,%rdx
mov %r15,%rbx
callq *0x180(%r15)
...
Этот вызов занимает нетривиальное количество времени, и кажется, что он должен быть встроенным; в общей сложности есть только несколько call-сайтов. Я, конечно, видел, как лямбды были встроены, но я не уверен, что мой подход к использованию функтора (через std::function
) как-то дисквалифицирует встраивание.
Возможно ли форсирование inline? Дайте мне знать, если вам нужна дополнительная информация.
EDIT:
Спасибо за всю очень полезную информацию. Теперь я понимаю, что способ, которым я настроил свою среду выполнения, не дает компилятору возможности встроить обратный вызов. Комментарии ясно дают понять, почему это так. Были некоторые намеки на альтернативные подходы, которые могут быть недостижимы Учитывая, что 1) я контролирую как приложение, так и источник времени выполнения (и модели программирования / API); 2) Я компилирую и библиотеку, и приложение одновременно (и могу даже сделать их унифицированным процессом сборки), есть ли альтернативные подходы, которые я мог бы здесь использовать, которые потенциально могли бы позволить встроить? Может быть шаблоны и лямбды (не std::functions
)? Я новичок в этой области, и у меня есть все уши, если у кого-то есть идеи о том, как эффективно дать компилятору то, что ему нужно встроить. В худшем случае, я могу даже создать собственную версию библиотеки (в качестве доказательства концепции) для каждого приложения, если это открывает какие-либо возможности ...