#compiler-construction
#построение компилятора
Вопрос:
В компиляторах фраза «циклически-инвариантное движение кода» описывает выражения или инструкции кода в цикле, которые не меняются от итерации к итерации и, следовательно, могут быть перемещены за пределы цикла для вычисления один раз.
Я понимаю «циклически-инвариантную» часть фразы, но что означает «движение кода»?
Ответ №1:
«Движение кода» просто означает, что код перемещается из цикла, поскольку не будет иметь никакого значения, выполняется ли он внутри цикла повторно или вне цикла один раз. Компилятор берет код, который не обязательно должен находиться в цикле, и перемещает его за его пределы в целях оптимизации.
Вот пример:
for ( int x=0; x < string.length(); x ) {
//other code here
}
Если компилятор знает, что ничто в цикле не изменяет длину строки, он может просто жестко запрограммировать длину строки в программе вместо того, чтобы вставлять фактический вызов метода length()
в соответствующую строку, потому что вызов метода всегда будет возвращать один и тот же результат и просто тратить память и процессорное время. Код для вызова метода перемещается перед циклом вместо того, чтобы оставаться внутри него. В статье это называется «движение кода», хотя я бы назвал это просто старой оптимизацией, поскольку большая часть оптимизации включает перемещение кода. 😀
Комментарии:
1. Возможно, я слишком придирчив. Я понимаю, что код перемещается за пределы цикла, но «движение» подразумевает непрерывное перемещение, тогда как «перемещение» подразумевает однократное изменение положения. Возможно, я слишком много вчитываюсь в эту фразу.
2. @Ross Я думаю, вы слишком много вникаете в это. движение кода было бы лучшим названием для этого, поскольку оно определенно не непрерывное. 🙂
Ответ №2:
Похоже, что из статьи в Википедии это означает, что инвариантный к циклу код фактически перемещается за пределы цикла в качестве шага оптимизации.
Ответ №3:
Термин «движение кода» может использоваться для любой ситуации, когда некоторый код перемещается куда-то еще, а семантика программы остается неизменной. Конечно, компилятор ожидает какого-то преимущества, такого как уменьшение давления в регистре, уменьшение размера кода, меньшее количество вычислений и так далее. Это очень общая оптимизация, которую легко описать, но очень сложно реализовать «хорошо». Случай движения кода, инвариантного к циклу, является тривиальным примером, когда множество вычислений просто удаляются, но для других ситуаций обычно намного сложнее сказать, какой подход является наилучшим для определенного ввода. Трудность заключается как в том, каковы все допустимые движения кода, так и в том, какие из них будут наилучшими, неоптимальными или, по крайней мере, полезными.