Разгрузка участков повторяемости

Такое название получил способ оптимизации, состоящий в вынесении вычислений из многократно проводимых (исполняемых) участков программы на участки программы, редко проходимые.

К этому виду преобразований относятся различные чистки зон, тел циклов и тел рекурсивных процедур, когда инвариантные (по результату выполнения) в соответствующих участках повторяемости выражения, линейные компоненты (т. е. гамаки, обязательно исполняемые при каждом прохождении участка повторяемости) выносятся из него и размещаются перед входом в участок повторяемости - чистка вверх,- или когда уничтожающие свои предыдущие результаты линейные компоненты или группы линейных компонент участка повторяемости выносятся из него и размещаются за выходы из участка повторяемости - чистка вниз.

При чистке вверх вынесенные вычисления образуют новый непосредственный обязательный предшественник участка повторяемости, а при чистке вниз - непосредственный обязательный преемник участка повторяемости.

Обычно выносятся только такие выражения и линейные фрагменты программы, которые обязательно исполняются при каждом прохождении разгружаемого участка повторяемости.

В группу разгрузок участков повторяемости также входят и различные преобразования, которые осуществляют перемещение гамака по пути, ведущему к месту использования его результатов.При таком преобразовании в отличие от чисток гамак остается в тех же зонах, циклах и процедурах.

СДВИГ ИНВАРИАНТНЫХ ОПЕРАТОРОВ

Рассмотрим подробнее преобразование сдвига инвариантных операторов, входящее в группу преобразований по разгрузке участков повторяемости.

Оператор инвариантен и может быть вынесен из блока, если он удовлетворяет следующим условиям:

1. Cдвиг оператора не приводит к тому, что результат сдвигаемого оператора перемещается через оператор, в котором результат используется.

Например, для блока (mi) * A,B.

(mk):= C,(mi), если ни A, ни B не определяются в области, то оператор mi может быть сдвинут вниз, но не может быть поставлен после опе-

ратора mk.

2. Cдвиг оператора не приводит к тому, что между определением переменной и ее использованием в качестве операнда появляется новый оператор, присваивающий этой переменной другое значение. Например, для блока

(mi):= A,1

(mj):= A,10

(mk):= C,A

Если больше никакой оператор после mj не присваивает значение переменной A, то оператор mj может быть сдвинут вниз, но не может быть поставлен после оператора mk, операторами mi, а также вверх, но не выше оператора, использующего значение переменной A, присвоенное оператором mi.

3. сдвиг оператора не нарушает связи между сдвигаемым оператором и оператором, использующим результат сдвигаемого в качестве операнда.

Таким образом, оператор инвариантен в области, если его операнды не зависят от места определения переменных в данной области.

Как уже отмечалось, сдвиг инвариантного оператора из тела цикла сокращает время выполнения программы. Особенность рассматриваемого метода заключается в том, что оператор сдвигается из блока во всех случаях, когда он может быть сдвинут независимо от того, находится он внутри цикла или нет. Ухудшение программы произойти не может.

Необходимо также отметить, что перед сдвигом инвариантных операторов нужно устранить идентичные операторы (об этом речь пойдет позже), так как они могут оказаться препятствием для сдвига операторов.

Рассмотрим условия, достаточные для сдвига операторов

I. Сдвиг оператора, не являющегося оператором присваивания, из области назад (на его входные пути) производится, если операнды оператора не зависят от места определения переменных в области, т.е.:

1. mi - идентификаторы, используемые в качестве аргумента оператора, не определены в блоке ни одним предшествующим оператором;

2. программные переменные оператора не определены в области. Если оба эти условия выполняются, то операнды оператора не зависят от места определения переменных в области.

II. Сдвиг оператора присваивания, из области назад (на его

входные пути) производится, если:

1. mi - идентификаторы, используемые в качестве аргумента оператора, не определены в блоке ни одним предшествующим оператором;

2. программные переменные, используемые в качестве операнда оператора не определены в области;

3. блок является артикуляционным, т.е. лежит на пересечении всех входных или всех выходных путей сильно связанной области;

4. не существует другого определения или использования программной переменной на любом пути от входа в область до этого определения.

 

III. Сдвиг оператора, не являющегося оператором присваивания, из области вперед (на его выходные пути) производится, если:

