flang компилятор доказывает, что программа не зациклится 0.6.2 GitHub

Вывод типов отдаёт доказанное отметкой на дереве, а не таблицей наружу

Обещанные две правки скорости сделаны, и обе оправдались: 1,77 раза геометрическим средним, до 4,50 на арифметике. Мы стали быстрее Python в 1,28 раза там, где были медленнее в 1,37.

Главное здесь — не число, а как оказалось правильно достать типы узлов. Вопрос стоял так: проверка типов знает тип каждого выражения, но выбрасывает его, а генератору кода он нужен, чтобы не печатать проверку, ответ которой известен заранее. Напрашивалось «пусть checkTypes вернёт таблицу узел → тип, а генератор кода в неё смотрит». Это неверный ход, и вот почему.

Генераторов кода восемь, и один из них написан на самом flang. Копия генератора C на flang (flang/self/emit-c.flang) проверку типов не видит вовсе — круг импортов. Значит таблица наружу означала бы либо второй вывод типов внутри копии, либо расхождение двух генераторов ровно там, где они обязаны совпадать побайтово.

Правильный ход уже стоял в дереве, оставалось им воспользоваться. В компиляторе есть проход отметок: анализ кладёт на узлы дерева поля («здесь доказана непустота», «здесь нужна проверка убывания меры»), а генератор кода их только читает и ничего не доказывает. Третья отметка легла туда же: поле числовая на узле двуместной операции, у которой доказан тип обоих операндов. Правка вышла примерно в 100 строк кода в свидетеле при оценке 150–250 — именно потому, что проход отметок уже был. Копия генератора на самом flang стоила ещё около 160 строк, и это та половина цены, которую оценка не учитывала вовсе.

Правило, которое из этого следует: знание анализа доезжает до генератора кода отметкой на дереве, а не отдельной таблицей. Таблица не переживает границу языков; отметка переживает, потому что едет вместе с самим деревом.

Чем подтверждено. Ветка work/skorost, коммиты c903983 (флаг сборки) и 2854d2b (отметка типа). Стенд benchmarks/speed, 11 кругов, медианы, сборки чередуются внутри круга; машина в этот раз была тихая, разброс 1–3 % вместо обычных 30 %.

задачабылопосле флагапосле обеихраз
коллатц596,8396,2132,54,50
нод149,6153,478,61,90
сортировка240,9201,7178,81,35
строки441,8398,5334,91,32
дерево635,5637,9556,41,14

Вклад по отдельности: флаг сборки 1,14 раза, отметка типа ещё 1,55.

Чем ограничено, и это ограничение стоило отдельной работы. Отметка снимает не проверку тега, а МЕЖМОДУЛЬНЫЙ ВЫЗОВ: сверка тега печатается одним if в теле вызывающего. Первая версия снимала и её, опираясь на дверь входа, — и прогон корпуса нашёл, что дверь сверяет не всё: параметр полиморфизма она пропускает, и через него чужое значение доезжает до доказанного места. Разбор — a-dropped-type-check-gives-a-wrong-answer. Цена честности 2 % по среднему.

Необязательное поле (иногда является число) числом не считается вовсе: значение там может быть «ничто», и вызов помощника остаётся целиком.

Связано: biggest-win-for-least-work, slower-than-python-by-1-4, a-dropped-type-check-gives-a-wrong-answer, lto-speeds-up-the-build-too, byte-for-byte-comparison