Наиболее важные изменения при переходе от lcc-1.29 к lcc-1.30 (changelog)¶
Изменения, затрагивающие совместимость¶
Улучшена реализация PGO (опции
-fprofile-generate,-fprofile-use) - теперь добавление или удаление цикловых прагм в исходнике не приводит к необходимости переполучения профиля. Побочным эффектом данной доработки стало то, что файлы с профильной информацией, полученные с помощью предыдущих версий компилятора, с большой вероятностью не подцепятся в режиме-fprofile-useна текущей версии компилятора; в этом случае следует переполучить профили с помощью текущей версии компилятора.Изменен смысл прагмы
comb_oper. Раньше прагма влияла только на эвристику комбинирования пар арифметических операций в соответствующем цикле, и не влияла на результат операций в этом цикле. В текущей версии компилятора эта прагма может влиять на результат в случае, когда на вход вещественной арифметической инструкции приходят аргументы inf и nan; инструкция может выдать inf вместо nan и наоборот. При этом прагма по-прежнему не влияет на точность результата.Полностью переписана выдача предупреждений по опции
-Wstrict-aliasing=<N>, где N может принимать значения от 1 до 3. Это может приводить к выдаче предупреждений там, где они раньше не выдавались, или отсутствию предупреждений там, где они раньше были. Основная проблема предупреждений-Wstrict-aliasing=<N>в нашем компиляторе состоит в том, что все три уровня реализованы в backend’е (у gcc первые два уровня реализованы во frontend’е), из-за этого могут выдаваться ложные предупреждения для конверсий типов, созданных frontend’ом, т.е. на те места, где в исходнике вообще не было конверсии типов (ни явной, ни неявной). Если подобные предупреждения мешают, их можно отключить опцией-Wno-strict-aliasingили повысить уровень предупреждений N.В заголовочном файле e2kintrin.h заведены E2K-зависимые intrinsic’и с именами _e2k_<имя_операции_e2k>, которые соответствуют существующим builtin’ам. Макросы __builtin_e2k_[ld,st]_…, работающие через вызов __builtin_e2k_loadmas/storemas, объявлены устаревшими и будут удалены в будущих версиях. Вместо них заведены intrinsic’и с именами _e2k_[ld,st]_…
Следующие опции объявлены устаревшими (DEPRECATED) и будут удалены в будущих версиях компилятора:
-fautopar(игнорируется)-fthreads=(игнорируется)-fpar-numa=(игнорируется)-fpar-distr-mem=(игнорируется)-fno-dam4swp(используйте-fno-swp-dam)-fdam-no-rbranch(используйте-fdam-no-short-cc)-fext-strict-aliasing(игнорируется)-fno-ext-strict-aliasing(игнорируется)
Прекращена поддержка процессора elbrus-2c+ с системой команд elbrus-v2
Общие улучшения¶
Расширена поддержка OpenMP 4.5 (lcc-1.29 поддерживал OpenMP 4.5 частично):
Реализована корректная поддержка прагм omp atomic через атомарные конструкции вместо критических секций в большинстве случаев.
Добавлена поддержка clause collapse по опции
-fopenmp-collapseПоддержаны подмассивы в качестве переменных редукции
В библиотеку поддержки добавлены недостающие функции и переменные окружения для управления thread affinity policy
Улучшен цикловой анализ
Оставшиеся ограничения текущей реализации OpenMP:
Игнорируются конструкции для гетерогенных систем
Не поддержаны пользовательские редукции
Не поддержана конструкция ordered с параметром (сейчас параметр игнорируется)
Модификаторы планирования в цикловых конструкциях игнорируются
Добавлена полноценная поддержка выражений в прагмах OpenMP (lcc-1.29 поддерживал выражения частично).
Добавлена поддержка опции
-fprofile-partial-training. По умолчанию, в режиме-fprofile-useкомпилятор очень консервативно оптимизирует участки кода, не покрытые тренировочным запуском, - оптимизируется размер кода, а не скорость его исполнения. Это может негативно сказаться на оптимизации горячих участков кода, не покрытых тренировочными запусками. С опцией-fprofile-partial-trainingкомпилятор уменьшает степень доверия профильной информации и начинает оптимизировать непокрытые профилем участки кода более агрессивно:Функции, не исполнявшиеся на тренировочных запусках оптимизируются так же, как и без опции
-fprofile-useЕсли функция исполнялась на тренировочном запуске, но в ней есть циклы, которые не исполнялись, то компилятор оптимизирует их более агрессивно.
Добавлена поддержка опции
-fuse-regs-part=<f>, позволяющая уменьшить количество доступных распределителю регистров. Опция может быть полезна в специфичных случаях, когда при работе программы значительная доля времени исполнения тратится на аппаратное сохранение/восстановление регистрового окна.Добавлена опция
-fswp-dam-cc(-fno-swp-dam-cc), которая включает (выключает) построение компенсирующего кода при применении DAM в конвейеризованных циклах. Стоит отметить, что DAM без компенсирующего кода (-fno-swp-dam-cc) имеет весьма низкую эффективность. Режим по умолчанию:-fswp-dam-cc(в режиме-O3),-fno-swp-dam-cc(в режиме-O2).Добавлена поддержка опции
-falign-loops=<n[:m]>, позволяющей выранивать начало кода циклов на величину, равную степени двойки, большей либо равной n, пропустив при этом не более m - 1 байт. В более ранних версиях компилятора данная опция игнорировалась для совместимости с GCC.Добавлена поддержка опции
-fopt-report-asmдля печати отчёта о применении оптимизаций в ассемблер. По этой опции в ассемблере перед кодом цикла вставляется комментарий, содержащий информацию о применении оптимизаций к данному циклу. Имеет смысл только вместе с опциями-fopt-report=<N>и-SДобавлена опция
-fstrict-aliasing-relaxed-char, позволяющая трактовать char как обычный тип в анализе указателей на основе типов (tbaa).Существенно повышена надёжность реализации Address Sanitizer (опция
-fsanitize=address) после перехода на новую версию библиотеки поддержкиРеализована полноценная поддержка барьеров для операций обращения к памяти:
__builtin_read_barrier,__builtin_write_barrier,__builtin_mem_barrier. В предыдущих версиях компилятора данные барьеры работали только на поздних оптимизационных фазах, что делало их практически бессмысленными. Формально эти барьеры остаются экспериментальными, поскольку проверять корректность их поддержки можно только вручную.Добавлена опция
-fspec-volatile-st(-fno-spec-volatile-st), разрешающая (запрещающая) ставить в спекулятивный режим исполнения операции записи в память по указателю с квалификатором volatile. Опция-fno-spec-volatile-stможет быть полезна для системного ПО (ядро linux, например), в котором есть обращения к особым типам памяти, для которых запрещены спекулятивные обращения.В runtime-анализатор качества работы оптимизаций (опция
-fsanitize=opt) добавлена поддержка оптимизаций vect и rtmd. Анализатор по-прежнему имеет статус экспериментального.Расширен набор e2k-зависимых builtin’ов для построения конкретных арифметических машинных операций
Начиная с версии lcc-1.30.03 оптимизация full peeling отключается, если значение прагмы
unrollне совпадает с количеством итераций циклаДобавлена опция
-ffinite-loops(-fno-finite-loops), позволяющая устранить неоднозначность в определении бесконечных циклов в случае, когда условие выхода из цикла является инвариантным, но не константным. Опция поддерживается начиная с версии lcc-1.30.03Введена опция
-faligned-apb(-fno-aligned-apb), по которой при задействовании механизма аппаратной подкачки массивов считаем, что все чтения из памяти в наиболее вложенных циклах выровнены на свой формат. Опция поддерживается начиная с версии lcc-1.30.03Введена
#pragma apb_aligned, по которой при задействовании механизма аппаратной подкачки массивов считаем, что все чтения из памяти в ближайшем после объявления прагмы цикле являются выровненными на свой формат. Прагма поддерживается начиная с версии lcc-1.30.03Начиная с версии lcc-1.30.05, отключена поддержка
#pragma ivdepдля режима-m128(конструкция игнорируется)
Доработки оптимизаций¶
Полностью переписан анализ указателей на основе типов (tbaa - Type Based Aliasing Analysis). Анализ включается опцией
-fstrict-aliasing(входит в состав-ffast). Новая версия анализа позволяет разрывать больше зависимостей между операциями обращения к памяти по сравнению с предыдущими версиями компилятора, особенно для обращений к полям struct, union и class. По нашим замерам новый анализ позволяет ускорить задачи spec cpu 2017 в среднем на 4-9% в зависимости от режима компиляции, отдельные задачи ускоряются до 1.9 раз. Нарушения правил строгой типизации (strict aliasing), которые прописаны в стандартах языков C и C++, встречаются в программах довольно часто; из-за таких ошибок в программах анализ tbaa может разрывать зависимости между операциями, работающими с пересекающимися областями памяти. Чтобы подобные ошибки в исходных кодах реже приводили к некорректной работе программ, в анализе tbaa предусмотрены специальные меры:Считаем, что указатель типа
void *может пересекаться с указателем любого другого типа. И хотя в стандартах языков C и C++ нет такого требования, мы учитываем здесь сложившуюся практику программирования. Аналогичным образом работает анализ tbaa в GCC.Если какой-либо другой анализ указателей выявил точное пересечение адресов двух операций обращения к памяти, анализ tbaa не разрешает зависимости между этими операциями. Аналогичным образом работает анализ tbaa в GCC.
Если в коде функции в переменную типа “указатель” пишется значение несовместимого (с т.з. правил strict aliasing) типа, то для такого указателя анализ tbaa отключается в данной функции.
Если в адресном выражении операции обращения к памяти есть преобразование между несовместимыми типами указателей, то для такой операции анализ tbaa отключается.
Для выключения последних двух проверок в анализе нарушений можно использовать опцию
-funsafe-strict-aliasing. Для поиска нарушений правил strict aliasing в исходниках рекомендуется использовать опцию-Wstrict-aliasing=<N>.Реализованы оптимизации для массивов переменной длины (VLA):
Удаление неиспользуемых массивов
Замена массива переменной длины на обычный массив, если в процессе оптимизаций удалось статически вычислить его длину
Удаление избыточных операций выделения/освобождения стека
Изменилось поведение DAM в конвейеризованных циклах: раньше в режиме
-O3при выборе решателем линейки оптимизаций уровня-O2DAM не строил компенсирующий код, а теперь начал его строить. Это может привести к увеличению размера кода в режиме-O3; поведение компилятора в режиме-O2не изменилось. Согласно нашим замерам, в режиме-O2добавление опции-fswp-dam-ccприводит к увеличению размера кода на 1-2% в среднем, при среднем ускорении исполнения около 5%.Расширена область применимости оптимизации exp_vars, теперь расширение 32-разрядных индуктивных переменных циклов до 64-разрядных должно выполняться для большего числа контекстов. Данная оптимизация имеет мало смысла сама по себе, однако, она критически необходима для применения других важных оптимизаций (например, apb, sle, rle и т.д.) в случае, когда формат индуктивной переменной цикла меньше формата адреса операций обращения к памяти.
Оптимизация ICF доработана для объединения статических read-only переменных с одинаковыми значениями.
Сняты некоторые ограничения на комбинирование вещественных операций (например, fmul_fadds) в случаях, когда для комбинирования требуется перестановка аргументов операций местами. Сейчас данное преобразование требует лишь опцию
-ffinite-math-onlyили прагмуcomb_oper.Добавлена оптимизация машин состояний, которые заданы конструкцией switch в цикле по опции
-ffinite-state-machine-transform. Оптимизация имеет статус экспериментальной и корректность её работы не гарантируется.Реализована оптимизация apb_versioning по опции
-floop-apb-align-versioning(включена по умолчанию), позволяющая динамически проверять выровненность адресов чтений в наиболее вложенных циклах, и в зависимости от результата проверки передавать управление на одну из версий цикла. В Elbrus V2-V4 оптимизация apb применяется только к тем чтениям, для которых статически или динамически удалось доказать выровненность адреса, это аппаратное ограничение; начиная с Elbrus V5 данное ограничение было снято. Таким образом apb_versioning не имеет смысла сама по себе, а нужна лишь для расширения применимости apb на старых версиях Elbrus. Поскольку apb_versioning может приводить к значительному росту размера кода, данное преобразование применяется только к циклам, имеющим достаточно большое количество итераций.Реализована оптимизация rwpe (Redundant Writes through Pointer Elimination) - удаление избыточных записей в таблицу виртуальных методов в деструкторах.
