El análisis de alias es una técnica de la teoría de compiladores que se utiliza para determinar si se puede acceder a una ubicación de almacenamiento de más de una manera. Se dice que dos punteros tienen alias si apuntan a la misma ubicación.
Las técnicas de análisis de alias suelen clasificarse por sensibilidad al flujo y sensibilidad al contexto. Pueden determinar información de alias posibles o de alias obligatorios. El término análisis de alias suele usarse indistintamente con el análisis de puntos a los que apuntar , un caso específico.
Los analizadores de alias tienen como objetivo crear y calcular información útil para comprender el alias en los programas.
En general, el análisis de alias determina si las referencias de memoria independientes apuntan o no a la misma área de memoria. Esto permite al compilador determinar qué variables del programa se verán afectadas por una instrucción. Por ejemplo, considere la siguiente sección de código que accede a miembros de estructuras:
p . foo = 1 ; q . foo = 2 ; i = p . foo + 3 ;
Aquí hay tres posibles casos de alias:
Si p y q no pueden crear alias, entonces i = p.foo + 3;
se pueden cambiar a i = 4
. Si p y q deben crear alias, entonces i = p.foo + 3;
se pueden cambiar a i = 5
porque p.foo + 3
= q.foo + 3
. En ambos casos, podemos realizar optimizaciones a partir del conocimiento del alias (asumiendo que ningún otro hilo que actualice las mismas ubicaciones puede intercalarse con el hilo actual, o que el modelo de memoria del lenguaje permite que esas actualizaciones no sean inmediatamente visibles para el hilo actual en ausencia de construcciones de sincronización explícitas ). Por otro lado, si no se sabe si p y q crean alias o no, entonces no se pueden realizar optimizaciones y se debe ejecutar todo el código para obtener el resultado. Se dice que dos referencias de memoria tienen una relación may-alias si se desconoce su alias.
En el análisis de alias, dividimos la memoria del programa en clases de alias . Las clases de alias son conjuntos disjuntos de ubicaciones que no pueden crear alias entre sí. Para el análisis que se presenta aquí, se supone que las optimizaciones realizadas aquí ocurren en una representación intermedia de bajo nivel del programa. Es decir, el programa se ha compilado en operaciones binarias, saltos, movimientos entre registros, movimientos de registros a memoria, movimientos de memoria a registros, bifurcaciones y llamadas/retornos de funciones.
Si el lenguaje que se está compilando es de tipo seguro , el verificador de tipos del compilador es correcto y el lenguaje carece de la capacidad de crear punteros que hagan referencia a variables locales (como ML , Haskell o Java ), entonces se pueden realizar algunas optimizaciones útiles. [1] Hay muchos casos en los que sabemos que dos ubicaciones de memoria deben estar en diferentes clases de alias:
Al realizar un análisis de alias para el código, cada carga y almacenamiento en la memoria debe etiquetarse con su clase. Entonces tenemos la propiedad útil, dadas las ubicaciones de memoria y con clases de alias, de que if then may-alias , y if then las ubicaciones de memoria no tendrán alias.
El análisis basado en flujo se puede aplicar a programas en un lenguaje con referencias o conversión de tipos. El análisis basado en flujo se puede utilizar en lugar del análisis basado en tipos o como complemento de este. En el análisis basado en flujo, se crean nuevas clases de alias para cada asignación de memoria y para cada variable global y local cuya dirección se haya utilizado. Las referencias pueden apuntar a más de un valor a lo largo del tiempo y, por lo tanto, pueden estar en más de una clase de alias. Esto significa que cada ubicación de memoria tiene un conjunto de clases de alias en lugar de una única clase de alias.