Развертка цикла - это обычная оптимизация, но тоже сделано обратное?
(чтобы уменьшить размер выходного файла объекта, меньший двоичный файл).
Мне любопытно, является ли общий метод компиляторами для дублирования последовательных идентичных блоков кода (или вызовов функций) в цикл или извлечения дублированного блока в статическую функцию.
Мне интересно, потому что в C есть библиотеки с заголовком *
, которые могут добавить много дублированного кода, поэтому было бы полезно знать, могут ли некоторые компиляторы C обнаружить это и обработать его более эффективно.
*
В заголовке-only-library я имею в виду заголовок, который определяет код напрямую, а не определения функций.
И если это будет сделано, было бы полезно знать, в каких условиях и ограничениях применяются, чтобы обеспечить его использование.
Примечание (для целей вопроса - любой популярный компилятор C - это GCC/Clang/Intel/MSVC).
Библиотека только для заголовка, которую я нашел, называется uthash, использует некоторые очень большие макросы, и я хотел знать, происходит ли какая-то компиляция, которая могла бы умно дедуплировать такие огромные блоки кода, см. например: uthash.h, другой похожий пример inline qsort.h
Пример блока, который можно было бы дедуплицировать (оказывается, Py_DECREF
может расширяться в довольно большой блок кода).
#define PY_ADD_TO_DICT(dict, i) \
do {
PyDict_SetItemString(dict, names[i], item = PyUnicode_FromString(values[i])); \
Py_DECREF(item); \
} while (0)
/* this could be made into a loop */
PY_ADD_TO_DICT(d, 0);
PY_ADD_TO_DICT(d, 1);
PY_ADD_TO_DICT(d, 2);
PY_ADD_TO_DICT(d, 3);
Обратите внимание, что это надуманно, но на основе реального примера.
Разъяснение
Кажется, что короткий ответ на мой вопрос - нет (или только в некоторых ограниченных/тривиальных случаях), просто чтобы выяснить, почему я спрашивал немного дальше.
Некоторые ответы в комментариях, по-видимому, предполагают, что вы просто переработаете код в функцию.
Это почти всегда лучший вариант, тем не менее, есть моменты, когда могут отображаться блоки очень похожего кода.
- код плиты котла, созданный не очень умным генератором кода.
- при использовании внешнего API, который предоставляет некоторые функции в качестве макросов (в этом случае, конечно, обертывание локально в функциях работает в большинстве случаев, но это означает, что ваш код получает свои собственные причуды, которые не типичны для использования этих API).
- когда вы не можете заменить макросы функциями, есть редкие случаи, когда это просто непрактично для этого.
- при импорте кода с внешней кодовой базы, он не всегда идеален, чтобы войти и начать очищать свой код, оценивая эту базу кода полезной, чтобы иметь представление о том, насколько умным будет компилятор для оптимизации кода.
Во всех этих случаях его можно дедуплировать (генерировать более умный код, обертывать макросы в функциях, исправлять сторонние библиотеки), но прежде чем прикладывать усилия к тому, чтобы делать такие вещи, стоит знать, сколько работы компилятор делает для нас.