2012-07-23 8 views
5

Tengo una función externa (C) a la que llamo en mi LLVM IR. El IR obtiene JIT y todo funciona bien, pero el código generado es sensible al rendimiento y, si es posible, quiero eliminar las llamadas duplicadas a mi función externa. La función no tiene efectos secundarios. ¿Hay un FunctionPass que elimine las llamadas redundantes a la función? ¿Hay algo que deba hacer para señalar que la función no tiene efectos secundarios?LLVM marcar la función como const y eliminar llamadas duplicadas

Gracias!

Respuesta

1

Según http://llvm.org/docs/LangRef.html#function-attributes puede especificar los atributos de sólo lectura o readnone para una función:

declare i32 @fn(i32 %i); 
declare i32 @readonly_fn(i32 %i) readonly; 
declare i32 @readnone_fn(i32 %i) readnone; 

readonly significa que la función no escribe de memoria, readnone significa que ni siquiera leer la memoria (por ejemplo sin() podría ser readnone)

Si una función no escribe memoria, debe devolver el resultado solo en función de los parámetros, y por lo tanto debe ser una función pura (si el estado global no cambia). En el caso de una función readnone, incluso el estado global podría cambiar.

El llvm optimizador puede optimizar llamadas a sólo lectura y las funciones readnone con la EarlyCSE pase (eliminación subexpresión común), como se muestra en el siguiente ejemplo:

usando las siguientes funciones de prueba

define i32 @test_no_readonly() 
{ 
    %1 = call i32 @fn(i32 0) 
    %2 = call i32 @fn(i32 0) 
    %add = add i32 %1, %2 
    ret i32 %add 
} 
define i32 @test_readonly() 
{ 
    %1 = call i32 @readonly_fn(i32 0) 
    %2 = call i32 @readonly_fn(i32 0) 
    %add = add i32 %1, %2 
    ret i32 %add 
} 
define i32 @test_readnone() 
{ 
    %1 = call i32 @readnone_fn(i32 0) 
    %2 = call i32 @readnone_fn(i32 0) 
    %add = add i32 %1, %2 
    ret i32 %add 
} 

y funcionamiento opt -early-cse -S readonly_fn.ll > readonly_fn_opt.ll optimiza distancia la segunda llamada para las funciones de sólo lectura y readnone, resultando en

define i32 @test_no_readonly() { 
    %1 = call i32 @fn(i32 0) 
    %2 = call i32 @fn(i32 0) 
    %add = add i32 %1, %2 
    ret i32 %add 
} 

define i32 @test_readonly() { 
    %1 = call i32 @readonly_fn(i32 0) 
    %add = add i32 %1, %1 
    ret i32 %add 
} 

define i32 @test_readnone() { 
    %1 = call i32 @readnone_fn(i32 0) 
    %add = add i32 %1, %1 
    ret i32 %add 
} 

Las funciones readonly_fn y readnone_fn solo se llaman una vez, por lo que se seleccionan las llamadas redundand.

El pase -functionattrs también puede agregar estos atributos a las funciones definidas

Cuestiones relacionadas