
- •Лабораторна робота № 4 Генерація і оптимізація об'єктнго кода
- •Короткі теоретичні відомості
- •Побудова асемблерного коду по дереву виводу
- •Побудова списку тріад по дереву виводу.
- •Оптимізація об'єктного коду методом виключення зайвих операцій
- •Загальний алгоритм генерації і оптимізації об'єктного коду
Побудова списку тріад по дереву виводу.
Тріади є універсальною, машинно-незалежною формою внутрішнього уявлення в компіляторі результуючої об'єктної програми, а тому не вимагають обмовки додаткових умов при генерації коду. Тріади взаємозв'язані між собою, тому для установки коректного взаємозв'язку процедура генерації коди повинна отримувати також поточний номер i чергової тріади.
Тоді чотирьом формам поточного вузла дерева відповідатимуть послідовності тріад об'єктної коди (табл. 6):
Таблиця 6.
Перетворення типових вузлів дерева виводу в послідовність тріад
Вид вузла дерева |
Результуючий код |
Примітка |
|
i) act (oper1,oper2) |
act - тип тріади oper1,oper2 - операнди (листя дерева виводу) |
|
i) Code(Узел 2,i) i+j) act(oper1,^i+j-1) |
Узел 2 - вузол дерева виводу, що пролягає нижче Code(Узел 2,i) - послідовність тріад, що породжується для Узла2, починаючи з тріади з номером i j - кількість тріад, що породжуються для Узла2 |
|
i) Code(Узел 2,i) i+j) act(^i+j-1,oper2)
|
Узел 2 - вузол дерева виводу, що пролягає нижче Code(Узел 2,i) - послідовність тріад, що породжується для Узла2, починаючи з тріади з номером i j - кількість тріад, що породжуються для Узла2 |
|
i) Code(Узел 2,i) i+j) Code(Узел 3,i+j) i+j+k) act(^i+j-1,^i+j+k-1)
|
Узел 2, Узел 3 - вузли дерева виводу, що пролягають нижче Code(Узел 2,i) - послідовність тріад, що породжується для Узла2, починаючи з тріади з номером i j - кількість тріад, що породжуються для Узла2 Code(Узел 3,i+j) - послідовність тріад, що породжується для Узла3, починаючи з тріади з номером i+j k - кількість тріад, що породжуються для Узла3 |
Розглянемо той же приклад дерева виводу для виразу A := B*c + D - B*10 на мал. 6 і відповідну йому послідовність тріад:
соответствующую ему последовательность триад:
Мал.
6. Дерево виводу для арифметичного
виразу.
i) :=(A,^i-1)
Крок 2: 1) Code(U3,1)
j) Code(U5,j)
i-1) -(^j-1,^i-2)
i) :=(A,^i-1)
Крок 3: 1) Code(U4,1)
k) +(^k-1,D)
j) Code(U5,j)
i-1) -(^j-1,^i-2)
i) :=(A,^i-1)
Крок 4: 1) *(B,C)
2) +(^1,D)
3) Code(U5,3)
i-1) -(^j-1,^i-2)
i) :=(A,^i-1)
Крок 5: 1) *(B,C)
2) +(^1,D)
3) *(B,10)
4) -(^2,^3)
5) :=(A,^4)
Слід звернути увагу, що в даному алгоритмі послідовні номери тріад (а отже, і посилання на них) встановлюються не відразу. Це не має значення при рекурсивній організації процедури, але при іншому способі обходу дерева виводу в програмі генерації коди краще пов'язувати тріади між собою саме по посиланню (покажчику), а не по порядковому номеру.
Для тріад розроблені універсальні (машинно-незалежні) алгоритми оптимізації коди. Після їх виконання (оптимізації внутрішнього уявлення) тріади можуть бути перетворені в команди на мові асемблера.
Оптимізація об'єктної коди методом згортки
Згортка об'єктного коду - це виконання під час компіляції тих операцій початкової програми для яких значення операндів вже відомі. Тому немає необхідності багато разів виконувати їх в самій результуючій програмі - цілком достатньо один раз виконати їх при її компіляції.
Простий варіант згортки - виконання в компіляторі операцій, операндами яких є константи. Декілька більш складений процес визначення тих операцій, значення яких можуть бути відомі в результаті виконання інших операцій. Для цього служить спеціальний алгоритм згортки.
Алгоритм згортки працює із спеціальною таблицею T, яка містить пари <переменная>-<константа> для всіх змінних, значення яких вже відомі. Крім того, алгоритм згортки позначає ті операції у внутрішньому уявленні програми, для яких в результаті згортки вже не потрібна генерація коду. Оскільки при виконанні алгоритму згортки враховується взаємозв'язок операцій, то зручною формою уявлення для нього є тріади, оскільки в інших формах представлення операцій (таких як тетради або команди асемблера) потрібні додаткові структури, щоб відобразити зв'язок результатів одних операцій з операндами інших.
Алгоритм згортки тріад послідовно проглядає тріади лінійного списку і для кожної тріади робить наступне:
Якщо операнд є змінна, яка міститься в таблиці T, то операнд замінюється на відповідне значення константи.
Якщо операнд є посилання на особливу тріаду типу C(K,0), то операнд замінюється на значення константи K.
Якщо всі операнди тріади є константами, то тріада може бути згорнута. Тоді дана тріада виконується і замість неї поміщається особлива тріада виду C(K,0), де K - константа, результат виконання згорнутої тріади. (При генерації коди для особливої тріади об'єктний код не породжується, а тому вона надалі може бути просто виключена).
Якщо тріада є привласненням типу A:=b, тоді:
якщо B - константа, то A із значенням константи заноситься в таблицю T (якщо там вже було старе значення для A, то це старе значення виключається).
якщо B - не константа, то A взагалі виключається з таблиці T, якщо воно там є.
Розглянемо приклад виконання алгоритму.
Хай фрагмент початкової програми (записаною на мові типу Паскаль) має вигляд:
I := 1 + 1;
I := 3;
J := 6*I + I;
Її внутрішньо уявлення у формі тріад матиме вигляд:
+ (1,1)
:= (I ^1)
:= (I, 3)
* (6, I)
+ (^4, I)
:= (J ^5)
Процес виконання алгоритму згортки можна відобразити в табл. 7:
Таблиця 7.
Приклад роботи алгоритму згортки
Тріада |
Крок 1 |
Крок 2 |
Крок 3 |
Крок 4 |
Крок 5 |
Крок 6 |
1 |
C (2, 0) |
C (2, 0) |
C (2, 0) |
C (2, 0) |
C (2, 0) |
C (2, 0) |
2 |
:= (I, ^1) |
:= (I, 2) |
:= (I, 2) |
:= (I, 2) |
:= (I, 2) |
:= (I, 2) |
3 |
:= (I, 3) |
:= (I, 3) |
:= (I, 3) |
:= (I, 3) |
:= (I, 3) |
:= (I, 3) |
4 |
* (6, I) |
* (6, I) |
* (6, I) |
C (18, 0) |
C (18, 0) |
C (18, 0) |
5 |
+ (^4, I) |
+ (^4, I) |
+ (^4, I) |
+ (^4, I) |
C (21, 0) |
C (21, 0) |
6 |
:= (J, ^5) |
:= (J, ^5) |
:= (J, ^5) |
:= (J, ^5) |
:= (J, ^5) |
:= (J, 21) |
Т |
( , ) |
( I, 2 ) |
( I, 3 ) |
( I, 3 ) |
( I, 3 ) |
( I, 3 ) ( J, 21 ) |
Якщо виключити особливі тріади типу C(K,0) (які не породжують об'єктної коди), то в результаті виконання згортки отримаємо наступну послідовність тріад:
:= (I, 2)
:= (I, 3)
:= (J, 21)