stringtranslate.com

Алгоритм Сети–Ульмана

В информатике алгоритм Сети–Ульмана — это алгоритм, названный в честь его создателей Рави Сети и Джеффри Д. Ульмана , для перевода абстрактных синтаксических деревьев в машинный код , использующий как можно меньше регистров .

Обзор

При генерации кода для арифметических выражений компилятор должен решить, какой из способов лучше всего перевести выражение с точки зрения количества используемых инструкций, а также количества регистров, необходимых для оценки определенного поддерева. Особенно в случае, когда свободных регистров мало, порядок оценки может быть важен для длины сгенерированного кода, поскольку различные упорядочения могут привести к большему или меньшему количеству промежуточных значений, которые будут сброшены в память и затем восстановлены. Алгоритм Сети-Ульмана (также известный как нумерация Сети-Ульмана ) создает код, которому требуется как можно меньше инструкций, а также как можно меньше ссылок на хранилище (при условии, что в лучшем случае коммутативность и ассоциативность применяются к используемым операторам, но дистрибутивные законы ie не выполняются). Алгоритм также успешно выполняется, если ни коммутативность , ни ассоциативность не выполняются для используемых выражений, и, следовательно, арифметические преобразования не могут быть применены. Алгоритм также не использует преимущества общих подвыражений и не применяется напрямую к выражениям, представленным в виде общих направленных ациклических графов, а не деревьев.

Простой алгоритм Сети–Ульмана

Простой алгоритм Сети–Ульмана работает следующим образом (для архитектуры загрузки/сохранения ):

  1. Обход абстрактного синтаксического дерева в прямом или обратном порядке
    1. Для каждого конечного узла, если это неконстантный левый дочерний узел, присвойте 1 (т.е. для хранения переменной/поля и т.д. необходим 1 регистр), в противном случае присвойте 0 (это неконстантный правый дочерний узел или константный конечный узел (правая часть операции – литералы, значения)).
    2. Для каждого нелистового узла, если левому и правому поддеревьям соответственно требуется разное количество регистров l и r , то назначаем max( lr ), в противном случае назначаем r  + 1.
  2. Чтобы выдать код, если поддеревьям требуется разное количество регистров, сначала оценивается поддерево, которому требуется больше всего регистров (поскольку регистр, необходимый для сохранения результата одного поддерева, может привести к тому, что другой будет сброшен ), в противном случае порядок не имеет значения.

Пример

Для арифметического выражения абстрактное синтаксическое дерево выглядит следующим образом:

 = / \ а * / \ / \ + + / \ / \ / \ д 3 + * / \ / \ бкфг

Чтобы продолжить работу с алгоритмом, нам нужно только проверить арифметическое выражение , т.е. нам нужно посмотреть только на правое поддерево присваивания '=':

 * / \ / \ + + / \ / \ / \ д 3 + * / \ / \ бкфг

Теперь мы начинаем обход дерева (пока в прямом порядке), назначая количество регистров, необходимых для вычисления каждого поддерева (обратите внимание, что последнее слагаемое в выражении является константой):

 * 2 / \ / \ + 2 + 1 / \ / \ / \ д 1 3 0 + 1 * 1 / \ / \ б 1 в 0 е 1 г 0

Из этого дерева видно, что нам нужно 2 регистра для вычисления левого поддерева '*', но только 1 регистр для вычисления правого поддерева. Узлы 'c' и 'g' не нуждаются в регистрах по следующим причинам: если T является листом дерева, то количество регистров для вычисления T равно 1 или 0 в зависимости от того, является ли T левым или правым поддеревом (поскольку такая операция, как add R1, A, может обрабатывать правый компонент A напрямую, не сохраняя его в регистре). Поэтому мы начнем сначала выдавать код для левого поддерева, потому что мы можем столкнуться с ситуацией, когда у нас останется только 2 регистра для вычисления всего выражения. Если бы мы теперь сначала вычислили правое поддерево (которому нужен только 1 регистр), то нам тогда понадобился бы регистр для хранения результата правого поддерева при вычислении левого поддерева (которому все еще нужны 2 регистра), поэтому нам одновременно понадобилось бы 3 регистра. Для вычисления левого поддерева сначала требуется 2 регистра, но результат можно сохранить в 1, а поскольку для вычисления правого поддерева требуется только 1 регистр, для оценки выражения можно обойтись всего 2 оставшимися регистрами.

Расширенный алгоритм Сети-Ульмана

В расширенной версии алгоритма Сети–Ульмана арифметические выражения сначала преобразуются с использованием алгебраических свойств используемых операторов.

Смотрите также

Ссылки

Внешние ссылки