Un compilador C optimiza mal el bucle principal de Lua

Fuentes: A C compiler pessimizes the main Lua loop due to register spilling

El desarrollador de antcc, un compilador C de código abierto, identificó una anomalía crítica en su herramienta tras observar que las compilaciones optimizadas con el nivel -O2 eran significativamente más lentas que las versiones no optimizadas en una prueba de rendimiento con Lua. En lugar de mejorar el rendimiento, la optimización agresiva degradó la ejecución, lo que sugirió un problema de diseño en la asignación de registros o la selección de instrucciones.

El análisis técnico reveló que la función luaV_execute, que interpreta el bytecode de Lua, era la principal causa del problema. Al desactivar la optimización de inlining, el rendimiento se recuperó, confirmando que la agresividad en la inlining estaba generando presión excesiva en los registros. Aunque la función era compleja y difícil de optimizar, el análisis del código intermedio (IR) mostró que la diferencia de tamaño en el IR era mínima (solo un 11% mayor en -O2 frente a -O1). Sin embargo, tras la asignación de registros, el código binario aumentó un 70% más, con más del 40% de las instrucciones siendo movimientos de pila a registros (movs).

El autor determinó que el problema residía en la representación de código con asignación estática única (SSA). En la forma SSA, las instrucciones 'phi' en bucles crean temporales que permanecen activos durante toda la iteración. La inlining de funciones pequeñas dentro del bucle principal de Lua generaba una presión de registros que forzaba el desbordamiento (spilling) de estos temporales, creando un ciclo de movimientos ineficientes entre la pila y los registros. Este caso ilustra las limitaciones de las heurísticas de inlining simples en funciones con bucles profundos y control de flujo complejo, donde la asignación de registros puede degradar el rendimiento si no se gestiona adecuadamente la presión de registros.