Вычисление живучести массивов и других не скаляров в низкоуровневом промежуточном коде - PullRequest
0 голосов
/ 22 февраля 2019

У меня проблемы с тем, чтобы обернуть голову вокруг концепции вычисления живучести массива, поскольку они не являются скалярными значениями.Во всех книгах и курсах, в которых говорится о живучести, всегда используются только скалярные значения, но не-скаляры, похоже, нуждаются в том, чтобы их живучесть рассчитывалась по-разному, например, когда элемент массива определяется присваиванием, что не обязательно означает, что весь массив больше не существует до этой точкикак это происходит со скалярными значениями.Чтобы еще больше усложнить ситуацию, вы можете получить доступ только к определениям и использованию массива в высокоуровневом промежуточном коде, когда мы переходим на более низкие уровни, эта информация частично исчезает.Кто-нибудь имеет какие-либо идеи, как это сделать?

Редактировать: Моя конечная цель состоит в том, чтобы создавать графы помех для раскраски графов стековых фреймов, чтобы минимизировать их размер, поэтому мне понадобится информация о живучести или диапазонах, чтобы быть точным,Проблема действительно состоит из двух частей.Во-первых, как мы вычисляем живучесть нескалярных значений в промежуточном коде высокого уровня, во-вторых, как мы переводим это решение в версию промежуточного кода низкого уровня.

Редактировать: Вот пример проблемы в C,хотя в AST или промежуточном коде высокого уровня это будет очень похоже.

void testFunction() {
    int n;
    int i[100]; // array is declared here

                // array is dead before this point
    i[10] = n;  // array elements are used/defined here, the array is live
    n = i[11];  // array elements are used/defined here, array is still live


    // other code here

    i[12] = n;  // array elements are used/defined here, array is still live
    i[13] = n;  // array elements are used/defined here again but for the            
                // last time, after this the array is not live
 }

В промежуточном коде низкого уровня доступ к массиву разбивается на множество инструкций, и после оптимизации мы можем потерять детализацию именно тогда, когдаЭлементы массива используются и определяются, потому что инструкции могут быть несколько зашифрованы, так что это станет немного беспорядком.добавьте метаданные к инструкциям разыменования низкого уровня, чтобы получить определения и использование нескаляров в промежуточном коде низкого уровня, как показано ниже.

t0 = &i // this would not count as a use since it is only the 
        // address of the array i

n = *t0 // use of i
*t0 = n // definition of i

Это только оставляет проблему извлечения жизненных / живых диапазонов нескаляры.Скалярная живучесть рассчитывается как проблема обратного потока данных, переменная становится действительной, когда ее использование замечено, и умирает, когда мы сталкиваемся с ее определением.Что касается нескалярной жизнедеятельности, то ее время жизни, похоже, должно расширяться от первого определения или использования, с которым встречаются, до последнего определения, встречающегося на каждом пути потока.Я думаю о том, чтобы сначала рассчитать определения нескалярных значений, а затем использовать их для вычисления цепочек def-use и use-def, а затем объединить все цепочки use-def вместе в один действующий диапазон.Я думаю, что это дало бы надлежащие действующие диапазоны для любого не скаляра, если его начальное определение не было сделано вне функции ?, В этом случае оно будет жить вплоть до точки входа в функцию.Так что это не сработает для глобалов, но в любом случае они будут считаться всегда живыми, и не нужно рассчитывать их живучесть.Я что-то пропустил?и кто-нибудь может придумать лучший способ сделать это?

1 Ответ

0 голосов
/ 22 февраля 2019

Анализ живучести всегда является консервативной оценкой.«Живая» переменная вполне может никогда не использоваться.(Его будущее использование может быть условным, даже на основе условий, значения которых могут быть уже определены.) Важно только то, что переменная, не являющаяся живым, гарантированно не понадобится.Чем точнее анализ, тем больше будет возможностей для оптимизации, но здесь есть компромисс: более точный анализ может оказаться чрезмерно дорогим по сравнению с возможной добавленной стоимостью.

В этом свете стоит спросить, чтозначение может быть сгенерировано, зная, что часть массива не является живой.Например, только в очень необычных случаях можно перерабатывать часть массива.

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

Может быть полезно узнать значение определенного элемента массива, но даже там его часто считают достаточным, чтобы знать, чтовесь массив не будет видоизменяться, вместо того, чтобы пытаться отслеживать изменчивость отдельных элементов.Если известно, что массив является неизменным, можно определить значение элемента по известному индексу, что позволяет сворачивать выражения в константу, используя таблицы поиска.Некоторые компиляторы определенно делают это, но опять-таки существует компромисс между сложностью и добавленной стоимостью, и абсолютная точность не требуется в тех случаях, когда было бы трудно или невозможно выполнить полностью точный анализ.

...