Interprocedurell optimering

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 .

Exempel

Ersätta en funktionsparameter med en konstant

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 ; }

Ersätta ett virtuellt samtal med ett statiskt

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 ; }

Ta bort oanvänd kod

Efter radering får du:

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

Samtidigt kan virtuella metodtabeller rensas .

Inlining

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 ; }

Länkar

  • Thomas C. Spillman, "Exposing side effects in a PL/I optimizing compiler", i Proceedings of IFIPS 1971 , North-Holland Publishing Company, sidorna 376-381.
  • Frances E. Allen, "Interprocedural Data Flow Analysis", IFIPS Proceedings, 1974.
  • Frances E. Allen och Jack Schwartz, "Determining the Data Flow Relationships in a Collection of Procedures", IBM Research Report RC 4989, aug. 1974.
  • Philip Abrams , "An APL Machine", Stanford University Computer Science Department, rapport STAN-CS-70-158, februari, 1970.
  • Terrence C. Miller, "Tentative Compilation: A Design for an APL Compiler", Ph.D. Avhandling, Yale University, 1978.