Каждый компилятор разрабатывается под конкретный процессор (или семейство процессоров) и его неотъемлемой чертой является завершающая оптимизация кода с учетом особенностей системы команд данного процессоры (Machine Specific Optimizations). Вариантов таких оптимизаций может быть очень много, они определяются особенностями архитектуры процессоров и системы команд, но их общими основными направлениями являются:
- сокращение накладных расходов на условные переходы: отказ от специальных команд проверки условий (типа cmp в ассемблере Intel), анализ флагов и выполнение условных переходов непосредственно по результатам арифметических и логических команд; выполнение операций по условию вместо выполнения условных переходов:
До машинной оптимизации на уровне команд | После машинной оптимизации на уровне команд |
a = a - 1; if ZERO jump 3: r1=2; r2 = 11; jump 4; 3: r1 = 3; 4: … | a = a - 1; if ZERO r1 = 3 if NOTZERO r1=2 if NOTZERO r2=11 … |
- замена доступа к элементам массива по индексам на доступ по указателям:
До машинной оптимизации на уровне команд | После машинной оптимизации на уровне команд |
p[0] = 0; p[1] = 1; p += 2; | *p++ = 0; *p++ = 1; |
Оптимизированный код более эффективен, поскольку не требует при каждом доступе к памяти каждый раз вычислять смещение относительно базового адреса начала массива элемента, соответствующего текущему индексу.
|
|
- замена условий в циклах по счетчику. Если переменная цикла не используется в теле цикла в качестве операнда, то для проверки условия завершения цикла вместо кода вида
До машинной оптимизации на уровне команд | После машинной оптимизации на уровне команд |
for (i=0; i<100; i++) a += random(); | for (i=100; i>0; i--) a += random(); |
Реализация второго варианта цикла всегда будет более эффективна, поскольку не требуется отдельная команда для сравнения с нулем. Каким является значение счетчика цикла после декрементирования можно определить сразу же по флагам. Это типичный пример Code Selection-оптимизации, когда две инструкции проверки и перехода заменяются на одну;
- попытка одновременного выполнения нескольких вычислительных операций в различных вычислительных устройствах (пример – многофункциональных инструкции в процессорах SHARC ADSP).