stringtranslate.com

Plegado constante

El plegado constante y la propagación constante son optimizaciones del compilador relacionadas utilizadas por muchos compiladores modernos . [1] Una forma avanzada de propagación constante conocida como propagación constante condicional dispersa puede propagar constantes con mayor precisión y eliminar simultáneamente el código inactivo .

Plegado constante

El plegado constante es el proceso de reconocer y evaluar expresiones constantes en tiempo de compilación en lugar de calcularlas en tiempo de ejecución. Los términos en expresiones constantes suelen ser literales simples, como el literal entero 2 , pero también pueden ser variables cuyos valores se conocen en el momento de la compilación. Considere la declaración:

 yo = 320 * 200 * 32 ;      

La mayoría de los compiladores en realidad no generarían dos instrucciones de multiplicación y un almacén para esta declaración. En lugar de ello, identifican construcciones como estas y sustituyen los valores calculados en el momento de la compilación (en este caso, 2,048,000).

El plegado constante puede hacer uso de identidades aritméticas. Si xes numérico, el valor de 0 * xes cero incluso si el compilador no conoce el valor de x(tenga en cuenta que esto no es válido para flotantes IEEE ya que xpodría ser Infinity o NaN . Aún así, algunos entornos que favorecen el rendimiento, como los sombreadores GLSL , permiten esto para constantes, que ocasionalmente pueden causar errores).

El plegado constante puede aplicarse a más que solo números. La concatenación de cadenas literales y cadenas constantes se puede plegar de forma constante. Código como el que "abc" + "def"puede sustituirse por "abcdef".

Plegado constante y compilación cruzada.

Al implementar un compilador cruzado , se debe tener cuidado de garantizar que el comportamiento de las operaciones aritméticas en la arquitectura del host coincida con el de la arquitectura de destino, ya que, de lo contrario, permitir el plegado constante cambiará el comportamiento del programa. Esto es de particular importancia en el caso de operaciones de coma flotante , cuya implementación precisa puede variar ampliamente.

Propagación constante

La propagación constante es el proceso de sustituir los valores de constantes conocidas en expresiones en tiempo de compilación. Dichas constantes incluyen las definidas anteriormente, así como funciones intrínsecas aplicadas a valores constantes. Considere el siguiente pseudocódigo:

 int x = 14 ; int y = 7 - x / 2 ; devolver y * ( 28 / x + 2 );                   

Propagar x produce:

 int x = 14 ; int y = 7-14 / 2 ;devolver y * ( 28/14 + 2 ) ;                   

Continuar propagando produce lo siguiente (que probablemente se optimizaría aún más mediante la eliminación del código muerto de x e y).

 int x = 14 ; int y = 0 ; devolver 0 ;         

La propagación constante se implementa en los compiladores utilizando los resultados del análisis de definición . Si todas las definiciones que alcanzan las variables tienen la misma asignación que asigna una misma constante a la variable, entonces la variable tiene un valor constante y puede reemplazarse con la constante.

La propagación constante también puede hacer que las ramas condicionales se simplifiquen en una o más declaraciones incondicionales, cuando la expresión condicional se puede evaluar como verdadera o falsa en el momento de la compilación para determinar el único resultado posible.

Las optimizaciones en acción.

El plegado y la propagación constantes generalmente se usan juntos para lograr muchas simplificaciones y reducciones, y su aplicación iterativa e intercalada continúa hasta que esos efectos cesen.

Considere este pseudocódigo no optimizado que devuelve un número desconocido pendiente de análisis:

 int a = 30 ; int b = 9 - ( a / 5 ); intc ;              c = segundo * 4 ; si ( c > 10 ) { c = c - 10 ; } devolver c * ( 60 / a );                     

Al aplicar la propagación constante una vez, seguida del plegado constante, se obtiene:

 int a = 30 ; int b = 3 ; intc ;          c = segundo * 4 ; si ( c > 10 ) { c = c - 10 ; } devolver c * 2 ;                   

Repetir ambos pasos dos veces produce:

 int a = 30 ; int b = 3 ; intc ;          c = 12 ; si ( verdadero ) { c = 2 ; } devolver c * 2 ;             

Habiendo reemplazado todos los usos de variables ay bcon constantes, la eliminación del código muerto del compilador se aplica a esas variables, dejando:

 intc ;c = 12 ;     si ( verdadero ) { c = 2 ; } devolver c * 2 ;          

(Las construcciones booleanas varían entre lenguajes y compiladores, pero sus detalles, como el estado, el origen y la representación de verdadero , no afectan estos principios de optimización).

La propagación constante tradicional no produce ninguna optimización adicional; no reestructura programas.

Sin embargo, una optimización similar, la propagación constante condicional dispersa , va más allá al seleccionar la rama condicional apropiada [2] y eliminar la prueba condicional siempre verdadera . Por tanto, la variable cse vuelve redundante y sólo queda una operación sobre una constante:

 devolver 4 ; 

Si ese pseudocódigo constituye el cuerpo de una función, el compilador sabe que la función se evalúa como una constante entera 4, lo que permite reemplazar las llamadas a la función con 4y aumentar aún más la eficiencia del programa.

Ver también

Referencias

  1. ^ Steven Muchnick; Muchnick y asociados (15 de agosto de 1997). Implementación de diseño de compilador avanzado . Morgan Kaufman. ISBN 978-1-55860-320-2. propagación constante O plegado constante.
  2. ^ Wegman, Mark N; Zadeck, F. Kenneth (abril de 1991), "Propagación constante con ramas condicionales", Transacciones ACM en sistemas y lenguajes de programación , 13 (2): 181–210, CiteSeerX 10.1.1.130.3532 , doi :10.1145/103135.103136, S2CID  52813828 

Otras lecturas