stringtranslate.com

Достижение определения

В теории компиляторов достигающее определение для данной инструкции — это более ранняя инструкция, целевая переменная которой может достичь (быть назначена) данной без промежуточного назначения. Например, в следующем коде:

d1 : у := 3d2 : х := у

d1является идущим определением для d2. В следующем примере, однако:

d1 : у := 3d2 : у := 4d3 : х := у

d1больше не является определением достижения для d3, поскольку d2убивает его достижение: значение, определенное в , d1больше недоступно и не может достичь d3.

Как анализ

Аналогично названные определения достижения — это анализ потока данных , который статически определяет, какие определения могут достичь заданной точки в коде. Из-за своей простоты он часто используется как канонический пример анализа потока данных в учебниках. Используемый оператор слияния потока данных — это объединение множеств, а анализ — прямой поток. Определения достижения используются для вычисления цепочек использования-определений .

Уравнения потока данных, используемые для данного базового блока при достижении определений, следующие:

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

Для общей инструкции мы определяем наборы и следующим образом:

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

Алгоритм рабочего списка

Достижение определения обычно рассчитывается с использованием итеративного алгоритма рабочего списка.

Вход: граф потока управления CFG = (Узлы, Ребра, Вход, Выход)

// Инициализация для всех узлов CFG n в N , OUT [ n ] = emptyset ; // можно оптимизировать с помощью OUT[n] = GEN[n];          // помещаем все узлы в измененный набор // N — все узлы в графе, Changed = N ;  // Итерация while ( Changed != emptyset ) { выбрать узел n в Changed ; // удалить его из измененного набора Changed = Changed - { n } ;                 // инициализируем IN[n] как пустой IN [ n ] = emptyset ;    // вычислить IN[n] из OUT[p] предшественников для всех узлов p в предшественниках ( n ) IN [ n ] = IN [ n ] Union OUT [ p ];            oldout = OUT [ n ]; // сохраняем старый OUT[n] // обновляем OUT[n] с помощью передаточной функции f_n() OUT [ n ] = GEN [ n ] Union ( IN [ n ] - KILL [ n ]);            // есть ли изменения в OUT[n] по сравнению с предыдущим значением? if ( OUT [ n ] changed ) // сравнить oldout с OUT[n] { // если да, поместить всех последователей n в измененный набор для всех узлов s в successors ( n ) Changed = Changed U { s }; } }                     

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

Дальнейшее чтение