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