¿Cómo optimizar los valores de retorno de funciones en C y C ++ en x86-64?
Los x86-64 ABI especifica dos registros de retorno:rax
yrdx
, ambos de 64 bits (8 bytes) de tamaño.
uponiendo que x86-64 es la única plataforma específica, cuál de estas dos funciones:
uint64_t f(uint64_t * const secondReturnValue) {
/* Calculate a and b. */
*secondReturnValue = b;
return a;
}
std::pair<uint64_t, uint64_t> g() {
/* Calculate a and b, same as in f() above. */
return { a, b };
}
arrojaría un mejor rendimiento, dado el estado actual de los compiladores C / C ++ dirigidos a x86-64? ¿Hay alguna dificultad en cuanto al rendimiento al usar una u otra versión? ¿Los compiladores (GCC, Clang) siempre pueden optimizar lastd::pair
para ser devuelto enrax
yrdx
?
ACTUALIZAR Generalmente, devolver un par es más rápido si el compilador optimiza elstd::pair
métodos (ejemplos de salida binaria conGCC 5.3.0 yClang 3.8.0). Sif()
no está en línea, el compilador debe generar código para escribir un valor en la memoria, por ejemplo:
movq b, (%rdi)
movq a, %rax
retq
Pero en caso deg()
es suficiente para que el compilador haga:
movq a, %rax
movq b, %rdx
retq
Debido a que las instrucciones para escribir valores en la memoria son generalmente más lentas que las instrucciones para escribir valores en los registros, la segunda versión debería ser más rápida.