7.3. Оптимизация (улучшение кода)
Параметры -O* задают удобные «пакеты» флагов оптимизации; параметры -f* , описанные позже, задают отдельные оптимизации, которые нужно включить/выключить; параметры -m* задают специфичные для машины оптимизации, которые нужно включить/выключить.
Большинство из этих параметров — булевы и имеют варианты для включения и выключения (начинающиеся с префикса no-). Например, -fspecialise включает специализацию, а -fno-specialise её отключает. Если на командной строке появляются несколько флагов для одного параметра, они обрабатываются слева направо. Например, -fno-specialise -fspecialise включит специализацию.
Важно отметить, что флаги -O* примерно эквивалентны комбинациям флагов -f*. По этой причине, эффект флагов -O* и -f* зависит от порядка их появления на командной строке.
Например, рассмотрим пример -fno-specialise -O1. Несмотря на то, что -fno-specialise присутствует в командной строке, специализация всё равно будет включена. Это потому, что -O1 подразумевает -fspecialise, переопределяя предыдущий флаг. В противоположность этому, -O1 -fno-specialise будет компилироваться без специализации, как и ожидалось.
7.3.1. -O*: удобные «пакеты» флагов оптимизации.
Существует множество параметров, влияющих на качество кода, генерируемого GHC. У большинства людей есть общая цель, например, «Компилировать быстро» или «Сделать мою программу быстрой, как молния». Следующие «пакеты» оптимизаций (или их отсутствие) должны быть достаточными.
Обратите внимание, что более высокие уровни оптимизации приводят к большему межмодульному оптимизации, что может повлиять на то, сколько вашей программы нужно перекомпилировать при внесении изменений. Это одна из причин придерживаться отсутствия оптимизации при разработке кода.
Не указан параметр типа ``-O*``: Это означает «Пожалуйста, скомпилируйте быстро; я не слишком забочусь о качестве скомпилированного кода». Так, например, ghc -c Foo.hs
-
-O0 -
Означает «выключить всю оптимизацию», возвращаясь к тем же настройкам, что и если не было указано никаких параметров
-O. Указание-O0может быть полезно, если, например,makeуже вставил-Oв командную строку.
-
-O -
-O1 -
Означает: «Сгенерировать качественный код без чрезмерных затрат времени». Таким образом, например:
ghc -c -O Main.lhs
-
-O2 -
Означает: «Применить все безопасные оптимизации, даже если это приведёт к значительному увеличению времени компиляции».
Избегаемые «опасные» оптимизации — те, которые могут ухудшить время выполнения или потребление памяти, если вам не повезёт. Обычно они включаются или выключаются индивидуально.
-
-O⟨n⟩ -
Любой -On, где n > 2, эквивалентен -O2.
Мы не используем флаг -O* в повседневной работе. Мы используем -O для достижения приемлемой скорости; например, когда мы хотим что-то измерить. Когда мы хотим добиться максимального результата, мы склонны использовать -O2 (и делаем много кофе-пауз).
Самый простой способ понять, что -O (и т.д.) «действительно означают», — это запустить с -v и полюбоваться результатом.
7.3.2. -f*: независимые от платформы флаги
Эти флаги включают и выключают отдельные оптимизации. Флаги, помеченные как включенные по умолчанию, включены параметром -O, поэтому вам, вероятно, не придётся устанавливать ни один из них явно. Флаг -fwombat может быть отменён, сказав -fno-wombat.
-
-fcase-merge -
- По умолчанию
-
включено
Объединить вложенные выражения case, которые анализируют одну и ту же переменную. Например,
case x of Red -> e1 _ -> case x of Blue -> e2 Green -> e3Преобразуется в,
case x of Red -> e1 Blue -> e2 Green -> e2
-
-fcase-folding -
- По умолчанию
-
включено
Разрешить свёртку констант в выражениях case, которые анализируют некоторые примитивные операции: Например,
case x `minusWord#` 10## of 10## -> e1 20## -> e2 v -> e3
Преобразуется в,
case x of 20## -> e1 30## -> e2 _ -> let v = x `minusWord#` 10## in e3
-
-fcall-arity -
- По умолчанию
-
включено
Включить анализ арности вызовов.
-
-fexitification -
- По умолчанию
-
включено
Включает вынесение точек выхода из рекурсивных функций.
-
-fcmm-elim-common-blocks -
- По умолчанию
-
включено
Включает оптимизацию удаления общих блоков в генераторе кода. Эта оптимизация пытается найти одинаковые блоки Cmm и удалить дубликаты.
-
-fcmm-sink -
- По умолчанию
-
включено
Включает проход погружения в генераторе кода. Эта оптимизация пытается найти одинаковые блоки Cmm и удалить дубликаты. Также она пытается переместить определения переменных ближе к местам их использования. Кроме того, она встраивает простые выражения, такие как литералы или регистры.
-
-fasm-shortcutting -
- По умолчанию
-
выключено
Включает обход на этапе сборки кода генератора. Проще говоря, обход означает, что если блок инструкций A состоит только из безусловного перехода, мы заменяем все переходы к A переходами к преемнику A.
Это в основном делается во время проходов Cmm. Однако это может пропустить частные случаи. Поэтому в -O2 мы запускаем проход ещё раз на стадии asm, чтобы поймать эти случаи.
-
-fblock-layout-cfg -
- По умолчанию
-
выключено, но включено с
-O.
Новый алгоритм учитывает все исходящие края базового блока для расположения кода вместо только последней инструкции перехода. Он также строит граф потока управления для функций, пытается найти горячие пути кода и расположить их последовательно, что приводит к лучшей загрузке кэша и производительности.
Ожидается, что это улучшит производительность в среднем, но фактическое различие в производительности может меняться.
Если вы найдёте случаи существенного снижения производительности, которые можно отследить до очевидно плохого расположения кода, пожалуйста, откройте запрос.
-
-fblock-layout-weights -
Этот флаг — для продвинутых пользователей. Главная цель этого флага — упростить отладку и настройку нового алгоритма расположения кода. Нет гарантии, что значения, дающие лучшие результаты сейчас, не ухудшат их в следующем выпуске.
Если вы считаете, что ваш код заслуживает изменения этих настроек, проконсультируйтесь с исходным кодом для значений по умолчанию и документации. Но я настоятельно не рекомендую этого.
-
-fblock-layout-weightless -
- По умолчанию
-
выключено
Когда не используется cfg-основанное расположение, расположение блоков определяется либо последним переходом в базовом блоке, либо самым тяжёлым исходящим ребром блока в cfg.
С этим флагом мы используем последнюю инструкцию перехода в блоках. Без этого флага старый алгоритм также использует самое тяжёлое исходящее ребро.
Если этот флаг включён и
-fblock-layout-cfgвыключен, расположение блоков ведёт себя так же, как в версиях 8.6 и ранее.
-
-fcpr-anal -
- По умолчанию
-
включено
Включить анализ CPR в анализаторе запросов.
-
-fcse -
- По умолчанию
-
включено
Включает оптимизацию удаления общих подвыражений. Выключение этого может быть полезно, если у вас есть некоторые
unsafePerformIOвыражения, которые вы не хотите объединять.
-
-fstg-cse -
- По умолчанию
-
включено
Включает оптимизацию удаления общих подвыражений в промежуточном языке STG, где она может объединять некоторые подвыражения, которые различаются по своим типам, но не по своему представлению.
-
-fdicts-cheap -
- По умолчанию
-
выключено
Очень экспериментальный флаг, который заставляет выражения со словарями-значениями казаться дешёвыми для оптимизатора.
-
-fdicts-strict -
- По умолчанию
-
выключено
Сделать словари строгими.
-
-fdmd-tx-dict-sel -
- По умолчанию
-
включено
Использовать специальный трансформатор запросов для селекторов словарей.
-
-fdo-eta-reduction -
- По умолчанию
-
включено
Применить эта-редукцию к лямбда-выражениям, если это избавляет от целой группы лямбда-выражений.
-
-fdo-lambda-eta-expansion -
- По умолчанию
-
включено
Расширять связывания let с помощью эта-расширения, чтобы увеличить их арность.
-
-feager-blackholing -
- По умолчанию
-
выключено
Обычно GHC чернит сущность только при переключении потоков. Этот флаг заставляет его делать это сразу после входа в сущность. См. Haskell on a shared-memory multiprocessor.
См. Параметры компиляции для параллелизма SMP для обсуждения его использования.
-
-fexcess-precision -
- По умолчанию
-
выключено
При задании этого параметра промежуточные значения с плавающей точкой могут иметь большую точность/диапазон, чем конечный тип. Обычно это хорошо, но некоторые программы могут полагаться на точную точность/диапазон
Float/Doubleзначений и не должны использовать этот параметр для компиляции.Обратите внимание, что генератор кода для 32-битных x86 поддерживает режим сверхточной точности, поэтому ни
-fexcess-precisionни-fno-excess-precisionне имеют никакого эффекта. Это известный баг, см. Ошибки в GHC.
-
-fexpose-all-unfoldings -
- По умолчанию
-
выключено
Экспериментальный флаг для раскрытия всех развёртываний, даже для очень больших или рекурсивных функций. Это позволяет выполнять инлайнирование всех функций, в то время как GHC обычно избегает инлайнирования больших функций.
-
-ffloat-in -
- По умолчанию
-
включено
Перемещать связывания let внутрь, ближе к их месту связывания. См. Let-floating: moving bindings to give faster programs (ICFP’96).
Эта оптимизация перемещает связывания let ближе к месту их использования. Преимущество заключается в том, что это может предотвратить ненужное выделение памяти, если ветвь, в которой находится let, никогда не выполняется. Также это позволяет другим оптимизирующим этапам работать эффективнее, так как у них больше информации локально.
Однако эта оптимизация не всегда полезна (поэтому GHC применяет некоторые эвристики, чтобы решить, когда её применять). Детали усложняются, но простой пример заключается в том, что часто бывает выгодно перемещать связывания let наружу, чтобы несколько связываний let можно было сгруппировать в одно больше связывание let, эффективно объединяя их выделение и помогая сборщику мусора и аллокатору.
-
-ffull-laziness -
- По умолчанию
-
включено
Запустить полную оптимизацию ленивости (также известную как let-floating), которая перемещает связывания let за пределы окружающих лямбда-выражений, надеясь, что таким образом они будут вычисляться реже. См. Let-floating: moving bindings to give faster programs (ICFP’96). Полная ленивость увеличивает совместное использование, что может привести к увеличению резидентности памяти.
Примечание
GHC не реализует полную ленивость. Несмотря на то, что оптимизация полной ленивости GHC позволяет выполнить некоторые преобразования, которые выполняла бы полностью ленивая реализация (например, извлечение повторяющихся вычислений из циклов), эти преобразования не применяются последовательно, поэтому не полагайтесь на них.
-
-ffun-to-thunk -
- По умолчанию
-
выключено
Worker-wrapper удаляет неиспользуемые аргументы, но обычно мы не удаляем их все, чтобы не превратить замыкание функции в сущность, что, возможно, создаст утечку памяти и/или нарушит инлайнирование. Этот флаг позволяет worker/wrapper удалять все лямбды значений.
-
-fignore-asserts -
- По умолчанию
-
включено
Приводит GHC к игнорированию использования функции
Exception.assertв исходном коде (другими словами, переписываниеException.assert p eвe(см. Утверждения).
-
-fignore-interface-pragmas -
- По умолчанию
-
выключено
Указывает GHC игнорировать всю неважную информацию при чтении файлов интерфейсов. То есть, даже если
M.hiсодержит информацию о развертывании или строгости для функции, GHC проигнорирует эту информацию.
-
-flate-dmd-anal -
- По умолчанию
-
выключено
Повторный запуск анализа спроса в конце потока упрощения. Мы обнаружили некоторые возможности для обнаружения строгости, которые раньше были не видны; и оптимизации, такие как
-fspec-constr, могут создавать функции с неиспользуемыми аргументами, которые удаляются поздним анализом спроса. Улучшения скромные, как и стоимость. См. примечания на странице wiki.
-
-fliberate-case -
- По умолчанию
-
выключено, но включено с
-O2.
Включить преобразование liberate-case. Это раскручивает рекурсивную функцию один раз в своём правом члене, чтобы избежать повторного анализа case свободных переменных. Это немного похоже на специализатора шаблонов вызова (
-fspec-constr), но для свободных переменных вместо аргументов.
-
-fliberate-case-threshold=⟨n⟩ -
- По умолчанию
-
2000
Установить порог размера для преобразования liberate-case.
-
-floopification -
- По умолчанию
-
включено
При включении этой оптимизации генератор кода преобразует все саморекурсивные насыщенные хвостовые вызовы в локальные переходы вместо вызовов функций.
-
-fllvm-pass-vectors-in-regs -
- По умолчанию
-
включено
Инструктирует GHC использовать встроенные векторные регистры платформы для передачи векторных аргументов при вызовах функций. Как и вся поддержка векторов, это требует
-fllvm.
-
-fmax-inline-alloc-size=⟨n⟩ -
- По умолчанию
-
128
Установить максимальный размер выделения инлайновых массивов до n байт. GHC выделит не закреплённые массивы со статически известным размером в текущем блоке выделения памяти, если они не больше n байт, игнорируя переполнение GC.
-
-fmax-inline-memcpy-insns=⟨n⟩ -
- По умолчанию
-
32
Инлайнировать вызовы
memcpy, если они сгенерируют не более ⟨n⟩ псевдоинструкций.
-
-fmax-inline-memset-insns=⟨n⟩ -
- По умолчанию
-
32
Инлайнировать вызовы
memset, если они сгенерируют не более n псевдоинструкций.
-
-fmax-relevant-binds=⟨n⟩ -
- По умолчанию
-
6
В сообщениях об ошибках тип-чекер иногда отображает фрагмент окружения типов, но только до определённого максимального числа, заданного этим флагом. Выключение с
-fno-max-relevant-bindsдаёт неограниченное число. Синтаксически верхнеуровневые связывания обычно также исключаются (поскольку их может быть много), но-fno-max-relevant-bindsвключает и их.
-
-fmax-uncovered-patterns=⟨n⟩ -
- По умолчанию
-
4
Максимальное число несопоставленных шаблонов, которое будет показано в предупреждениях, генерируемых
-Wincomplete-patternsи-Wincomplete-uni-patterns.
-
-fmax-simplifier-iterations=⟨n⟩ -
- По умолчанию
-
4
Устанавливает максимальное число итераций для упростителя.
-
-fmax-worker-args=⟨n⟩ -
- По умолчанию
-
10
Если у работника столько аргументов, больше их не будет распаковываться.
-
-fno-opt-coercion -
- По умолчанию
-
оптимизация coercion включена.
Отключить оптимизатор coercion.
-
-fno-pre-inlining -
- По умолчанию
-
прединлайнирование включено
Отключить прединлайнирование.
-
-fno-state-hack -
- По умолчанию
-
включен режим «state hack»
Отключить «state hack», благодаря которому любая лямбда с маркером
State#в качестве аргумента считается одноэлементной, следовательно, вложение кода внутри неё допустимо. Это может улучшить производительность кода с использованием монады IO и ST, но существует риск уменьшения совместного использования.
-
-fomit-interface-pragmas -
- По умолчанию
-
Включено по умолчанию, если указано
-O0, в противном случае выключено.
Указывает GHC опустить всю неважную информацию из файла интерфейса, сгенерированного для компилируемого модуля (например, M). Это означает, что модуль, импортирующий M, увидит только типы экспортируемых функций M, но не их развертывания, информацию о строгости и т. д. Таким образом, например, никакая функция, экспортируемая из M, не будет встроена в импортирующий модуль. Преимущество заключается в том, что модулям, импортирующим M, потребуется рекомпилироваться реже (только при изменении типа экспорта M, а не при изменении его реализации).
-
-fomit-yields -
- По умолчанию
-
указаны точки yield
Указывает GHC опустить проверки кучи, когда не происходит выделение памяти. Хотя это улучшает размер двоичного файла примерно на 5 %, это также означает, что потоки, выполняемые в узких циклах без выделения памяти, не будут своевременно прерываться. Если важно всегда иметь возможность прерывать такие потоки, следует отключить эту оптимизацию. Также следует рассмотреть возможность повторной компиляции всех библиотек с выключенной этой оптимизацией, если вам необходимо гарантировать прерывистость.
-
-fpedantic-bottoms -
- По умолчанию
-
выключено
Заставляет GHC быть более точным в обращении с дном (но см. также
-fno-state-hack). В частности, останавливает GHC от eta-расширения через выражение case, что хорошо для производительности, но плохо, если вы используетеseqдля частичных применений.
-
-fregs-graph -
- По умолчанию
-
выключено из-за ошибки производительности (#7679)
Применяется только в сочетании с генератором кода нативного кода. Используйте алгоритм выделения регистров с окраской графов для выделения регистров в генераторе кода нативного кода. По умолчанию GHC использует более простой и быстрый линейный алгоритм выделения регистров. Недостатком является то, что линейный алгоритм выделения регистров обычно генерирует худший код.
Обратите внимание, что алгоритм выделения регистров с окраской графов является немного экспериментальным и может не удастся при столкновении с кодом с высокой нагрузкой на регистры #8657.
-
-fregs-iterative -
- По умолчанию
-
выключено
Применяется только в сочетании с генератором кода нативного кода. Используйте итеративный алгоритм коалиции графа с окраской графов для выделения регистров в генераторе кода нативного кода. Это тот же алгоритм выделения регистров, что и у
-fregs-graph, но также включает итеративную коалицию при выделении регистров.
-
-fsimplifier-phases=⟨n⟩ -
- По умолчанию
-
2
Устанавливает количество фаз для упростителя. Игнорируется при
-O0.
-
-fsimpl-tick-factor=⟨n⟩ -
- По умолчанию
-
100
Оптимизатор GHC может разойтись, если вы напишете правила переписывания (Правила переписывания), которые не завершаются, или (менее удовлетворительно) если вы используете рекурсию через типы данных (Ошибки в GHC). Чтобы избежать попадания компилятора в бесконечный цикл, оптимизатор использует «счетчик тактов» и останавливает встраивание и применение правил переписывания, когда этот счетчик превышен. Предел установлен как кратное размеру программы, поэтому у больших программ больше тактов. Флаг
-fsimpl-tick-factorпозволяет изменить множитель. По умолчанию значение 100; числа больше 100 дают больше тактов, а числа меньше 100 — меньше.Если счетчик тактов истекает, GHC суммирует выполненные шаги упростителя; вы можете использовать
-fddump-simpl-statsдля получения более подробного списка. Обычно это довольно точно определяет цикл, поскольку некоторые числа очень велики.
-
-fspec-constr -
- По умолчанию
-
выключено, но включено с помощью
-O2.
Включить специализацию шаблона вызова; см. Специализация шаблона вызова для программ Haskell.
Эта оптимизация специализирует рекурсивные функции в соответствии с «формами» их аргументов. Лучше всего это объяснить на примере, поэтому рассмотрим:
last :: [a] -> a last [] = error "last" last (x : []) = x last (x : xs) = last xs
В этом коде, как только мы пройдём начальную проверку на пустой список, мы знаем, что в рекурсивном случае это соответствие шаблонов избыточно. Поэтому
-fspec-constrпреобразует приведенный выше код в:last :: [a] -> a last [] = error "last" last (x : xs) = last' x xs where last' x [] = x last' x (y : ys) = last' y ysКроме того, избегание ненужного сопоставления шаблонов, также помогает избежать ненужного выделения. Это применяется, когда аргумент является строгим в рекурсивном вызове самому себе, но не при начальном входе. Создаётся строгая рекурсивная ветвь функции, подобная приведенному выше примеру.
Также возможно, что авторы библиотек могут указать GHC на выполнение специализации шаблона вызова очень агрессивно. Это необходимо для некоторых высокооптимизированных библиотек, где мы можем захотеть специализировать независимо от количества специализаций или размера кода. В качестве примера рассмотрим упрощённый случай использования из библиотеки
vector.import GHC.Types (SPEC(..)) foldl :: (a -> b -> a) -> a -> Stream b -> a {-# INLINE foldl #-} foldl f z (Stream step s _) = foldl_loop SPEC z s where foldl_loop !sPEC z s = case step s of Yield x s' -> foldl_loop sPEC (f z x) s' Skip -> foldl_loop sPEC z s' Done -> zЗдесь, после того, как GHC встроит тело
foldlв точку вызова, он выполнит очень агрессивную специализацию шаблона вызова дляfoldl_loopиз-за использованияSPECв аргументе тела цикла.SPECизGHC.Typesспециально распознаётся компилятором.(Примечание: крайне важно использовать
seqили шаблон с указанием на строгость для аргументаSPEC!)В частности, после встраивания это позволит напрямую передать
fв тело цикла, что позволит сильно специализировать рекурсивные случаи.
-
-fspec-constr-keen -
- По умолчанию
-
выключено
Если этот флаг включен, специализация шаблона вызова будет специализировать вызов
(f (Just x))с явным аргументом конструктора, даже если аргумент не проверяется в теле функции. Иногда это полезно; например, аргумент может быть передан другой функции, которая сама может быть специализирована.
-
-fspec-constr-count=⟨n⟩ -
- По умолчанию
-
3
Устанавливает максимальное количество специализаций, которые будут созданы для любой функции преобразованием SpecConstr.
-
-fspec-constr-threshold=⟨n⟩ -
- По умолчанию
-
2000
Устанавливает пороговое значение размера для преобразования SpecConstr.
-
-fspecialise -
- По умолчанию
-
включено
Специализировать каждую функцию, перегруженную типом класса, определённую в этом модуле, для типов, в которых она вызывается в этом модуле. Если установлен
-fcross-module-specialise, импортированные функции, имеющие прагму INLINABLE (Прагма INLINABLE), также будут специализированы.
-
-fspecialise-aggressively -
- По умолчанию
-
выключено
По умолчанию специализируются только методы типа класса и методы, помеченные
INLINABLEилиINLINE. Этот флаг будет специализировать любую перегруженную функцию независимо от размера, если её развертывание доступно. Этот флаг не включен в уровень оптимизации, так как может значительно увеличить размер кода. Его можно использовать совместно с-fexpose-all-unfoldings, если вы хотите убедиться, что все вызовы специализированы.
-
-fcross-module-specialise -
- По умолчанию
-
включено
Специализировать
INLINABLE(Прагма INLINABLE) функции, перегруженные типом класса, импортированные из других модулей, для типов, в которых они вызываются в этом модуле. Обратите внимание, что специализация должна быть включена (флагом-fspecialise) для того, чтобы это имело какой-либо эффект.
-
-flate-specialise -
- По умолчанию
-
выключено
Выполняет другой этап специализации в конце оптимизационной цепочки. Это может выявить возможности специализации, которые возникли на предыдущем этапе специализации или в результате другого встраивания.
Возможно, вам захочется использовать его, если у вас есть метод типа класса, который возвращает ограниченный тип. Например, тип класса, в котором один из методов реализует обход.
-
-fsolve-constant-dicts -
- По умолчанию
-
включено
При решении ограничений, стараться решать ограничения для суперклассов с помощью доступных словарей.
Например:
class M a b where m :: a -> b type C a b = (Num a, M a b) f :: C Int b => b -> Int -> Int f _ x = x + 1
Тело
fтребует экземплярNum Int. Мы могли бы решить это ограничение из контекста, потому что у нас естьC Int b, который предоставляет нам решение дляNum Int. Однако, мы часто можем создавать гораздо лучший код, напрямую решая для доступногоNum Intсловаря, который у нас может быть под рукой. Это устраняет потенциально много уровней косвенности и, что очень важно, позволяет запускать другие оптимизации, так как словарь будет статически известен, и функции выбора могут быть встроены.Оптимизация также работает для GADTs, которые связывают словари. Если мы статически знаем, какой словарь класса нам нужен, то мы решим его напрямую, а не косвенно, используя тот, что передан во время выполнения.
-
-fstatic-argument-transformation -
- По умолчанию
-
выключено
Включить статическую трансформацию аргументов, которая преобразует рекурсивную функцию в нерекурсивную с локальным рекурсивным циклом. См. главу 7 диссертации Андре Сантоса https://www.microsoft.com/en-us/research/publication/compilation-transformation-non-strict-functional-languages/.
-
-fstg-lift-lams -
- По умолчанию
-
включено
Включает оптимизацию позднего подъема лямбда-выражений в промежуточном языке STG. Это выборочно поднимает локальные функции на верхний уровень, преобразуя свободные переменные в параметры функции.
-
-fstg-lift-lams-known -
- По умолчанию
-
выключено
Разрешить превращение известных вызовов в неизвестные при выполнении позднего подъема лямбда-выражений. Это считается невыгодным, поэтому по умолчанию выключено.
-
-fstg-lift-lams-non-rec-args -
- По умолчанию
-
5
Создать функции без рекурсии на верхнем уровне с не более чем <n> параметрами во время выполнения позднего подъема лямбда-выражений. По умолчанию 5, количество доступных регистров параметров на x86_64.
-
-fstg-lift-lams-rec-args -
- По умолчанию
-
5
Создать рекурсивные функции на верхнем уровне с не более чем <n> параметрами во время выполнения позднего подъема лямбда-выражений. По умолчанию 5, количество доступных регистров параметров на x86_64.
-
-fstrictness -
- По умолчанию
-
включено
Включить анализатор строгости. Реализация описана в статье https://www.microsoft.com/en-us/research/wp-content/uploads/2017/03/demand-jfp-draft.pdf.
Анализатор строгости определяет, когда аргументы и переменные в функции могут быть обработаны «строго» (то есть они всегда оцениваются в функции в какой-то момент). Это позволяет GHC применять определенные оптимизации, такие как unboxing, которые в противном случае не применяются, так как они изменяют семантику программы, когда применяются к ленивым аргументам.
-
-fstrictness-before=⟨n⟩ -
Выполнить дополнительный анализ строгости перед фазой упрощения ⟨n⟩.
-
-funbox-small-strict-fields -
- По умолчанию
-
включено
Этот параметр вызывает распаковку всех полей конструкторов, которые помечены как строгие (т. е. «!») и размер представления которых меньше или равен размеру указателя, если это возможно. Он эквивалентен добавлению директивы
UNPACK(см. директива UNPACK) к каждому строгому полю конструктора, которое удовлетворяет ограничению размера.Например, поля конструкторов в следующих типах данных
data A = A !Int data B = B !A newtype C = C B data D = D !C
все будут представлены одним значением
Int#(см. Неупакованные типы и примитивные операции) при включённом-funbox-small-strict-fields.Этот параметр менее радикален, чем
-funbox-strict-fields; он редко ухудшает ситуацию. Если вы используете-funbox-small-strict-fieldsдля включения распаковки по умолчанию, вы можете отключить её для определенных полей конструктора с помощью директивыNOUNPACK(см. директива NOUNPACK).Обратите внимание, что для согласованности
Double,Word64, иInt64поля конструкторов распаковываются на 32-битных платформах, даже если они технически больше, чем указатель на этих платформах.
-
-funbox-strict-fields -
- По умолчанию
-
выключено
Этот параметр вызывает распаковку всех полей конструкторов, помеченных как строгие (т. е.
!), если это возможно. Это эквивалентно добавлению директивыUNPACKк каждому строгому полю конструктора (см. директива UNPACK).Этот параметр немного радикален: иногда он может ухудшить ситуацию. Лучше использовать селективное распаковку полей, используя директивы
UNPACK. Альтернативой является использование-funbox-strict-fieldsдля включения распаковки по умолчанию, но отключение её для определенных полей конструкторов с помощью директивыNOUNPACK(см. директива NOUNPACK).Альтернативно, можно использовать
-funbox-small-strict-fields, чтобы распаковывать только строгие поля, которые «маленькие».
-
-funfolding-creation-threshold=⟨n⟩ -
- По умолчанию
-
750
Определяет максимальный размер, который GHC позволит функции разворачиваться. (Развертывание имеет «размер», который отражает стоимость с точки зрения «разбухания кода» при расширении (т. е. вставке) этого разворачивания в месте вызова. Более крупной функции будет присвоен больший размер.)
Последствия:
- ничего больше этого не будет вставлено (если нет директивы
INLINE) - ничего больше этого не будет выведено в файл интерфейса.
Увеличение этого значения скорее приведет к более длительному времени компиляции, чем к более быстрому коду.
-funfolding-use-threshold=⟨n⟩является более полезным.
-
-funfolding-dict-discount=⟨n⟩ -
- По умолчанию
-
30
Насколько рьяно компилятор должен вставлять словари?
-
-funfolding-fun-discount=⟨n⟩ -
- По умолчанию
-
60
Насколько рьяно компилятор должен вставлять функции?
-
-funfolding-keeness-factor=⟨n⟩ -
- По умолчанию
-
1.5
Насколько рьяно компилятор должен вставлять функции?
-
-funfolding-use-threshold=⟨n⟩ -
- По умолчанию
-
60
Это волшебная граница для разворачивания (вставки): функции меньшего размера будут развернуты в месте вызова, функции большего размера — нет. Вычисленная для функции величина размера зависит от двух вещей: фактического размера выражения минус любые скидки, которые применяются в зависимости от контекста, в который это выражение должно быть вставлено.
Разница между этим параметром и
-funfolding-creation-threshold=⟨n⟩заключается в том, что этот параметр определяет, будет ли определение функции вставлено в месте вызова. Другой параметр определяет, будет ли определение функции вообще сохранено для потенциальной вставки.
-
-fworker-wrapper -
Включить преобразование worker-wrapper после прохождения анализа строгости. Подразумевается
-Oи-fstrictness. Отключено-fno-strictness. Включение-fworker-wrapperпри отключенном анализе строгости (с помощью-fno-strictness) не имеет эффекта.
-
-fbinary-blob-threshold=⟨n⟩ -
- По умолчанию
-
500000
Генератор нативного кода может либо поместить двоичные фрагменты (например, строковые литералы) в файл ассемблера (используя директивы ассемблера “.asciz” или “.string”), либо поместить их как двоичные данные во временный файл, который затем включается ассемблером (используя директиву ассемблера “.incbin”).
Этот флаг устанавливает размер (в байтах) порог, выше которого используется второй подход. Вы можете полностью отключить второй подход, установив порог в 0.
© 2002–2007 The University Court of the University of Glasgow. All rights reserved.
Licensed under the Glasgow Haskell Compiler License.
https://downloads.haskell.org/~ghc/8.10.2/docs/html/users_guide/using-optimisation.html