Linguaggi e traduttori. Generazione codice intermedio

Lauke
Oi ragazzi ciao, perdonate il disturbo. Ho un quesito da porvi.
Stavo studiando la rappresentazione del codice intermedio nelle sue forme (Quadruple, triple e triple indirette).

Come fungono queste 3 l'ho capito. Ma non ho capito i vantaggi delle triple indirette. Vi recito cosa dice il libro a riguardo, magari riuscite a illuminarmi.

"A benefit of quadruples over triples can be seen in an optimizing compiler, where instructions are often moved around. With quadruples, if we move an instruction that computes a temporary t, then the instruction that use t require no change. With triples, the result of an operation is referred to by its position, so moving an instruction may require us to change all references to that result. This problem does not occur with indirect triples, which we consider next."

Poi dice in che consistono le triple indirette e dice successivamente...

"With indirect triples, an optimizing compiler can move an instruction by reordering the instruction list, without affecting the triples themselves."

Diciamo che nel succo succo succo ho capito che i vantaggi delle quadruple sulle triple riguardano questi "movimenti". Intanto non ho capito cosa viene inteso con questi movimenti. Poi non ho capito l'effettivo vantaggio. Cioè la rappresentazione in triple contiene di per se dei riferimenti ad una istruzione in un'altra tripla piuttosto che un temporaneo, e questo probabilmente è uno svantaggio. Infatti, per come ho capito io, si fa riferimento all'operazione che calcola il temporaneo presente nelle quadruple, quindi non ho il valore disponibile ma lo devo calcolare di volta in volta. Ma il problema non viene eliminato con le triple, perchè dall'array delle istruzioni ho un riferimento ad una tripla e questa poi può avere riferimento ad altre triple, quindi non vedo il vantaggio.

Non so se ho reso l'idea di cosa non capisco. Cmq il succo è se qualcuno può illuminarmi sui vantaggi dei vari metodi di rappresentazione.

Grazie!!!!

Risposte
Uccio1978
Ciao Lauke,

cercherò di chiarire i tuoi dubbi con parole semplici, sperando siano sufficienti; partiamo dall'assunto fatto dal libro di testo:

"L'autore del testo di Lauke":
A benefit of quadruples over triples can be seen in an optimizing compiler, where instructions are often moved around. With quadruples, if we move an instruction that computes a temporary t, then the instruction that use t require no change. With triples, the result of an operation is referred to by its position, so moving an instruction may require us to change all references to that result. This problem does not occur with indirect triples, which we consider next.


I compilatori, così come le CPU in fase d'esecuzione, tendono a riorganizzare le istruzioni in modo da ottimizzare le prestazioni o le fasi d'analisi successive. Questo "rimaneggiamento" viene generalmente attuato al termine dell'analisi semantica e spesso prevede degli spostamenti; la sequenza d'istruzioni necessaria allo svolgimento di una operazione, così come tradotta dall'analisi semantica può, infatti, non essere la migliore in assoluto. Premesso questo, esaminiamo un esempio di operazione scomponendola in tripla d'indirizzi: A = B + C * D.

Abbiamo quattro variabili (A, B, C e D) e tre operatori in gioco (=, + e *) e dato che dobbiamo adottare una rappresentazione a triple d'indirizzi, dovremo usare delle variabili temporanee per i risultati intermedi trasformando l'operazione nelle seguenti:

    T1 = C * D
    T2 = B + T1
    A = T2[/list:u:1tu6mtsc]

    Il nostro compilatore, così, memorizzerà le singole istruzioni in una lista indicizzata come la seguente:

    0: {*, C, D}
    1: {+, B, [0]} <-- [0] è l'indice della tripla nella lista e rappresenta T1
    2: {=, [1], A} <-- [1] è l'indice della tripla nella lista e rappresenta T2


    In questa situazione, se il compilatore valutasse che le migliori prestazioni si ottengono invertendo la istruzione descritta dalla tripla d'indice 1 con la 2, è chiaro che sarebbe costretto a modificare anche gli indici nelle triple stesse; un'operazione più complessa che richieda l'uso di molte altre variabili temporanee forzerebbe il compilatore a riesaminare e modificare molte degli elementi nella lista.

    "L'autore del testo di Lauke":
    "With indirect triples, an optimizing compiler can move an instruction by reordering the instruction list, without affecting the triples themselves."


    Una possibile soluzione all'inconveniente precedente è quella di adottare una rappresentazione leggermente differente che faccia uso di una indirezione; viene mantenuta, in pratica, un'ulteriore lista indicizzata per le istruzioni che abbini ad esse un riferimento alla lista delle triple d'indirizzi:

    # Lista delle istruzioni
    0: 100 <-- Puntatore alla lista delle triple d'indirizzi
    1: 101 <-- Puntatore alla lista delle triple d'indirizzi
    2: 102 <-- Puntatore alla lista delle triple d'indirizzi
    
    # Lista delle triple d'indirizzi
    100: {*, C, D}
    101: {+, B, [100]} <-- [100] è l'indice della lista nella lista e rappresenta T1
    102: {=, [101], A} <-- [101] è l'indice della lista nella lista e rappresenta T2


    Così non è più necessario modificare le triple d'indirizzi qualora il compilatore decidesse d'invertire le istruzioni analogamente al caso precedente; esso agirebbe, infatti, solo sulla lista delle istruzioni, risparmiandosi molto lavoro. Una rappresentazione in quadruple d'indirizzi, per sua natura, non è affetta da questo genere di problematiche e non necessita della lista aggiuntiva necessaria nella rappresentazione a triple indirette.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.