ARM+gcc: no use una gran sección.rodata
inline lto (2)
Quiero compilar un programa con gcc con optimización de tiempo de enlace para un procesador ARM. Cuando compilo sin LTO, el sistema se compila. Cuando habilito LTO (con -flto), obtengo el siguiente error de ensamblador:
Error: constante literal no válida: el grupo debe estar más cerca
Al mirar alrededor de la web, descubrí que esto tiene algo que ver con las constantes de mi sistema, que se ubican en una sección especial llamada .rodata, que se llama grupo de constantes y se ubica inmediatamente después de la sección .text de mi sistema. Parece que al compilar con LTO debido a las optimizaciones internas y otras optimizaciones, esta sección .rodata se aleja demasiado de las instrucciones, por lo que ya no es posible direccionar las constantes. ¿Es posible colocar las constantes justo después de la función que las usa? ¿O es posible utilizar otro modo de direccionamiento para que la sección .rodata pueda seguir siendo direccionada? Gracias.
Este es un mensaje de ensamblador, no un mensaje de enlazador, por lo que esto sucede antes de que se generen las secciones.
El ensamblador tiene una pseudoinstrucción para cargar constantes en los registros:
ldr r0, =0x12345678
esto se expande en
ldr r0, [constant_12345678, r15]
...
bx lr
constant_12345678:
dw 0x12345678
El grupo constante generalmente sigue la instrucción de retorno. Con la función en línea, la función puede ser lo suficientemente larga como para que la instrucción de retorno esté demasiado lejos; desafortunadamente, el compilador no tiene idea de la distancia entre las direcciones de memoria, y el ensamblador no tiene idea del flujo de control que no sea "el flujo no pasa más allá de la instrucción de retorno, por lo que es seguro emitir aquí el conjunto constante".
Desafortunadamente, no hay una buena solución en este momento.
Puedes probar un bloque de asm
que contenga
b 1f
.ltorg
1:
Esto forzará la emisión del conjunto constante en este punto, a costa de una instrucción de bifurcación adicional.
Puede ser posible indicar al ensamblador que omita la bifurcación si el grupo de constantes está vacío, pero no puedo probarlo en este momento, por lo que probablemente no sea válido:
.if (2f - 1f)
.b 2f
.endif
1:
.ltorg
2:
"Este es un mensaje de ensamblador, no un mensaje de enlace, por lo que esto sucede antes de que se generen secciones" - No estoy seguro, pero creo que es un poco más complicado con LTO. La compilación (incluido el ensamblaje) de los archivos c individuales con LTO habilitado funciona bien y no causa ningún problema. El problema ocurre cuando intento vincularlos junto con LTO habilitado. No sé cómo se hace LTO exactamente, pero aparentemente esto también incluye llamar al ensamblador nuevamente y luego aparece este mensaje de error. Al enlazar sin LTO, todo está bien y cuando miro el desastroso puedo ver que mis constantes no se colocan después de una función. En cambio, todas las constantes se colocan en la sección .rodata. Con LTO habilitado debido a la alineación, mis funciones probablemente lleguen a ser grandes para alcanzar el grupo constante ...