This shows you the differences between two versions of the page.
cpl:labs:11 [2016/10/04 07:45] bogdan.nitulescu |
cpl:labs:11 [2016/12/20 01:59] (current) bogdan.nitulescu [Exercițiul 3] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== 11. LLVM Passes - optimizarea codului ====== | + | ===== 11. LLVM - transformări de cod ===== |
+ | |||
+ | |||
+ | ===== Introducere ===== | ||
+ | |||
+ | În LLVM optimizările sunt implementate sub formă de [[http://llvm.org/docs/Passes.html|Pass]]-uri care traversează programul pentru a-l analiza și a-l transforma. Obținerea de informații despre program prin analiza fluxului de [[cpl:labs:09#tipuri_de_probleme|date]] sau de [[cpl:labs:08|control]] constituie un pas important în implementarea optimizărilor. | ||
+ | |||
+ | Pentru a aplica o anumită selecție de optimizări se poate folosi tool-ul [[http://llvm.org/docs/CommandGuide/opt.html|opt]] prezentat și [[cpl:labs:llvm-pass|aici]]. Pentru a integra o optimizare nouă în sursele LLVM (fără să mai fim nevoiți să specificăm biblioteca dinamică la runtime) se va folosi [[http://llvm.org/docs/CommandGuide/llvm-build.html|sistemul de build]] din llvm și pașii descriși în exemplul de [[cpl:labs:llvm-pass#integrarea_unui_pas_in_llvm|aici]]. | ||
+ | ===== Afișarea informațiilor de debug ===== | ||
+ | Informațiile de debug, pot fi afișate rulând utilitarul ''opt'' cu parametrul ''-debug''. Pentru a filtra informațiile de debug doar pentru un anumit pas, se folosește parametrul ''-debug-only=//<nume_pass>//''. De exemplu, pentru a filtra doar log-urile optimizării hello, se rulează comanda: | ||
+ | <code bash> | ||
+ | opt -hello -debug-only=hello hello.bc | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ===== SSA ====== | ||
+ | |||
+ | Un program este reprezentat în forma SSA dacă fiecărei variabile i se atribuie o valoare doar o singură dată şi fiecare folosire a variabilei este dominată de definiţia ei. | ||
+ | |||
+ | Un program poate fi convertit în forma [[http://en.wikipedia.org/wiki/Static_single_assignment_form|SSA]] prin: | ||
+ | * asocierea de nume unice variabilelor de fiecare dată când li se atribuie o valoare | ||
+ | * înlocuirea numelor de variabile cu numele unice atunci când variabilele sunt folosite. | ||
+ | |||
+ | Exemple | ||
+ | ^ Program inițial ^ Program în forma SSA ^ | ||
+ | | <code c> | ||
+ | V = 4; | ||
+ | = V + 5; | ||
+ | V = 6; | ||
+ | = V + 7; | ||
+ | </code> | <code c> | ||
+ | V0 = 4; | ||
+ | = V0 + 5; | ||
+ | V1 = 6; | ||
+ | = V1 + 7; | ||
+ | </code> | | ||
+ | | <code c> | ||
+ | if (...) | ||
+ | X = 5; | ||
+ | else | ||
+ | X = 3; | ||
+ | |||
+ | Y = X; | ||
+ | </code> | <code c> | ||
+ | if (...) | ||
+ | X0 = 5; | ||
+ | else | ||
+ | X1 = 3; | ||
+ | X2 = O(X0, X1); | ||
+ | Y0 = X2; | ||
+ | </code> | | ||
+ | | <code c> | ||
+ | j = 1; | ||
+ | while (j < X) | ||
+ | ++j; | ||
+ | N = j; | ||
+ | </code> care se mai poate scrie şi <code c> | ||
+ | j = 1; | ||
+ | if (j >= X) | ||
+ | goto E; | ||
+ | S: | ||
+ | j = j + 1; | ||
+ | if (j < X) | ||
+ | goto S; | ||
+ | E: | ||
+ | N = j; | ||
+ | </code> | <code c> | ||
+ | j0 = 1; | ||
+ | if (j0 >= X0) | ||
+ | goto E; | ||
+ | S: | ||
+ | j1 = O(j0, j2); | ||
+ | j2 = j1 + 1; | ||
+ | if (j2 < X0) | ||
+ | goto S; | ||
+ | E: | ||
+ | j3 = O(j0, j2); | ||
+ | N0 = j3; | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | </code> | | ||
+ | |||
+ | Într-un basic block B având N predecesori P<sub>1</sub>, P<sub>2</sub>, ..., P<sub>N</sub>, prin X = O(V<sub>1</sub>, V<sub>2</sub>, ..., V<sub>n</sub>) se înțelege că variabila ''X'' va avea valoarea V<sub>j</sub> dacă fluxul de control intră în blocul B din blocul P<sub>j</sub>, 1<=j<=N. | ||
+ | |||
+ | ===== Ierarhia de clase în LLVM ===== | ||
+ | * clasa [[http://llvm.org/docs/ProgrammersManual.html#Instruction|Instruction]] este subclasă a | ||
+ | * clasei [[http://llvm.org/docs/ProgrammersManual.html#User|User]] care este subclasă a | ||
+ | * clasei [[http://llvm.org/docs/ProgrammersManual.html#Value|Value]] | ||
+ | Mai jos este un exemplu de instrucțiune (Instruction). Ea este şi utilizator (User) ale variabilelor (Value) a şi b. În acelaşi timp reprezintă şi definirea variabilei (Value) c. | ||
+ | <code asm> | ||
+ | %c = add i32 %a, %b | ||
+ | </code> | ||
+ | |||
+ | [[http://llvm.org/docs/ProgrammersManual.html#iterate-chains|Aici]] este un exemplu de cum pot fi parcurşi toţi utilizatorii unei variabile. | ||
+ | |||
+ | [[http://llvm.org/docs/ProgrammersManual.html#iterate-function|Aici]] este un exemplu de cum pot fi parcurse toate basic block-urile dintr-o funcţie. | ||
+ | |||
+ | [[http://llvm.org/docs/ProgrammersManual.html#iterate-basicblock|Aici]] este un exemplu de cum pot fi parcurse toate instrucţiunile dintr-un basic block. | ||
+ | |||
+ | [[http://llvm.org/docs/ProgrammersManual.html#iterate-institer|Aici]] este un exemplu de cum pot fi parcurse toate instrucţiunile dintr-o funcţie. | ||
+ | |||
+ | [[http://llvm.org/docs/ProgrammersManual.html#iterate-preds|Aici]] este un exemplu de cum pot fi parcurşi toţi predecesorii şi succesorii unui basic block. | ||
+ | |||
+ | [[http://llvm.org/docs/ProgrammersManual.html#isa|Aici]] este un exemplu de cast folosit la exerciţiul 3. | ||
+ | |||
+ | [[http://llvm.org/docs/ProgrammersManual.html#dss-valuemap|Aici]] este o scurtă descriere a structurii de date ValueMap folosită la exerciţiul 3. | ||
+ | |||
+ | [[http://llvm.org/docs/ProgrammersManual.html#dss-bitvector|Aici]] este o scurtă descriere a structurii de date BitVector folosită la exerciţiul 3. | ||
+ | |||
+ | ====== Exerciții de laborator (15p) ====== | ||
+ | |||
+ | <note> | ||
+ | Laboratorul este compus dintr-o exerciții practice care includ analiza formei SSA și implementarea unor optimizări. | ||
+ | Înainte de începerea exercițiilor downloadați arhiva de {{:cpl:labs:lab11_2016.zip|aici}}. | ||
+ | |||
+ | Compilati exercitiile cu -O0 pentru a nu lasa compilatorul sa aplice optimizari. | ||
+ | </note> | ||
+ | |||
+ | ===== Exercițiul 1 ===== | ||
+ | |||
+ | Scrieti un Pass de LLVM care sa elimine basic block-urile trivially dead. Hint: Un basic block este trivially dead daca nu exista niciun jump care sa duca catre acesta; cu alte cuvinte nu are predecesori. | ||
+ | |||
+ | <file c dead.c> | ||
+ | #include<stdio.h> | ||
+ | #include<time.h> | ||
+ | #include<stdlib.h> | ||
+ | |||
+ | void main(void) { | ||
+ | int a = 1, b =2, c = 3; | ||
+ | |||
+ | if (a + b * (rand() % 3) == 3) { | ||
+ | goto end1; | ||
+ | } else { | ||
+ | goto end2; | ||
+ | } | ||
+ | |||
+ | dead: | ||
+ | printf("Unreachable\n"); | ||
+ | |||
+ | |||
+ | end1: | ||
+ | printf("Still reachable\n"); | ||
+ | end2: | ||
+ | printf("Reachable\n"); | ||
+ | } | ||
+ | |||
+ | </file> | ||
+ | |||
+ | ===== Exercițiul 2 ===== | ||
+ | |||
+ | Scrieti un pass care optimizeaza cazuri de tipul jump to jump. Un caz de jump to jump avem in momentul in care singura intructiune dintr-un basic block este un salt neconditionat intr-un alt bloc. In acest caz toate instructiunile de salt din blocul initial pot fi optimizate pentru a duce direct la blocul destinatie. | ||
+ | Blocul initial este in acest moment dead code si poate fi eliminat cu pass-ul de la exercitiul anterior. | ||
+ | |||
+ | <file c jump_to_jump.c> | ||
+ | #include<stdio.h> | ||
+ | #include<time.h> | ||
+ | #include<stdlib.h> | ||
+ | |||
+ | void main(void) { | ||
+ | int x = rand() % 100 - 10; | ||
+ | |||
+ | if ( x < 0 ) { | ||
+ | return; | ||
+ | } else { | ||
+ | printf("Not negative\n"); | ||
+ | } | ||
+ | |||
+ | printf("End\n"); | ||
+ | } | ||
+ | |||
+ | </file> | ||
+ | |||
+ | ===== Exercițiul 3 ===== | ||
+ | |||
+ | Folosind codul din fişierul ''Hello.cpp'' din arhiva laboratorului, urmăriţi modul în care poate fi implementată simple constant propagation în LLVM. | ||
+ | * cum poate fi identificată o instrucţiune inutilă? | ||
+ | * identificaţi metoda responsabilă pentru constant folding | ||
+ | * cum se înlocuiesc apariţiile viitoare ale variabilei în cauză cu o constantă? | ||
+ | * de ce se adaugă din nou în worklist unele instrucţiuni? | ||
+ | * Rulaţi acest pas folosind fisierul ''test.c'' din arhiva laboratorului. | ||
- | **TO BE PUBLISHED SOON** | ||