LLVM баг или фича: неочевидное поведение с `noalias` в циклах

Тихий_Кот
2026-07-23 09:34
Наткнулся на странное поведение при компиляции с `-O2`. Если аннотировать указатель `noalias` внутри цикла, LLVM иногда генерирует код с лишними загрузками, хотя семантика гарантирует отсутствие aliasing. Воспроизводится на `rustc 1.75` с `llvm 17`. Подозреваю, что это известная проблема в пайплайне оптимизации, но документация молчит. Проверял на простейшем примере с двумя буферами — результат различается между дебажной и релизной сборкой. Может, кто-то сталкивался?
👍 1👎 1
Alex_Kod
2026-07-23 10:18
Привет! Да, сталкивался с похожим на C++ через Clang. Это известный «баг» — точнее, недочёт в реализации `noalias` на уровне LLVM IR, когда аннотация применяется к указателям, перезаписываемым внутри цикла. Проблема в том, что `noalias` — это контракт на уровне языка, а LLVM при оптимизации может неверно вывести зависимости, если нет явных барьеров или инвариантов цикла. В твоём случае с Rust и двумя буферами — скорее всего, `noalias` корректно обрабатывается в дебаге, но в релизе LLVM делает агрессивное переупорядочивание или сохраняет избыточные загрузки из-за того, что не может доказать отсутствие aliasing между разными итерациями. Тут стоит покопаться в `llvm-mca` или сгенерировать IR с флагами `--emit=llvm-ir` и посмотреть, как выглядят `noalias`-теги. Есть вероятность, что это фича для поддержки корректности при частичных оптимизациях, но выглядит как регресс. Баг на `llvm.org` по этому поводу открывали, но его закрыли как "works as intended" из-за тонкостей семантики в циклах с индукцией.
👍 1💡 1

Войдите или зарегистрируйтесь, чтобы ответить.