Удаление общих подвыражений

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

Пример:

X, Y: ARRAY [1..10, 1..10] OF INTEGER

FOR I:=1 TO 10 DO

X[I, 2*J-1]:= Y[I, 2*J]

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

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

Примеру соответствует следующая последовательность четверок:

(1):= #1 I {инициализация цикла}

(2) JGT I #10 (20)

(3) - I #1 i1 {вычисление индексов для X}

(4) * i1 #10 i2

(5) * #2 J i3

(6) - i3 #1 i4

(7) - i4 #1 i5

(8) + i2 i5 i6

(9) * i6 #2 i7

(10) - I #1 i8 {вычисление индексов для Y}

(11) * i8 #10 i9

(12) * #2 J i10

(13) - i10 #1 i11

(14) + i9 i11 i12

(15) * i12 #2 i13

(16):= Y[i13] X[i7]

(17) + #1 I i14 {конец цикла}

(18):= i14 I

(19) J (2)

(20) {следующее предложение}

Четверки (5) и (12) совпадают, за исключением имени получаемого промежуточного результата. Операнд J не меняет своего значения между четверками (5) и (12). Таким образом, четверки (5) и (12) вычисляют одно и то же значение. Это означает, что мы можем удалить четверку (12) и заменить любые обращения к ее результату (i10) на обращение к переменной i3.

После замены i10 на i3 мы обнаружим, что четверки (6) и (13) также совпадают, за исключением имени результата. Следовательно, мы можем удалить четверку (13) и заменить i11 на i4.

Аналогично четверки (10) и (11) также могут быть удалены, поскольку они эквивалентны четверкам (3) и (4).

2. Удаление инвариантов цикла

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

Примером инварианта цикла является вычисление выражения 2*J (четверка 5).

Значение J в цикле не изменяется. Поэтому четверку (5) можно поместить непосредственно перед циклом. Аналогичные соображения справедливы относительно четверок (6) и (7).

Получится:

(1) * #2 J i3 {вычисление инвариантов цикла}

(2) - i3 #1 i4

(3) - i4 #1 i5

(4):= #1 I {инициализация цикла}

(5) JGT I #10 (16)

(6) - I #1 i1 {вычисление индексов для X}

(7) * i1 #10 i2

(8) + i2 i5 i6

(9) * i6 #2 i7

(10) + i2 i4 i12 {вычисление индексов для Y}

(11) * i12 #2 i13

(12):= Y[i13] X[i7]

(13) + #1 I i14 {конец цикла}

(14):= i14 I

(15) J (5)

(16) {следующее предложение}

Количество четверок внутри тела цикла уменьшилось, с 14 до 11. Тело цикла выполняется 10 раз, поэтому общее количество операций, необходимых для выполнения FOR, сократилось со 141 до 114.


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



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