Рабочим названием платформы .NET было |
Динамическая генерация кода
Оптимизация линейных участков кода
Зачастую бывает удобно разделить фазы генерации и оптимизации кода. Это позволяет существенно упростить генератор, сделать его независимым от оптимизатора и, кроме того, повторно использовать оптимизатор с другими генераторами.
Существует большое количество методов оптимизации, но в контексте динамической генерации кода, требующей быстрой работы оптимизатора, не все эти методы применимы. Поэтому мы рассмотрим один из самых простых методов - так называемую peephole-оптимизацию.
Суть peephole-оптимизации заключается в том, что оптимизатор ищет в коде метода сравнительно короткую последовательность инструкций, удовлетворяющую некоторому образцу, и заменяет ее более эффективной последовательностью инструкций.
Алгоритм peephole-оптимизации использует понятие фрейма. Фрейм можно представить как окошко, двигающееся по коду метода. Содержимое фрейма сравнивается с образцом, и в случае совпадения выполняется преобразование (см. рис. 5.1).
Peephole-оптимизация линейного участка кода должна выполняться многократно до тех пор, пока на очередном проходе фрейма по этому участку кода не будет найдено ни одного образца. С другой стороны, алгоритм peephole-оптимизации может быть остановлен в любой момент, что позволяет добиться требуемой скорости работы оптимизатора.
В таблице 5.3 приведен список некоторых образцов и замен, которые можно использовать для peephole-оптимизации CIL-кода.
Образец | Замена |
---|---|
stloc(starg) x ldloc(Ldarg) х |
dup stloc(starg) x |
ldloc(ldarg) x ldloc(ldarg) x |
ldloc(ldarg) x dup |
ckfinite ckfinite |
ckfinite |
not(neg) pop |
pop |
add(sub, mul, div,...) pop |
pop pop |
idc.i4.0 add(sub) |
- |
ldloca(ldarga) x initobj int32 |
idc.i4.0 stloc(starg) x |
stloc(starg) x ldloc(ldarg) y ldloc(ldarg) x add (или любая коммутативная бинарная операция) |
dup stloc(starg) x ldloc(ldarg) y add (или любая коммутативная бинарная операция) |