Optimización interprocedimiento ( ing. Interprocedural O ptimization , IPO ), u optimización de programa completo de programas ( ing. optimización de programa completo ): optimización del compilador que utiliza análisis de flujo de control global y afecta muchos procedimientos, incluso aquellos ubicados en diferentes módulos, debido a la que se puede lograr un aumento significativo en la velocidad.
A medida que los programas crecían en tamaño, los desarrolladores comenzaron a hacer que su código fuera más legible y reutilizable . A menudo, esto lleva al hecho de que los procedimientos se vuelven extremadamente generales, mientras que en un programa específico puede arreglárselas con un caso especial. La tarea de la optimización interprocesal es precisamente la generación de tales casos especiales.
El compilador realiza automáticamente la optimización entre procedimientos (a veces con directivas especiales). Activarlo puede conducir a un aumento significativo en el tiempo de compilación. Los compiladores que pueden realizar esta optimización incluyen MLton y MLKit para Standard ML , Stalin para Scheme , para Haskell , Intel C++ Compiler .
Después de recorrer el código, el compilador se asegura de que uno de los parámetros sea siempre una constante y lo destruye.
Fue void HacerAlgo ( Objeto * aObj , int aParam ) { si ( aObj == NULL ) throw logic_error ( "aObj==NULL" ); cout << "HacerAlgo(" << aObj -> nombre () << "," << aParam << ")" << endl ; } int principal () { Objeto obj1 , obj2 ; HazAlgo ( & obj1 , 1 ); HazAlgo ( & obj2 , 1 ); devolver 0 ; } Se convirtió en void HacerAlgo ( Objeto * aObj ) { si ( aObj == NULL ) throw logic_error ( "aObj==NULL" ); cout << "HacerAlgo(" << aObj -> nombre () << "," << 1 << ")" << endl ; } int principal () { Objeto obj1 , obj2 ; Hacer Algo ( & obj1 ); Hacer Algo ( & obj2 ); devolver 0 ; }Aquí es donde el compilador se asegura de que todas las llamadas virtuales que se ejecutan realmente conduzcan a la misma llamada de función. En lugar de acceder a la tabla de métodos virtuales , el compilador realiza una llamada de función directa.
En el mismo ejemplo, si Object::name() es un método virtual, la función optimizada se vería así.
void HacerAlgo ( Objeto * aObj ) { si ( aObj == NULL ) throw logic_error ( "aObj==NULL" ); cout << "HacerAlgo(" << Objeto :: nombre ( aObj ) << "," << 1 << ")" << endl ; }Después de la eliminación obtienes:
void HacerAlgo ( Objeto * aObj ) { cout << "HacerAlgo(" << Objeto :: nombre ( aObj ) << "," << 1 << ")" << endl ; }Al mismo tiempo, se pueden borrar las tablas de métodos virtuales .
Si una función se usa una vez, se incluye directamente en el lugar desde el que se llama.
También se pueden incluir funciones pequeñas directamente en el código de llamada.
Muchos lenguajes de programación ( Pascal , Java , D ) no tienen la palabra clave inline , y la decisión de incorporar una función la toma el optimizador (en el caso de Java , el ofuscador ).
Fue en línea int Hacer Algo ( int aParam ) { return aParam * aParam ; } int principal () { int x = 2 ; int y = 3 ; cout << x << "^2=" << HacerAlgo ( x ) << " , " << y << "^2=" << HacerAlgo ( y ) << endl ; devolver 0 ; } Se convirtió en int principal () { int x = 2 ; int y = 3 ; cout << x << "^2=" << x * x << ", " << y << "^2=" << y * y << endl ; devolver 0 ; }