Рабочим названием платформы .NET было |
Динамическая генерация кода
Оптимизация кода, содержащего развилки
Рассмотрим несколько простых методов оптимизации кода, содержащего развилки, а именно:
- удаление избыточных инструкций сохранения значений в переменных;
- удаление псевдонимов переменных;
- воспроизведение констант;
- удаление неиспользуемых переменных.
Хороших результатов можно достичь, если применять эти методы в совокупности с peephole-оптимизацией. При этом получаемая цепочка оптимизирующих преобразований должна выполняться над одним и тем же кодом многократно до тех пор, пока не будет достигнута неподвижная точка.
Удаление избыточных инструкций сохранения значений в переменных
Это преобразование уменьшает количество присваиваний. Оно осуществляется только для переменных, адреса которых не используются. Под переменными мы будем понимать как локальные переменные, так и параметры методов.
Другими словами, избыточные инструкции stloc и starg удаляются только для переменных, не использующихся в инструкциях ldloca и ldarga.
Для обнаружения избыточных инструкций сохранения значений выполняется анализ использования переменной, состоящий из двух фаз:
- Построение графа использования переменной.
- Анализ графа использования переменной.
Инструкции ldloc(ldarg) X и stloc(starg) X будем называть инструкциями использования переменной X.
Мы будем говорить, что в графе потока управления инструкция использования B следует за инструкцией использования A на пути w, если:
- инструкции A и B используют одну и ту же переменную X ;
- путь w соединяет A и B ;
- путь w не содержит ни одной инструкции использования переменной X, кроме инструкций A и B.
Граф использования переменной X - это ориентированный граф, в узлах которого находятся инструкции использования переменной X, а дуги задают отношение следования для этих инструкций. То есть, если инструкция B следует за инструкцией A на каком-либо пути в графе потока управления, то в графе использования переменной X имеется дуга от инструкции A к инструкции B.
Анализ графа использования переменной заключается в нахождении таких инструкций stloc(starg), за которыми не следует ни одной инструкции ldloc(ldarg). Эти инструкции являются избыточными и заменяются инструкциями pop.
На рисунке 5.3 изображен пример графа использования переменной. Серым цветом обозначены избыточные инструкции stloc.
Удаление псевдонимов переменных
Это преобразование позволяет избавиться от лишних присваиваний и уменьшает количество локальных переменных. Под переменной будем понимать, опять же, как локальные переменные, так и параметры методов.
Переменная Y является псевдонимом переменной X тогда и только тогда, когда:
- переменная X используется в теле метода только один раз, причем в инструкции ldloc(ldarg) X ;
- за инструкцией ldloc(ldarg) X непосредственно следует инструкция stloc(starg) Y (впрочем, допускается наличие между ними любого количества инструкций dup ). Причем инструкция stloc(starg) Y является первым использованием переменной Y (назовем ее инструкцией инициализации переменной Y ).
Схема удаления псевдонима Y переменной X показана на рис. 5.4. При удалении осуществляются два действия:
- Инструкция инициализации переменной Y заменяется инструкцией pop.
- Все использования переменной Y заменяются использованиями переменной X.
Воспроизведение констант
Это преобразование позволяет избавиться от переменных, имеющих константное значение.
Переменная Y имеет константное значение C тогда и только тогда, когда:
- первым использованием переменной Y является инструкция stloc(starg) Y (назовем ее инструкцией инициализации переменной Y );
- инструкция инициализации переменной Y непосредственно следует за инструкцией ldc C (любая инструкция загрузки константы на стек вычислений). Впрочем, допускается наличие между ними любого количества инструкций dup ;
- за исключением инструкции инициализации, переменная Y используется только в инструкциях ldloc(ldarg) Y.
Схема воспроизведения константы C, являющейся значением переменной Y, показана на рисунке 5.5. При воспроизведении осуществляются два действия:
- Инструкция инициализации переменной Y заменяется инструкцией pop.
- Инструкции ldloc(ldarg) Y заменяются инструкциями ldc C.
Удаление неиспользуемых переменных
Если некоторая переменная не используется в графе метода или встречается только в инструкциях stloc(starg), то она удаляется. При этом все инструкции stloc(starg), использующие эту переменную, заменяются инструкциями pop.