Optimizare interprocedurală

Optimizare interprocedurală ( ing.  O ptimizare interprocedurală , IPO ), sau optimizare integrală a programelor ( ing.  optimizarea întregului program ) - optimizare a compilatorului care utilizează analiza globală a fluxului de control și afectează multe proceduri, chiar și cele situate în module diferite, datorită la care se poate realiza o creştere semnificativă a vitezei.

Pe măsură ce programele au crescut în dimensiune, dezvoltatorii au început să-și facă codul mai lizibil și mai reutilizabil . Adesea, acest lucru duce la faptul că procedurile devin extrem de generale, în timp ce într-un anumit program te poți descurca cu un caz special. Sarcina optimizării interprocedurale este tocmai generarea unor astfel de cazuri speciale.

Optimizarea interprocedurală este realizată automat de către compilator (uneori cu directive speciale). Activarea acestuia poate duce la o creștere semnificativă a timpului de compilare. Compilatoarele care pot efectua această optimizare includ MLton și MLKit pentru Standard ML , Stalin pentru Scheme , pentru Haskell , Intel C++ Compiler .

Exemple

Înlocuirea unui parametru de funcție cu o constantă

După ce parcurge codul, compilatorul se asigură că unul dintre parametri este întotdeauna o constantă și îl distruge.

A fost void DoSomething ( Object * aObj , int aParam ) { dacă ( aObj == NULL ) throw logic_error ( "aObj==NULL" ); cout << "DoSomething(" << aObj -> name () << "," << aParam << ")" << endl ; } int main () { Obiect obj1 , obj2 ; Fă ceva ( & obj1 , 1 ); Fă ceva ( & obj2 , 1 ); returnează 0 ; } A devenit void DoSomething ( Obiect * aObj ) { dacă ( aObj == NULL ) throw logic_error ( "aObj==NULL" ); cout << "DoSomething(" << aObj -> name () << "," << 1 << ")" << endl ; } int main () { Obiect obj1 , obj2 ; Faceți ceva ( & obj1 ); Faceți ceva ( & obj2 ); returnează 0 ; }

Înlocuirea unui apel virtual cu unul static

Aici compilatorul se asigură că toate apelurile virtuale care sunt executate efectiv conduc la același apel de funcție. În loc să acceseze tabelul de metode virtuale , compilatorul efectuează un apel direct de funcție.

În același exemplu, dacă Object::name() este o metodă virtuală, funcția optimizată ar arăta astfel.

void DoSomething ( Obiect * aObj ) { dacă ( aObj == NULL ) throw logic_error ( "aObj==NULL" ); cout << "DoSomething(" << Object :: name ( aObj ) << "," << 1 << ")" << endl ; }

Eliminarea codului neutilizat

După ștergere, obțineți:

void DoSomething ( Obiect * aObj ) { cout << "DoSomething(" << Object :: name ( aObj ) << "," << 1 << ")" << endl ; }

În același timp, tabelele de metode virtuale pot fi șterse .

Inliniere

Dacă o funcție este folosită o dată, aceasta este inclusă direct în locul din care este apelată.

Funcțiile mici pot fi incluse și direct în codul de apelare.

Multe limbaje de programare ( Pascal , Java , D ) nu au cuvântul cheie inline , iar decizia de a inline o funcție este luată de optimizator (în cazul Java  , ofuscatorul ).

A fost inline int DoSomething ( int aParam ) { return aParam * aParam ; } int main () { int x = 2 ; int y = 3 ; cout << x << "^2=" << Faceți ceva ( x ) << ", " << y << "^2=" << Faceți ceva ( y ) << endl ; returnează 0 ; } A devenit int main () { int x = 2 ; int y = 3 ; cout << x << "^2=" << x * x << ", " << y << "^2=" << y * y << endl ; returnează 0 ; }

Link -uri

  • Thomas C. Spillman, „Expunerea efectelor secundare într-un compilator de optimizare PL/I”, în Proceedings of IFIPS 1971 , North-Holland Publishing Company, paginile 376-381.
  • Frances E. Allen, „Analiză interprocedurală a fluxului de date”, IFIPS Proceedings, 1974.
  • Frances E. Allen și Jack Schwartz, „Determining the Data Flow Relationships in a Collection of Procedures”, IBM Research Report RC 4989, august. 1974.
  • Philip Abrams , „An APL Machine”, Departamentul de Informatică al Universității Stanford, Raport STAN-CS-70-158, februarie 1970.
  • Terrence C. Miller, „Tentative Compilation: A Design for an APL Compiler”, Ph.D. Teză, Universitatea Yale, 1978.