Когда загружается, хранится и размещается в LLVM - PullRequest
0 голосов
/ 26 мая 2018

Я смотрю на LLVM, чтобы увидеть, как они используют load, store и alloca.На первом слайде ниже их нет смысла.Во втором случае используется alloca.

. Я не знаком с C, поэтому мне придется набрать скорость, чтобы запустить пример и самому разобраться, но я хотел спроситьесли кто-нибудь уже знал.Не уверен, какой пример кода C нужно написать, чтобы определить вывод, который использует load, store и alloca в LLVM.

Вопрос в том, когда LLVM использует load,store и alloca.

Интересно, нужна ли загрузка / хранение, или LLVM может обойтись без него.

Рисунок 1 ↓

enter image description here

Рисунок 2 ↓

enter image description here

Ответы [ 2 ]

0 голосов
/ 26 мая 2018

alloca выделяет память в локальном фрейме функции.Необходимо создать переменную, адрес которой берется, как в этом примере:

void foo(int* ptr) {
    *ptr = 4;
}

int main() {
    int value = 0;
    foo(&value);
    printf("%i\n", value); // 4
}

Если она не встроена foo, тогда LLVM потребуется инструкция alloca в main длясоздать память, которая поддерживает переменную value.foo необходимо использовать store, чтобы поместить 4 по адресу, на который указывает ptr, а затем main необходимо использовать load для загрузки содержимого value после того, как оно было изменено с помощью foo.

Компиляторы для языков семейства C обычно предпочитают начинать с использования alloca для каждой переменной в фрейме функции, а затем позволяют LLVM оптимизировать значения alloca s для значений SSA.Во многих случаях компилятор может преобразовывать переменные alloca в значения SSA, как показывает функция ssa2.Форма SSA может представлять переменные, которые удовлетворяют следующим двум условиям:

  • их адреса не заняты
  • их размер фиксирован

"Получение адреса переменной - это операция, которой нет в Javascript / Ruby, поэтому вам, возможно, придется разбираться в C, чтобы понять, что это значит.Это очень часто встречается в C и C ++.

«Фиксированный размер» означает, что компилятор заранее знает, сколько памяти ему нужно для конкретной структуры данных.Например, он всегда знает простые числа, но массивы часто имеют переменный размер.Массивы, размер которых неизвестен во время выполнения, могут быть выделены с помощью alloca или malloc, а затем вам нужно получить доступ к их содержимому с помощью load и store.

Наконец, обратите внимание, чтоваш второй пример не работает: он читает неинициализированное значение, и если вы скомпилируете его с более высокими уровнями оптимизации, вы просто получите ret i32 undef.

0 голосов
/ 26 мая 2018

Без оптимизации clang создаст код LLVM, в котором есть один alloca для каждой локальной переменной, один read для каждого использования этой переменной в качестве значения r и один store для каждого присвоения этой переменной (включаяего инициализация).

При оптимизации clang попытается свести к минимуму число read s и store и, если возможно, будет часто полностью исключать alloca (используя только регистры).

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

Интересно, если загрузка / сохранениетакже необходимо, или LLVM может обойтись без него.

Вам нужно store / load всякий раз, когда вы пишете в ячейки памяти.Поэтому возникает вопрос, можно ли обойтись без памяти, сохраняя все в регистрах.Поскольку LLVM (в отличие от реальных машин) поддерживает бесконечное количество регистров, это правильный вопрос.

Однако, как я уже говорил, регистры не имеют адресов.Поэтому любой код, который принимает адрес переменной, должен использовать память.То же относится и к любому коду, выполняющему арифметику с адресами, например коду, который индексирует массивы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...