Metody realizacji języków programowania/MRJP Wykład 8: Różnice pomiędzy wersjami
Linia 88: | Linia 88: | ||
= Optymalizacja pętli = | = Optymalizacja pętli = | ||
== Przemieszczenie kodu == | |||
Polega na zmiejszeniu ilości kodu w pętli, przez przemieszczenie obliczeń niezmienniczych | |||
przed pętle. | |||
Przykład: | |||
i = 0 | |||
'''do''' { | |||
a = 13 | |||
i = i + 1 | |||
} '''while''' (i < 15) | |||
przedstawiamy w postaci SSA: | |||
(0) i1 = 0 | |||
(1) i2 = <math>\phi</math>(i1,i3) | |||
(2) a = 13 | |||
(3) i3 = i2 + 1 | |||
(4) if (i3 < 15) goto (1) | |||
Wyrażeniem niezmienniczym jest instrukcja przypisania w linii (2). Możemy ją przemieścić przed pętlę: | |||
(0) i1 = 0 | |||
(1) a = 13 | |||
(2) i2 = <math>\phi</math>(i1,i3) | |||
(3) i3 = i2 + 1 | |||
(4) if (i3 < 15) goto (2) | |||
== Zmienne indukcyjne == | |||
== Redukcja mocy == |
Wersja z 23:21, 14 lip 2006
Wprowadzenie
Podstawowe przekształcenia poprawiające kod
Propagacja kopii
Instrukcja postaci jest instrukcją kopiowania. Naturalne jest zastąpienie wystąpień zmiennej przez .
Przykład:
x = y a = x + y b = a + x
Zastępujemy przez:
x = y a = y + y b = a + y
Po wykonaniu propagacji kopii, instrukcja kopiująca jest martwym kodem. Ostatecznie otrzymamy:
a = y + y b = a + y
Eliminacja wspólnych podwyrażeń
Wyrażenie postaci jest nazywane wspólnym podwyrażeniem jeśli występuje ono w kilku miejscach oraz wartości zmiennych i użytych w kolejnych wystąpieniach nie zmieniły się po poprzednim obliczeniu . W takiej sytuacji można zastąpić kolejne wystąpienia przez wartość wyliczoną za pierwszym razem.
Przykład:
a=4*i b=4*i c=a+b
Drugie wyliczenie można zastąpić przez . Przekształcony blok:
a=4*i b=a c=a+b
Eliminację wspólnych podwyrażeń można stosować
- lokalnie - gdy przeszukujemy jeden blok bazowy,
- globalnie - dla całego grafu przepływu (trudniejsze z powodu pętli).
Usuwanie martwego kodu
Zmienną nazywamy żywą w danym miejscu programu, jeżeli jej wartość może zostać użyta. W pozostałych przypadkach nazywamy zmienną martwą w tym miejscu. Analogicznie definiujemy kod martwy, tzn. taki który oblicza wartości bezużyteczne. Na przykład wyliczenie wartości dla zmiennej martwej lub instrukcja postaci
if (false) ...
to kod martwy.
W oczywisty sposób kod martwy usuwamy.
Często kod martwy powstaje po propagacji kopii lub po zwijaniu stałych.
Zwijanie stałych
Jest to proces upraszczania wyrażeń stałych. Przykład:
x = 30 * 2
można zastąpić przez
x = 60
Zwijanie stałych czasem wykonuje się na wcześniejszych etapach kompilacji.
Propagacja stałych
Jest to proces zastępowania wystąpień stałych przez ich wartości. Przykład
x = 60 y = 3 * x
można zastąpić przez
x = 60 y = 3 * 60
i dalej po zwinięciu wartości w drugim przypisaniu otrzymamy
x = 60 y = 180
W wyniku propagacji stałych instrukcja definiująca stałą staje się martwym kodem, który można usunąć w trakcie eliminacji martwego kodu.
Optymalizacja pętli
Przemieszczenie kodu
Polega na zmiejszeniu ilości kodu w pętli, przez przemieszczenie obliczeń niezmienniczych przed pętle.
Przykład:
i = 0 do { a = 13 i = i + 1 } while (i < 15)
przedstawiamy w postaci SSA:
(0) i1 = 0 (1) i2 = (i1,i3) (2) a = 13 (3) i3 = i2 + 1 (4) if (i3 < 15) goto (1)
Wyrażeniem niezmienniczym jest instrukcja przypisania w linii (2). Możemy ją przemieścić przed pętlę:
(0) i1 = 0 (1) a = 13 (2) i2 = (i1,i3) (3) i3 = i2 + 1 (4) if (i3 < 15) goto (2)