Clase digital 17. Optimización.

Portada » Clase digital 17. Optimización.
person holding black computer keyboard

Optimización

Introducción

¡Hola!

Me da mucho gusto saludarte en esta ocasión, que sin demeritar las anteriores, ya has avanzado mucho en este proceso formativo y eso es razón suficiente para pedirte que continúes con ese mismo ímpetu por aprender más. Te reitero mis felicitaciones y te doy la bienvenida a la  penúltima clase del curso. 

En esta sesión aprenderemos sobre 

¿Interesante no crees? ¡Pues comencemos!

Desarrollo del tema

Generación de código

¿Cuál es el criterio más importante para el diseño del generador de código? Producir código correcto.

La entrada del generador de código es código intermedio y tablas de símbolos con información.

La fase final de un compilador es la generación de código.
Recibe una representación intermedia (IR) con información suplementaria en una tabla de símbolos.
Produce un programa semánticamente equivalente.
Tareas principales del generador de código:

  • Selección de instrucción.
  • Asignación de registros.
    Ordenamiento de instrucciones
  • El criterio más importante es que produzca código correcto.
  • Entrada al generador de código:
    • IR + Tabla de símbolos
    • Asumimos que el front-end produce IR de bajo nivel, pe. valores de nombres que pueden ser directamente manipulados por las instrucciones de máquina.
    • Errores sintácticos y semánticos ya han sido detectados.
  • Programa objetivo:
    Arquitecturas objetivo comunes: 
    • RISC; 
    • CISC y de Stack

La complejidad del mapeo depende de:

  • Nivel de la IR
  • Naturaleza de la arquitectura del conjunto de instrucciones objetivo
    Calidad deseada del código generado.

Asignación de Registros:

Hay dos subproblemas:

  • Selección de registros:

Seleccionar el conjunto de variables que residirán en registros en cada punto del programa.

  • Asignación de registros: 

Seleccionar un registro específico para una variable.
Complicaciones impuestas por la arquitectura de hardware.
Ejemplo: pares de registros para multiplicación y división.

  • Operaciones de carga:
    LD r, x y LD r1, r2
  • Operaciones de almacenamiento:
    ST x, r
  • Operaciones de cálculo:
    OP dst, src1, src2
  • Saltos incondicionales:
    BR L
  • Saltos condicionales:
    Bcond r, L como BLTZ r, L

Modos de Direccionamiento:

  • Nombre de variable: 
    x
  • Dirección indexada:
    a(r) como LD R1, a(R2) → R1 = contenido(a+contenido(R2))
  • Entero indexado por un registro:
    LD R1, 100(R2)
  • Modo de direccionamiento indirecto:
    *r 
    *100(r)
  • Modo de direccionamiento inmediato:
    LD R1, #100

Código para b = a [i]

LD R1, i //R1 = i
MUL R1, R1, 8//R1 = Rl * 8
LD R2, a(R1)//R2=contenido(a+contenido(R1))
ST b, R2//b = R2

Código para a[j] = c

LD R1, c//R1 = c
LD R2, j//R2 = j
MUL R2, R2, 8//R2 = R2 * 8
ST  a(R2), R1//contenido(a+contenido(R2))=R1

Código para x=*p

LD R1, p//R1 = p
LD R2, 0(R1)//R2=contenido(0+contenido(R1))
ST  x, R2//x=R2

Instrucción de Salto Condicional

If x<y goto L
LD R2, y//R1 = x
ST  x, R2//R2 = y
SUB R1, R1, R2//R1 = R1 – R2
BLTZ R1, M//si R1 < 0 saltar a M

Costos Asociados con Modos de Direccionamiento:

LD R0, R1costo = 1
LD R0, Mcosto = 2
LD R1, *100(R2)costo = 3

Se asigna un costo para evaluar la calidad del código
Se escoge la alternativa de menor costo para optimizar

Organización de Memoria del Código Objetivo:

  • Área de Código determinada estáticamente.
  • Área de Datos determinada estáticamente.
  • Área de Heap gestionada dinámicamente.
  • Área de Pila gestionada dinámicamente.

Instrucciones de llamada a subrutina y retorno:

  • call callee
  • Return
  • Halt
  • action

Asignación de Stack:

Inicializar stack para regresar de una llamada a subrutina o función

Retorno de subrutina:

Subrutina:BR *0(SP)
Llamada:SUB SP, SP, #caller.recordsize

Producir un programa en lenguaje ensamblador como salida facilita la generación de código.

Qué arquitectura objetivo tiene muchos registros, pocos modos de direccionamiento y un conjunto de instrucciones relativamente simple: RISC.

Un compilador redestinable es aquél que puede generar código para varios conjuntos de instrucciones.

Qué arquitectura objetivo tiene relativamente pocos registros, modos de direccionamiento complejos e instrucciones de longitud variable: CISC.

Muchos compiladores particionan el código intermedio en bloques básicos.

Qué es un modo de direccionamiento: Una manera de indicar un operando en una instrucción.

Cuando el código intermedio es de alto nivel, se pueden utilizar plantillas para traducir cada instrucción de código intermedio.

Conclusión

Para recordar:

Hasta aquí han sido abordados los temas de esta sección. Espero que hayas comprendido lo suficiente. Acude con tu asesor para despejar las dudas que hayan surgido. Resuelve la consigna asignada en tiempo y forma. Nos encontraremos pronto.

Fuentes de información