Interprocedurell optimering ( eng. Inter procedural Optimization , IPO ) , eller fullprogramoptimering av program ( eng. whole program optimization ) - kompilatoroptimering som använder global kontrollflödesanalys och påverkar många procedurer, även de som finns i olika moduler, pga . till vilken en betydande hastighetsökning kan uppnås.
När programmen växte i storlek började utvecklare göra sin kod mer läsbar och återanvändbar . Ofta leder detta till att procedurerna blir extremt generella, medan man i ett specifikt program kan klara sig med ett specialfall. Uppgiften med interprocedurell optimering är just att skapa sådana specialfall.
Interproceduroptimering utförs automatiskt av kompilatorn (ibland med särskilda direktiv). Att aktivera det kan leda till en betydande ökning av kompileringstiden. Kompilatorer som kan utföra denna optimering inkluderar MLton och MLKit för Standard ML , Stalin för Scheme , för Haskell , Intel C++ Compiler .
Efter att ha gått igenom koden ser kompilatorn till att en av parametrarna alltid är en konstant och förstör den.
Det var void DoSomething ( Object * aObj , int aParam ) { if ( aObj == NULL ) kasta logic_error ( "aObj==NULL" ); cout << "DoSomething(" << aObj -> namn () << "," << aParam << ")" << endl ; } int main () { Objekt obj1 , obj2 ; Gör något ( & obj1 , 1 ); Gör något ( & obj2 , 1 ); returnera 0 ; } Blev void DoSomething ( Object * aObj ) { if ( aObj == NULL ) kasta logic_error ( "aObj==NULL" ); cout << "DoSomething(" << aObj -> namn () << "," << 1 << ")" << endl ; } int main () { Objekt obj1 , obj2 ; Gör något ( & obj1 ); Gör något ( & obj2 ); returnera 0 ; }Det är här kompilatorn ser till att alla virtuella anrop som faktiskt exekveras leder till samma funktionsanrop. Istället för att komma åt den virtuella metodtabellen gör kompilatorn ett direkt funktionsanrop.
I samma exempel, om det Object::name() är en virtuell metod, skulle den optimerade funktionen se ut så här.
void DoSomething ( Object * aObj ) { if ( aObj == NULL ) kasta logic_error ( "aObj==NULL" ); cout << "DoSomething(" << Objekt :: namn ( aObj ) << "," << 1 << ")" << endl ; }Efter radering får du:
void DoSomething ( Object * aObj ) { cout << "DoSomething(" << Objekt :: namn ( aObj ) << "," << 1 << ")" << endl ; }Samtidigt kan virtuella metodtabeller rensas .
Om en funktion används en gång ingår den direkt på den plats som den anropas från.
Små funktioner kan också inkluderas direkt i anropskoden.
Många programmeringsspråk ( Pascal , Java , D ) har inte nyckelordet inline , och beslutet att infoga en funktion tas av optimeraren (i fallet Java , obfuscatorn ).
Det var inline int DoSomething ( int aParam ) { returnera aParam * aParam ; } int main () { int x = 2 ; int y = 3 ; cout << x << "^2=" << DoSomething ( x ) << ", " << y << "^2=" << DoSomething ( y ) << endl ; returnera 0 ; } Blev int main () { int x = 2 ; int y = 3 ; cout << x << "^2=" << x * x << ", " << y << "^2=" << y * y << endl ; returnera 0 ; }