[GCC] Два лица inline
От: Tilir Россия http://tilir.livejournal.com
Дата: 15.01.13 07:03
Оценка: 137 (21)
Hi,

Не могу не поделиться прекрасным. Итак исходные данные -- ваяем компилятор GCC (бэкенд к нему). От пользователя пришла проблема, схематично изображённая на рисунке ниже:



есть код A, в котором функция foo() проинлайнена в bar(). Присоединяем к нему код B, который ни к одной из функций не имеет никакого отношения и foo() перестаёт инлайниться. И код A и код B собирались с LTO. Была задача определить почему так произошло, виноват в этом наш бэкенд или это фишка компилятора как такового.

Расковыряв механизм IPA в GCC, я обнаружил там обычную priority queue, куда складываются все функции-кандидаты на инлайн с эвристическими приоритетами. При этом каждый ltrans-модуль имеет ограничение на то, на сколько он может вырасти при инлайне. Как только он вырос "вот на столько", инлайн прекращается. Из-за добавленного кода B, функция foo() отодвигалась по очереди слишком далеко и инлайн прекращался раньше чем очередь доходила до неё. Пользователю я порекомендовал подать в командную строку GCC параметр inline-unit-growth побольше чем дефолтный:

--param inline-unit-growth=60


И это решило проблему.

Через некоторое время, где-то два месяца, ко мне обратился другой пользователь, у которого был принципиально другой код, но очень похожая проблема, схематично изображённая на рисунке 2:



Есть код A+B, в котором функция foo() проинлайнена в bar(). Удаляем из него код B, и функция foo перестаёт инлайниться. Код B не имеет никакого отношения ни к foo, ни к bar, он просто лежит рядом. И код A и код B собирались с LTO.

Этому пользователю я предложил то же самое решение (увеличить --param inline-unit-growth по сравнению с дефолтными 60%) и оно ему помогло.

Кто-нибудь попробует догадаться почему?






А ответ крайне прост -- lto в GCC бьёт код на фиксированное количество ltrans модулей. Для кода A+B эти модули получались достаточно большими и в 60% от них попадал инлайн foo. После того как код B убрали, ltrans-модули стали меньше и инлайн foo перестал попадать в ограничение на рост модуля.

---
With best regards, Konstantin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.