LINUX.ORG.RU

История изменений

Исправление numas13, (текущая версия) :

Теперь понял про что. Да, с алиасингом по-другому никак.

Не только. У небольшого базового блока очень большие шансы быть объединённым с другими.

Когда в e2k начинается работа с памятью, то всё становится намного веселее. Часть/части базовых блоков начинают мигрировать выше нагружая процессор бесполезной работой, если исполнение не лежит через эту ветку. Но с другой стороны это повышает загруженность ШК и избавляет от и без того медленных ветвлений в e2k.

В e2k всегда будет обращаться в память, даже если эту ветку не надо исполнять. Кеш-промахи будут в любом случае. :)

Но в обоих случаях компилятор не знает что именно будет исполнятся, а это может сильно повлиять на генерируемый код.

  • e2k https://ce.mentality.rip/z/5Gq8qn
    • Ожидания памяти не будет в худшем случае, но будет вариативная задержка (если не ошибаюсь, 4-7 такта до 16C и 4-5 для 16C) из-за невыставленных nop для fmuld.
  • amd64 https://godbolt.org/z/3v64c3re1
    • Не взятые ветвления обычно дешевле.

Хотя ты заметишь, что можно было бы спланировать и лучше, но lcc частенько так «косячит», так что привыкай. Только не надо вновь загонять про «вот напишут нормальный компилятор и заживём». Это не такая простая задача как может показаться на первый взгляд.

Вообще-то подготовленный переход позволяет из одной точки перейти на разные метки. А ibranch технически должен быть равен некоему disp на скрытый регистр при начале выполнения + ct (то есть задержка в 3 такта гарантированно прошла).

disp => ct == 5 тактов.

И если бы он был больше одного такта, то в конце был бы не ibranch .L45, а ct %ctpr1 (если даже считать, что rbranch содержит магию и на ct не заменяется).

Нет всё верно, это тот самый «unhappy path». Зачем зря греть воздух и подготавливать переход? Тем более, что количество доп. конвейеров очень ограничено. В реальных программах компилятор так не делает, т.к. они обычно заняты.

Исправление numas13, :

Теперь понял про что. Да, с алиасингом по-другому никак.

Не только. У небольшого базового блока очень большие шансы быть объединённым с другими.

Когда в e2k начинается работа с памятью, то всё становится намного веселее. Часть/части базовых блоков начинают мигрировать выше нагружая процессор бесполезной работой, если исполнение не лежит через эту ветку. Но с другой стороны это повышает загруженность ШК и избавляет от и без того медленных ветвлений в e2k.

В e2k всегда будет обращаться в память, даже если эту ветку не надо исполнять. Кеш-промахи будут в любом случае. :)

Но в обоих случаях компилятор не знает что именно будет исполнятся, а это может сильно повлиять на генерируемый код.

  • e2k https://ce.mentality.rip/z/5Gq8qn
    • Ожидания памяти не будет в худшем случае, но будет вариативная задержка (если не ошибаюсь, 4-7 такта до 16C и 4-5 для 16C) из-за невыставленных nop для fmuld.
  • amd64 https://godbolt.org/z/3v64c3re1
    • Не взятые ветвления обычно дешевле.

Хотя ты заметишь, что можно было бы спланировать и лучше, но lcc частенько так «косячит», так что привыкай. Только не надо вновь загонять про «вот напишут нормальный компилятор и заживём». Это не такая простая задача как может показаться на первый взгляд.

Вообще-то подготовленный переход позволяет из одной точки перейти на разные метки. А ibranch технически должен быть равен некоему disp на скрытый регистр при начале выполнения + ct (то есть задержка в 3 такта гарантированно прошла).

disp => ct == 5 тактов.

И если бы он был больше одного такта, то в конце был бы не ibranch .L45, а ct %ctpr1 (если даже считать, что rbranch содержит магию и на ct не заменяется).

Нет всё верно, это тот самый «unhappy path». Зачем зря греть воздух и подготавливать переход? Тем более, что количество доп. конвейеров очень ограничено. В реальных программах компилятор так не делает, т.к. они обычно заняты.

Исходная версия numas13, :

Теперь понял про что. Да, с алиасингом по-другому никак.

Не только. У небольшого базового блока очень большие шансы быть объединённым с другими.

Когда в e2k начинается работа с памятью, то всё становится намного веселее. Часть/части базовых блоков начинают мигрировать выше нагружая процессор бесполезной работой, если исполнение не лежит через эту ветку. Но с другой стороны это повышает загруженность ШК и избавляет от и без того медленных ветвлений в e2k.

В e2k всегда будет обращаться в память, даже если эту ветку не надо исполнять. Кеш-промахи будут в любом случае. :)

Но в обоих случаях компилятор не знает что именно будет исполнятся, а это может сильно повлиять на генерируемый код.

  • e2k https://ce.mentality.rip/z/5Gq8qn
    • Ожидания памяти не будет в худшем случае, но будет вариативная задержка (если не ошибаюсь, 4-7 такта до 16C и 4-5 для 16C) из-за невыставленных nop для fmuld.
  • amd64 https://godbolt.org/z/3v64c3re1
    • Не взятые ветвления обычно дешевле.

Хотя ты заметишь, что можно было бы спланировать и лучше, но lcc частенько так «косячит», так что привыкай. Только не надо вновь загонять про «вот напишут нормальный компилятор и заживём». Это не такая простая задача как может показаться на первый взгляд.

Вообще-то подготовленный переход позволяет из одной точки перейти на разные метки. А ibranch технически должен быть равен некоему disp на скрытый регистр при начале выполнения + ct (то есть задержка в 3 такта гарантированно прошла).

disp => ct == 5 тактов.

И если бы он был больше одного такта, то в конце был бы не ibranch .L45, а ct %ctpr1 (если даже считать, что rbranch содержит магию и на ct не заменяется).

Нет всё верно, это тот самый «unhappy path». Зачем зря греть воздух и подготавливать переход? Тем более, что количество доп. конвейеров очень ограничено. В реальных программах компилятор так не делает, т.к. они обычно заняты.