Оптимизатор СПФ. Инлайн подстановщик. Оптимизатор вызывается инлайн подстановщиком INLINE, . Вернее, _INLINE,. Инлайн подстановщик представляет собой M_WL цикл: : M_WL CS-DUP POSTPONE WHILE ; IMMEDIATE метод шага _INLINE, определяется подбором кода. Некоторая оптимизация инлайн подстановщиком, он обеспечивает отложением модификации регистра указателя на верщину стека данных. Вернее, на оставшуюся часть стека, так как EAX истользуется в качестве ТОСа. С помощью -EVEN-EBP удаляет инструкцию LEA ebp, OFF-EBP [EBP], а индекс при [EBP] заносится в переменную +>OFF-EBP. В конце инлайн подстановщики, процедура EVEN-EBP восстанавливает эту инструкцию. В процессе инлайн подстановки, индекс при [EBP] модифицируется в соответствии с переменной +>OFF-EBP. Инструкция LEA ebp, OFF-EBP [EBP] воспринимается инлайном как модификация переменой +>OFF-EBP. Функция INLINE? оценивает CFA на возможность инлайн подстановки аналогичным методом подбора кода. Если все инструкции от CFA до машинного кода RET прописаны в цепочки сравнений и размер фрагмента от CFA до RET менще значения переменной MM_SIZE то функция INLINE? возвращает разрешение для инлайн-подстановки. Определение COMPILE, имеет вид: : COMPILE, \ 94 CORE EXT \ Интерпретация: семантика не определена. \ Выполнение: ( xt -- ) \ Добавить семантику выполнения определения, представленого xt, к \ семантике выполнения текущего определения. CON>LIT IF INLINE? IF INLINE, ELSE _COMPILE, THEN THEN ; CON>LIT пытается некоторые CFA (типа константы) представить в виде литерала. Оптимизация OPT_ вызывается на каждом шаге инлайн подстановки. В свою очередь OPT_ вызывает в цикле OPT-RULES. OPT-RULES представляет собой последовательность правил. Правила состоят из анализатора и модификатора. Модификатор модифицирует последний фрагмент компилируемого кода. Аанализатор проверяет возможность применения правила. OPT-RULES возыращвет FALSE если проебразование было и есть смысл попробывать еще раз выполнить OPT-RULES. Т.о. крупное преобразование может быть выражено множеством иелких. Наблюдение работы оптимизатора. Для этой задачи, потребуется экземпляр СПФ системы использующий векторное слово DTST. Для этого надо файле src\tc_spf.F определить M\ как пустое слово : M\ ( POSTPONE \) ; IMMEDIATE и пересобрать систему. В качестве параметра на вход DTST подается номер правила. По умолчанию, к качестве заглушки, DTST инициализирован командой DROP . Включение наблюдения производится путем инициализации слова DTST словом DoDTST: REQUIRE DoDTST ~mak\OptTr.f : ZZZ [ ' DoDTST TO DTST ] 5 < 0= IF THEN ; Клавиша 'Q' - ABORT 'D' - вызов файла по имени DDD.F остальнве - шаг трассировки. Добавление жёстких правил. Жёсткие правила представляет собой обднозначную занену одного кода на эквивалентный. На пример: DUP C@ C3 XOR OP1 @ W@ CA8B XOR OR \ 582148 8BCA MOV ECX , EDX OP0 @ W@ C12B XOR OR \ 58214A 2BC1 SUB EAX , ECX 0= IF M\ 180 DTST C22B OP1 @ W! \ SUB EAX , EDX OP0 OPexcise FALSE M\ 181 DTST EXIT THEN Выработка условия перед IF является анализатором данного правила. На входе анализатора на стеке лежит текущий указатель на источник кода инлайн подстановки. Указание на код 0xC3 (RET) означает что мы в конце инлайн подстановки и значение в ECX не подлежит дальнейшему использованию. OP0 и OP1 указатели на 0й и 1й элементы массива ссылок на инструкции . 0й элемент указывает на последнюю инструкцию, 1й на предпоследнюю и т.д. Массива ссылок на инструкции введен ради отличия кода команды от операндов при рассмотрении машинного кода задом на перед. Указатель с максимальным номером в анализаторе определяет размер фрагмента в количестве инструкций. При этом, мы абстрагируемся от реального размера (в байтах). Правила в программе OPT-RULES распределены по размеру фрагментов кода с которыми они работаю. Сначала идут правила для коротких фрагментов потом для длинных. Строки вида: OP1 @ :-SET U< IF TRUE EXIT THEN OP2 @ :-SET U< IF TRUE EXIT THEN OP3 @ :-SET U< IF TRUE EXIT THEN OP4 @ :-SET U< IF TRUE EXIT THEN (без разделителей в начале строки) являются границами между группами правил объединенных по размеру фрагментов, которые они обрабатывают. Новое правило следует занести в конец своей группы. Где :-SET переменная содержащая указатель ограничивающий область оптимизации. Тут надо учесть, что для фрагментов оканчивающихся записью в EAX существует своя программа содержащая правила - ?EAX=RULES . Для каждого из фрагментов соответствующих одному из следующих условий: OP0 @ W@ ADD|XOR|OR|AND= \ $ 4444 OR OP0 @ W@ 558B = \ MOV EDX , X [EBP] OP1 @ W@ 453B = \ CMP EAX , X [EBP] отведена своя область в теле условного оператора. Для генерации анализатора жёстких правил можно использовать средство наблюдения работы оптимизатора, по средствам вызова файла DDD.F ( Клавиша 'D' ). При этом DDD.F должен содержать программу генерации анализатора. Типа: CR .( DUP C@ C3 XOR) .WOP1 .WOP0 Где .WOP0 .WOP1 генерируют части анализатора для последней и предпоследней инструкций интересуемого фрагмента кода. .WOP0 .WOP1 определены в devel\~mak\DOP.F префикс W означает 2-байтный шаблон. Для создания преобразователя мозно использовать уже существующие преобразователи в качестве прототипа. Абстрагирование. Чаще всего используется абстрагированме от глубины стека: OP1 @ 2 + C@ OP0 @ 2 + C@ XOR \ ?xx=yy OP1 @ W@ 4503 XOR OR \ 034500 ADD EAX , yy [EBP] OP0 @ W@ 558B XOR OR \ 8B5500 MOV EDX , xx [EBP] 0= IF M\ 288 DTST 558B OP1 @ W! \ MOV EDX , xx [EBP] C203 OP0 @ W! \ ADD EAX , EDX -1 ALLOT FALSE M\ 289 DTST EXIT THEN xx и yy - глубины стека. Для данного правила, должны быть равными. можно также абстрагироваться от кода команды: OP1 @ 2+ C@ OP0 @ 2+ C@ XOR OP1 @ W@ 5589 XOR OR \ 8955F8 MOV F8 [EBP] , EDX OP0 @ W@ FFC7 AND 4503 XOR OR \ 0B45F8 ADD|OR|ADC|SBB|AND|SUB|XOR|CMP EAX , F8 [EBP] 0= IF M\ B2 DTST C2 OP0 @ 1+ C! \ OR EAX , EDX -1 ALLOT FALSE M\ B3 DTST EXIT THEN в данном случае от 3-х битов кода-команды определяемых маской 0xFFC7 Соответственно, 8 вариантов кода-команд. Модификация фрагментов кода неопределенного размера. Относительно простым примером является лишнее восстановление регистра EAX со стеке. При том, что после сохранения EAX на стеке его никто не модифицировал. Т.е. фрагмент представляет собой пару MOV X [EBP], EAX MOV EAX, X [EBP] проложенных машинным кодом не содержащем модификацию содержимого регистра EAX Анализатор данного правила представляет собой цикл, который пробегает по массиву ссылок на инструкции и вызывая XX_STEP . XX_STEP продвигает указатель и проверяет инструкции на которые этот указатель косвенно указывает. Если очередная инструкция найдена среди среди допустимых образцов - поиск продолжается иначе завершается с отказом. Если встречается MOV X [EBP], EAX - поиск завершается с разрешением удалить последнюю инструкцию. Если между MOV X [EBP], EAX MOV EAX, X [EBP] встречается запись в регистр EAX , то в данном промежутке, EAX можно заменить другим регистром. Программа DO_EAX>ECX производит замену EAX на ECX . С помощью ?EAX>ECX проверяется возможность произвести данное преобразование. В переменную ?~EAX заносится флаг необходимости добавления инструкции MOV EAX , ECX . Преобразование осуществляется от найденной MOV X [EBP], EAX в направлении исполнения. С помощью EAX>ECX0 пропускаются инструкции не меняющие EAX. Далее с помощью EAX>ECX производится подмена EAX на ECX во всех последующих инструкциях. Перед компиляцией условного перехода используется специальный набор правил содержащейся в процедуре ?BR-OPT-RULES . При этом, учитывается данная специфика связанная с созданием флагов условного перехода. Есть некоторый забег на оптимизацию нелинейного участка кода RESOLVE_OPT . Пока замена длинного перехода вперед на короткий (там где это допустимо). Но по моему, на данном этапе не до этого.