1. mi - идентификаторы, используемые в качестве аргумента оператора, не переопределяются ни на одном пути между оператором и точкой выхода из области;

2. программные переменные, используемые в качестве аргумента оператора не переопределяются ни на одном пути между оператором и точкой выхода из области;

3. mi - указатель, являющийся результатом действия оператора, не используется на пути между оператором и концом блока.

IV. Сдвиг оператора присваивания, из области назад (на его входные пути) производится, если:

1. mi - идентификаторы, используемые в качестве аргумента оператора, не переопределяются ни на одном пути между оператором и точкой выхода из области;

2. программные переменные, используемые в качестве аргумента оператора не переопределяются ни на одном пути между оператором и точкой выхода из области;

3. блок является артикуляционным пунктом области;

4. не существует другого определения программной переменной ни на одном пути между определением и точкой выхода из области;

5. программная переменная не используется в области.

ВСТАВКА ПСЕВДОБЛОКА

В процессе оптимизации операторы, сдвигаемые из блоков, собираются в псевдоблок. После оптимизации области Rk операторы псевдоблока должны быть вставлены в программу так, чтобы они выполнялись до (после) выполнения операторов области Ri.

Для того, чтобы операторы псевдоблока выполнялись на всех входных (выходых) путях области Rk, они должны вставляться во все блоки, непосредственно предшествующие (следующие) области либо из псевдоблока должен быть сформирован блок, который будет вставлен на все входные (выходные) пути области Rk.

Вставка операторов в существующие блоки или формирование из псевдоблока фактического блок выполняется по следующему алгоритму (алгоритм рассматривается для операторов, сдвинутых назад на входные пути, для операторов, сдвинутых вперед, алгоритм аналогичен):

1) операторы вставляются во все блоки, непосредственно предшествующие области, которые имеют только один непосредственно следующий блок. Вставляемые операторы записываются перед оператором перехода.

2) из псевдоблока создается формальный блок, который вставляется на всех входных путях, идущих от непосредственно предшествующих блоков, имеющих несколько преемников.

3) если входной блок программы принадлежит области Rk, то псевдоблок формируется в формальный блок и ставится на неявном пути между внешним и вызывающим оператором и начальным блоком.Это соответствует созданию нового блока.

4).Набор и последовательность оптимизирующих преобразований.

Каждый из способов оптимизации может быть реализован в виде отдельного преобразования. В то же время практика оптимизирующей трансляции показала, что все эти способы оптимивации, не совпадая друг с другом, реализуют во многом совпадающие процессы обработки программы, в основе которых лежит небольшое число более элементарных и фундаментальных преобразований программ.

Поэтому в реальных оптимизирующих трансляторах разнообразные наборы способов оптимизации программ сводятся к применению более простых преобразований в их сочетании друг с другом и с учетом их совокупного влияния на транслируемую программу.

Реально используемые наборы оптимизирующих преобразований не обладают свойством, позволяющим не следить за порядком применения преобразованнй. Обычно существуют ситуации, когда применение одного преобразования закрывает возможности применения другого (в этом случае говорят, что первое преобравование обладает тупиковостью по отношонию ко второму) или, наоборот, приводит к новым возможностям другого преобразования (т.о. обладает повторностью по отношению к нему).

Поэтому важным для имеющегося набора оптимизирующих преобразований (с точки зрения качества получаемой программы) представляется выбор порядка применения преобразований из набора. Нужно стремиться к тому, чтобы в последовательности применения любое преобразование не предшествовало преобразованию, по отношению к которому оно тупиково, но предшествовало преобравованию, по отношению к которому оно повторно.

Можно дать некоторые частные рекомендации по оптимизации циклов и линейных участков.

Оптимизацию циклов можно осуществлять в три прохода, расположенных между проходом обычного анализа, в котором получается внутреннее представление исходной программы, и проходом, генерирующим объектный код:

1) анализ циклов - выявление циклов, подлежащих оптимизации и получение необходимой для оптимизации информации;

2) вынесение за границу циклов инвариантных операций;

3) замена сложных операций.

Свертка или исключение лишних операций на линейных участках осуществляются непосредственно перед или в процессе обработки инвариантных операций.

ПРАКТИЧЕСКАЯ ЧАСТЬ


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: