Я хотел бы видеть дизассемблированный код в том же порядке, который генерирует компилятор после переназначения инструкций. b.t.w я использую GDB и когда я даю команду, говорящую disas /m FunctionName
это дает мне разобранный код в порядке исходного кода. Я пытаюсь посмотреть на эффективность перепланирования инструкций моим компилятором (GCC 4.1) и хотел бы посмотреть, как перепланированы инструкции.
Спасибо!
////////////////// редактирует /////////////////////////////// /////////
После просмотра дизассемблированного кода для строки кода:
double w_n = (A_n[2] * x[0] + A_n[5] * y + A_n[8] * z + A_n[11]) ;
Я мог видеть его 83 байта инструкции. Но после разворачивания его на 2 итерации:
double w_n[2] = { (A_n[2] * x[0] + A_n[5] * y + A_n[8] * z + A_n[11]), (A_n_2[2] * x[0] + A_n_2[5] * y + A_n_2[8] * z + A_n_2[11]) };
Блок кода составляет 226 байтов. И существует огромное увеличение количества команд. Кто-нибудь может сказать мне, почему это происходит? Я также вижу из VTune, что инструкции, удаленные после развертывания, увеличились.
Возможная причина, по которой я мог бы подумать: компилятор получает достаточно возможностей с увеличенным размером блока для генерации простых инструкций, поэтому максимизирует пропускную способность блока предварительной выборки и декодирования инструкций.
Любая помощь с благодарностью. Спасибо!!
Если перепланирование было выполнено компилятором, вы действительно должны увидеть это при разборке в gdb.
В противном случае вы можете, возможно, использовать objdump
непосредственно в командной строке, это мой предпочтительный способ просмотра кода в ELF:
$ objdump --disassemble a.out | less
Он вообще не ссылается на источник, поэтому он должен действительно показывать, что находится в самом бинарном файле.
На этапе, на котором вы компилируете код в объектный файл, вы также можете просто сообщить драйверу GCC (gcc
) что вы хотите получить ассемблерный код:
gcc -S -c file.c
gcc -O2 -S -c file.c
gcc -S -masm=intel -c file.c
(последний генерирует Intel вместо AT&T синтаксическая сборка)
Вы даже можете затем выбросить этот ассемблерный код в ассемблер (например, gasm
) позже, чтобы получить объектный файл, который можно связать.
Относительно того, почему код больше, есть ряд причин. Эвристика, которую мы, люди, использовали для оптимизации сборки, уже давно не соответствует действительности. Одна большая цель — конвейеризация, другая векторизация. В общем, речь идет о максимально возможном распараллеливании и необходимости как можно меньше делать недействительными из (уже прочитанного) кэша в любой момент времени, чтобы ускорить выполнение.
Даже при том, что это кажется нелогичным, это может привести к большему, но более быстрому коду.