Muchas veces cuando escribo código, me encuentro usando un valor de una llamada de función particular varias veces. Me di cuenta de que una optimización obvia sería capturar estos valores utilizados repetidamente en las variables. Este (pseudo código):¿Cómo puede un compilador aplicar la eliminación de funciones a funciones impuras?
function add1(foo){ foo + 1; }
...
do_something(foo(1));
do_something_else(foo(1));
se convierte en:
function add1(foo){ foo + 1; }
...
bar = foo(1);
do_something(bar);
do_something_else(bar);
Sin embargo, hacer esto hace explícitamente código menos legible en mi experiencia. Supuse que los compiladores no podrían hacer este tipo de optimización si nuestro lenguaje de elección permite que las funciones tengan efectos secundarios.
Recientemente analicé esto, y si entiendo correctamente, esta optimización se puede/se puede hacer para los idiomas donde las funciones deben ser puras. Eso no me sorprende, pero supuestamente esto también se puede hacer para funciones impuras. Con algunas búsquedas rápidas de Google he encontrado estos fragmentos: GCC 4.7 Fortran improvement
Al realizar front-end-optimización, la opción de la función de eliminación de -faggressive permite la eliminación de la función duplicado llamadas, incluso para las funciones impuras.
Compiler Optimization (Wikipedia)
Por ejemplo, en algunas funciones de idiomas no están autorizados a tener efectos secundarios. Por lo tanto, si un programa realiza varias llamadas a la misma función con los mismos argumentos, el compilador puede deducir inmediatamente que el resultado de la función debe computarse solo una vez. En los idiomas en los que se permite que las funciones tengan efectos secundarios, otra estrategia es posible. El optimizador puede determinar qué función no tiene efectos secundarios y restringir dichas optimizaciones a funciones libres de efectos secundarios. Esta optimización solo es posible cuando el optimizador tiene acceso a la función llamada.
Desde mi entender, esto significa que un optimizador puede determinar cuándo una función es o no pura, y realizar esta optimización cuando la función es. Digo esto porque si una función siempre produce la misma salida cuando se le da la misma entrada, y es libre de efectos secundarios, cumpliría ambas condiciones para ser considerada pura.
Estos dos fragmentos me plantean dos preguntas.
- ¿Cómo puede un compilador ser capaz de realizar esta optimización de manera segura si una función no es pura? (como en -faggressive-function-elimination)
- ¿Cómo puede un compilador determinar si una función es pura o no? (Como en la estrategia sugerida en el artículo de Wikipedia)
y finalmente:
- Puede este tipo de optimización puede aplicar a cualquier lengua, o sólo cuando se cumplen ciertas condiciones?
- ¿Es esta optimización una valiosa incluso para funciones extremadamente simples?
- ¿Cuánta sobrecarga genera el almacenamiento y la recuperación de un valor de la pila?
Pido disculpas si estas son preguntas estúpidas o ilógicas. Son algunas de las cosas que me han llamado la atención últimamente. :)
Esto se llama ** eliminación de subexpresiones comunes ** http://en.wikipedia.org/wiki/Common_subexpression_elimination – leppie
Parece que falta la documentación para esa opción GNU Fortran, y sospecho que solo genera código incorrecto si la función tiene efectos secundarios no idempotentes. Una lectura rápida del manual de opciones de generación de código para Fortran de GNU me hace dudar seriamente de la calidad de su implementación, especialmente cosas como poner silenciosamente grandes variables locales en la memoria estática ... –