Может ли gcc/clang оптимизировать вычисления инициализации?
Недавно я написал инструмент генератора синтаксических анализаторов, который принимает грамматику BNF (в виде строки) и набор действий (в виде массива указателей на функции) и выводит синтаксический анализатор (= автомат состояний, размещенный в куче). Затем я использую другую функцию, чтобы использовать этот анализатор для моих входных данных и генерирует абстрактное синтаксическое дерево.
В первоначальном поколении парсера было довольно много шагов, и мне было интересно, способны ли gcc или clang оптимизировать это, учитывая постоянные входные данные для функции генерации парсера (и никогда не используя значения указателей, только разыменовывая их)? Можно ли запустить функцию во время компиляции и встроить результат (он же выделенная память) в исполняемый файл?
(очевидно, для этого использовалась бы оптимизация времени компоновки, поскольку компилятор должен был бы иметь возможность проверить, что вся функция действительно имеет одинаковый результат с теми же параметрами)
1 ответ
В этом случае вы могли бы иметь код, который генерирует код.
Создайте исходный генератор синтаксического анализатора как отдельный фрагмент кода, который выполняется независимо. Результатом этого кода будет заголовочный файл, содержащий набор определений переменных, инициализированных правильными значениями. Затем вы используете этот файл в своем основном коде.
В качестве примера предположим, что у вас есть программа, которая должна знать количество битов, которые установлены в данном байте. Вы можете сделать это вручную, когда вам нужно:
int count_bits(uint8_t b)
{
int count = 0;
while (b) {
count += b & 1;
b >>= 1;
}
return count;
}
Или вы можете создать таблицу в отдельной программе:
int main()
{
FILE *header = fopen("bitcount.h", "w");
if (!header) {
perror("fopen failed");
exit(1);
}
fprintf(header, "int bit_counts[256] = {\n");
int count;
unsigned v;
for (v=0,count=0; v<256; v++) {
uint8_t b = v;
while (b) {
count += b & 1;
b >>= 1;
}
fprintf(header, " %d,\n" count);
}
fprintf(header, "};\n");
fclose(header);
return 0;
}
Это создаст файл с именем bitcount.h, который выглядит следующим образом:
int bit_counts[256] = {
0,
1,
1,
2,
...
7,
};
Это вы можете включить в свой "реальный" код.