A menudo podemos obtener una mejora sustancial en el tiempo de ejecucin
de cdigo simplemente mediante la realizacin de optimizacin local dentro de cada bloque bsico por s mismo. Ms optimizacin global y profunda, que analiza cmo los flujos de informacin entre los elementos bsicos de un programa, se trata en captulos posteriores, comenzando con el captulo 9. Es un tema complejo, con muchas tcnicas diferentes a considerar. 8.5.1 El DAG Representacin de los bloques bsicos Muchas tcnicas importantes para la optimizacin local comienzan mediante la transformacin de una bsica bloquear en un DAG (grfico acclico dirigido). En la Seccin 6. 1.1, presentamos el DAG como una representacin de expresiones individuales. La idea se extiende de forma natural a la coleccin de las expresiones que se crean dentro de un bloque bsico. Nosotros construir un DAG durante blockas bsicos siguientes: 1. Hay un nodo en el DAG para cada uno de los valores iniciales de las variables que aparece en el bloque bsico. 2. Hay una N nodo asociado con cada declaracin s dentro del bloque. Los hijos de N son los nodos correspondientes a declaraciones que son los ltimos definiciones, antes de la s, de los operandos utilizados por s. 3. Nodo N est marcado por el operador aplica en s, y tambin unido a N es la lista de variables para la cual es la ltima definicin dentro del bloque. 4. Ciertos nodos se denominan nodos de salida. Estos son los nodos cuyos variables son en directo a la salida del bloque; es decir, sus valores pueden ser utilizado ms tarde, en otro bloque del diagrama de flujo. El clculo de estos "vivo variables "es una cuestin para el anlisis de flujo global, discutido en la Seccin 9.2.5.
La representacin DAG de un bloque bsico permite ejecutar varias
transformaciones codeimproving en el cdigo representado por el bloque. a) Podemos eliminar subexpresiones comunes locales, es decir, instrucciones que calcular un valor que ya ha sido calculada. b) Podemos eliminar cdigo muerto, es decir, las instrucciones que calculan un valor que no se utiliza. c) Podemos reordenar declaraciones que no dependen el uno del otro; tal reordenamiento puede reducir el tiempo de un valor temporal necesita ser preservado en un registro. d) Podemos aplicar leyes algebraicas para reordenar operandos de las instrucciones de tres direcciones, ya veces con ello simplificar el clculo.
8.5.2 Bsqueda de locales subexpresiones comunes
Subexpresiones comunes pueden ser detectados por notar, como un nuevo nodo M se trata de que aadir, si existe un nodo N existente con los mismos nios, en el mismo orden y con el mismo operador. Si es as, TV computa el mismo valor como M y puede ser utilizado en su lugar. Esta tcnica fue presentado como el mtodo del "valor-nmero" de deteccin de subexpresiones comunes en la Seccin 6.1.1. E x a m p l e 8. 1 0: Un DAG para el bloque a=b+c b=a-d c=b+c d=a-d se muestra en la Fig. 8.12. Cuando construimos el nodo para la tercera declaracin c = b + c, sabemos que el uso de la b en b + c se refiere al nodo de la Fig. 8.12 marcado -, porque esa es la definicin ms reciente de b. Por lo tanto, no lo hacemos
confundir a los valores calculados en las declaraciones de uno y tres.
Figura 8.12: DAG para el bloque bsico en el Ejemplo 8.10 Sin embargo, el nodo correspondiente a la cuarta declaracin d = A - d tiene la operador - y los nodos con variables adjuntado una y hacen como nios. Desde el operador y los nios son los mismos que para el nodo correspondiente a la declaracin de dos, no creamos este nodo, pero aadimos d para la lista de definiciones para el nodo etiquetado -. Podra parecer que, dado que slo hay tres nodos no hoja en el DAG de Fig. 8.12, el bloque bsico en el Ejemplo 8.10 puede ser sustituido por un bloque con solamente tres declaraciones. De hecho, si b no est online en la salida del bloque, entonces no lo hacemos necesario para calcular esa variable, y puede utilizar d para recibir el valor representado por el nodo etiquetado -. en la Fig. 8.12. El bloque se convierte 8.5. OPTIMIZACIN DE BLOQUES BSICOS 535 Sin embargo, si ambos byd son en directo en la salida, y luego una cuarta declaracin debe ser utilizado para copiar el valor de una a la otra. 1 E jemplo 8.11: Cuando buscamos subexpresiones comunes, que realmente somos en busca de expresiones que estn garantizados para calcular el mismo valor, no importa cmo se calcula ese valor. Por lo tanto, el mtodo de DAG se perder el hecho de que la expresin calculada por el primer y cuarto declaraciones en la secuencia a = b + c; b=b-d c=c+d e=b+c es lo mismo, a saber, en bo 4-. Es decir, a pesar de que b y c tanto el cambio entre las primeras y ltimas declaraciones, su suma sigue siendo el mismo, ya que b +c=
(b - d) + (c + d). El DAG para esta secuencia se muestra en la Fig. 8.13, pero lo
hace no presentan ningn subexpresiones comunes. Sin embargo, las identidades algebraicas aplican al DAG, como se discute en la Seccin 8.5.4, puede exponer a la equivalencia.
co bo hacer Figura 8.13: DAG para el bloque bsico en el Ejemplo 8.11
8.5.3 Dead Cdigo Eliminacin
La operacin en DAG de que corresponde a-cdigo muerto eliminacin puede llevarse a cabo como sigue. Borramos de un DAG alguna raz (nodo sin antepasados) que no tiene variables en vivo adjuntos. La aplicacin repetida de esta transformacin se eliminarn todos los nodos de la DAG que corresponden al cdigo muerto. E x a m p l e 8.12: Si, en la Fig. 8,13, a y b son en vivo, pero C y E no son, podemos retirar inmediatamente la raz etiquetada e. A continuacin, el nodo etiquetado c se convierte en una raz y se puede quitar. Las races A y B siguen siendo marcado, ya que cada tienen variables en vivo unidos. 1 E n general, se debe tener cuidado, al reconstruir el cdigo de DAG de, cmo elegimos los nombres de variables. Si una variable x se define dos veces, o si se le asigna una vez y la inicial Se utiliza tambin valor xq, entonces tenemos que asegurarnos de que no cambiamos el valor de x hasta que han hecho todos los usos del nodo cuyo valor x celebrado con anterioridad. 5 3 6 CAPTULO 8. CDIGO GENERACIN 8.5.4 El uso de identidades algebraicas
Identidades algebraicas representan otra clase importante de optimizaciones
en bsica bloques. Por ejemplo, podemos aplicar las identidades aritmticas, tales como x+0=0+x-xx-0=x xxl = LXX = x x / 1 = x para eliminar los clculos de un bloque bsico. Otra clase de optimizaciones algebraicas incluye reduccin local de la fuerza, es decir, la sustitucin de un operador ms caro por uno ms barato como en: EXPENSIVECHEAPER X 2 = xxx 2xx=x+x x / 2 = x x 0. 5 Una tercera clase de optimizaciones relacionadas es plegado constante. Aqu evaluamos expresiones constantes en tiempo de compilacin y sustituyen a las expresiones constantes por sus valores. 2 Por lo tanto la expresin 2 * 3. 1 4 se sustituye por 6. 2 8. Mayora expresiones constantes surgen en la prctica debido al uso frecuente de simblica constantes en los programas. El proceso DAG-construccin puede ayudar a aplicar estos y otros ms transformaciones algebraicas generales como conmutatividad y asociatividad. por ejemplo, supongamos que el manual de referencia de lenguaje especifica que * es conmutativa; es decir, x * y = y * x. Antes de crear un nuevo nodo etiquetado * con hijo izquierdo M y hijo derecho N, siempre compruebe si ya existe un nodo tales. Sin embargo, * porque es conmutativo, entonces debe comprobar si hay un nodo que tiene el operador *, nio dejado N, y el nio derecho M.
Los operadores relacionales como <y - a veces generar inesperada
subexpresiones comunes. Por ejemplo, la condicin x> y puede tambin ser probado restando los argumentos y la realizacin de una prueba en el conjunto de cdigos de condicin por la resta. 3 Por lo tanto, pueden necesitar slo un nodo del DAG que se generen para x - y y x> y. Leyes asociativas tambin podran ser aplicables para exponer subexpresiones comunes. Por ejemplo, si el cdigo fuente tiene las asignaciones a = b + c; e = c + d + b; el siguiente cdigo intermedio podra ser generado: 2 Las expresiones aritmticas deben ser evaluados de la misma manera en tiempo de compilacin, ya que se encuentran en tiempo de ejecucin. K. Thompson ha sugerido una solucin elegante para plegado constante: compilar el expresin constante, ejecutar el cdigo de destino sobre el terreno, y sustituir la expresin con el resultado. Por lo tanto, el compilador no necesita contener un intrprete. 3 L a la resta puede, sin embargo, la introduccin de los desbordamientos y subdesbordamientos mientras que una comparacin de la instruccin no lo hara. 8.5. OPTIMIZACIN DE BLOQUES BSICOS 537 a=b+c t=c+d e=t+b Si no se necesita t fuera de este bloque, podemos cambiar esta secuencia para a=b+c e=a+d utilizando tanto la asociatividad y la conmutatividad de +.
El escritor compilador debe examinar el manual de referencia del lenguaje
cuidadosamente para determinar qu reordenamientos de los clculos estn permitidos, ya que (debido a posibles desbordamientos o subdesbordamientos) aritmtica computacional no siempre obedecen las identidades algebraicas de las matemticas. Por ejemplo, el Fortran norma establece que un compilador puede evaluar cualquier matemticamente equivalente expresin, a condicin de que la integridad de los parntesis no se viola. Por lo tanto, un compilador puede evaluar x * y - x * za, sx * (y - z), pero no puede evaluar a + (6 - c) como (a b +) - c. Por tanto, un compilador Fortran debe perder de vista donde parntesis estaban presentes en las expresiones del lenguaje fuente si es optimizar programas, de conformidad con la definicin del lenguaje.
8.5.5 Representacin de matriz Referencias
A primera vista, podra parecer que las instrucciones matriz de indexacin pueden ser tratado como cualquier otro operador. Considere, por ejemplo, la secuencia de declaraciones threeaddress: x = a [i] una [j] = y z = a [i] Si pensamos en un [i] como una operacin que implica una y yo, similar a un + i, a continuacin, podra parecer como si los dos usos de un [i] eran una subexpresin comn. En ese caso, podra verse tentado a "optimizar" sustituyendo la tercera instruccin z = a [i] por los ms simples = z x. Sin embargo, desde j podra igualar i, el medio declaracin de hecho, puede cambiar el valor de a [i]; por lo tanto, no es legal para tomar este cambio.
La forma correcta de representar serie de accesos en un DAG es el siguiente.
1. La cesin de una matriz, como x = a [i], est representado por la creacin de un nodo con el operador = [] y dos nios que representan el valor inicial de la matriz, un 0 en este caso, y el ndice i. X variable se convierte en una etiqueta de este nuevo nodo. 2. La cesin a un conjunto, como un [j] = y, es representado por un nuevo nodo con el operador [] = y tres nios que representan un 0, j y. Ahi esta sin etiquetado variable de este nodo. Lo que es diferente es que la creacin de 538 CAPTULO 8. CDIGO GENERACIN este nodo mata a todos los nodos actualmente construidas cuyo valor depende de un 0. Un nodo que se ha matado no puede recibir ms etiquetas; eso es no puede convertirse en una subexpresin comn. E x a m p l e 8. 1 3: El DAG para el bloque bsico x = a [i] una [j] = y z = a [i] se muestra en la Fi- 8,14. El nodo N de x se crea primero, pero cuando el nodo etiqueta [] = se crea, N es asesinado. Por lo tanto, cuando se crea el nodo para z, se no puede ser identificado con N, y un nuevo nodo con el mismo operandos un 0 y yo 0 se debe crear en su lugar. ao io j 0 Yo Figura 8.14: El DAG para una secuencia de asignaciones de matriz E x a m p l e 8. 1 4: A veces, un nodo debe ser muerto a pesar de que ninguno de sus los nios tienen una matriz como una variable de 0 en el ejemplo 8.13 que se adjunta. Del mismo modo,
un nodo puede matar si tiene un descendiente que es una matriz, a pesar de
que ninguno de sus los nios son nodos de la matriz. Por ejemplo, considere el cdigo de tres direcciones b = 12 + a x = b [i] b [j] = y Lo que est sucediendo aqu es que, por razones de eficiencia, b se ha definido a ser una posicin en una matriz a. Por ejemplo, si los elementos de un cuatro bytes de longitud, a continuacin, b representa el cuarto elemento de una. Si jy i representan el mismo valor, entonces b [i] y B [j] representan el mismo lugar. Por lo tanto es importante tener la tercera instruccin, b [j] = y, matar al nodo con x como su adjunto variable. Sin embargo, como vemos en la Fig. 8.15, tanto el nodo y el nodo matado que hace el asesinato han cio como un nieto, no como un nio. 8.5. OPTIMIZACIN DE BLOQUES BSICOS 539 Figura 8.15: Un nodo que mata a un uso de una matriz no necesita tener que matriz como una nio 8.5.6 Puntero Asignaciones y Procedimientos Llamadas Cuando asignamos indirectamente a travs de un puntero, como en las asignaciones x=p* *q=y no sabemos lo que po q elija. En efecto, x = p * es un uso de cada variable de ningn tipo, y * q = y es una posible asignacin a cada variable. Como En consecuencia, el operador = * debe tener todos los nodos que estn asociados actualmente con identificadores como argumentos, lo que es relevante para la eliminacin de cdigo muerto. Ms
importante, el operador * = mata a todos los dems nodos hasta ahora
construidas en el DAG. Hay puntero mundial analiza uno podra realizar eso podra limitar el conjunto de variables un puntero podra hacer referencia a un lugar determinado en el cdigo. Incluso locales anlisis podra restringir el alcance de un puntero. Por ejemplo, en la secuencia p=&x *p=y sabemos que x, y ninguna otra variable, se le da el valor de y, por lo que no necesitamos para matar a cualquier nodo pero el nodo al que se adjunt x. Llamadas a procedimientos comportan como las asignaciones a travs de punteros. en el A falta de informacin mundial de flujo de datos, tenemos que asumir que un procedimiento utiliza y cambia los datos a los que tiene acceso. Por lo tanto, si la variable x est en el mbito de un procedimiento P, una llamada a P tanto utiliza el nodo con adjunta x variable y mata a ese nodo.
8.5.7 volver a montar los bloques bsicos Desde DAG de
Despus realizamos lo optimizaciones son posibles durante la construccin de la DAG o manipulando el DAG, una vez construido, es posible reconstituir el cdigo de tres direcciones para el bloque bsico de la que construimos el DAG. Para cada 540 CAPTULO 8. CDIGO GENERACIN nodo que tiene una o ms variables adjuntos, construimos una de tres direcciones declaracin de que calcula el valor de una de esas variables. Preferimos calcular el resultado en una variable que es en vivo a la salida del bloque. Sin embargo, si
no tenemos la informacin mundial en vivo-variable para trabajar, tenemos
que asumir que todos los temporales variables del programa (pero no que se generan por el compilador para procesar expresiones) es directo a la salida del bloque. Si el nodo tiene ms de una variable en vivo adjunto, entonces tenemos que introducir las declaraciones de copia para dar el valor correcto a cada una de esas variables. A veces, la optimizacin global puede eliminar esas copias, si podemos arreglar utilizar uno de dos variables en lugar de la otra. E x a m p l e 8. 1 5: Recordemos el DAG de la Fig. 8.12. En la discusin siguiente Ejemplo 8.10, decidimos que si b no est online en la salida del bloque, entonces el tres declaraciones a=b+c d=a-d c=d+c suficiente para reconstruir el bloque bsico. La tercera instruccin, c = d + c, debe utilizar d como operando en lugar de b, porque el bloque optimizado nunca se calcula b. Si tanto byd son en directo en la salida, o si no lo sea o no estn seguros de que son en directo en la salida, entonces tenemos que calcular b y d. Podemos hacerlo con la secuencia a=b+c d=a-d b=d c=d+c Este bloque bsico es an ms eficaz que el original. Aunque el nmero de las instrucciones es el mismo, hemos sustituido una sustraccin de una copia, que
tiende a ser menos costoso en la mayora de mquinas. Adems, puede ser
que al hacer un anlisis global, podemos eliminar el uso de este clculo de b fuera el bloque mediante su sustitucin por usos de d. En ese caso, podemos volver a este bloque bsico y eliminar b = d despus. Intuitivamente, podemos eliminar esta copia si donde se utiliza este valor de b, d an se mantiene el mismo valor. Esa situacin puede o no ser cierto, dependiendo de cmo el programa vuelve a calcular d. Al reconstruir el bloque bsico de un DAG, no slo tenemos que preocuparnos acerca de lo que se utilizan variables para mantener los valores de los nodos de la DAG, pero Tambin tendr que preocuparse por el orden en que listamos las instrucciones de computacin los valores de los distintos nodos. Las reglas a tener en cuenta son 1. El orden de las instrucciones debe respetar el orden de los nodos de la DAG. Es decir, no podemos calcular el valor de un nodo hasta hemos calculado un valor para cada uno de sus hijos. 8.5. OPTIMIZACIN DE BLOQUES BSICOS 541 2. Las asignaciones a un array deben seguir todas las asignaciones anteriores a, o evaluaciones de la misma matriz, de acuerdo con el orden de estas instrucciones en el bloque bsico inicial. 3. Las evaluaciones de los elementos de la matriz deben seguir cualquier anterior (segn la bloque original) asignaciones a la misma matriz. La nica permutacin permitido es que dos evaluaciones de la misma matriz pueden realizarse en cualquiera orden, siempre y cuando ni los cruces ms de una asignacin a esa matriz. 4. Cualquier uso de una variable debe seguir todos los anteriores (de acuerdo con el original bloque) llamadas a procedimientos o asignaciones indirectas a travs de un puntero.
5. Cualquier llamada a procedimiento o cesin indirecta a travs de un puntero
deben seguir todos los anteriores (de acuerdo con el bloque original) evaluaciones de cualquier variable. Es decir, cuando la reordenacin de cdigo, ninguna declaracin puede cruzar una llamada a procedimiento o asignacin a travs de un puntero, y los usos de la misma matriz pueden cruzar entre s slo si ambos son array accede, pero no las asignaciones a los elementos de la matriz. 8.5.8 Ejercicios para la Seccin 8.5 Ejercicio 8. 5. 1: Construir el DAG para el bloque bsico d=b*c e=a+b b=b*c a=e-d Ejercicio 8. 5. 2: Simplificar el cdigo de tres direcciones del Ejercicio 8.5.1, suponiendo a) Slo una es vivir a la salida del bloque. b) a, b, y c son en vivo a la salida del bloque. Ejercicio 8. 5. 3: Construir el bloque bsico para el cdigo en el bloque B 6 de la Fig. 8.9. No se olvide de incluir la comparacin i <10. Ejercicio 8. 5. 4: Construir el bloque bsico para el cdigo en el bloque B 3 de la Fig. 8.9. Ejercicio 8. 5. 5: Extender el algoritmo 8.7 para procesar tres enunciados de la forma a) a [i] = B b) a = b [i] c) a = b * c) * a = b Ejercicio 8. 5. 6: Construir el DAG para el bloque bsico