TIE448 Kääntäjätekniikka, syksy 2009 Antti-Juhani Kaijanaho TIETOTEKNIIKAN LAITOS 16. marraskuuta 2009
Sisällys
Sisällys
Seuraava deadline Vaihe E tiistai 1.12. klo 10 koodigenerointi (ilman rekisteriallokaatiota) Vaihe F maanantai 14.12. klo 10 rekisteriallokaatio
Kääntäjän rakenne lähdeohjelma SELAAJA sanasjono JÄSENTÄJÄ rakennepuu VÄLIKOODIN GENEROIJA välikoodi KOHDEKOODIN GENEROIJA kohdeohjelma TARKASTAJA SOKERINPILKKOJA OPTIMOIJA OPTIMOIJA
Rekisteriallokaatio Ideaalitilanteessa kaikki muuttujat ovat rekistereissä. Rekistereitä ei ole riittävästi. Tarvitaan vekotin, joka päättää, mitkä muuttujat ovat kulloinkin rekistereissä. olennainen käsitteellinen jako: lokaali (peruslohkojen sisäinen) globaali eli aliohjelmaa kokonaisuutena käsittelevä interproseduraalinen eli koko ohjelmaa kokonaisuutena käsittelevä Aiemmin esiteltiin yksinkertainen lokaali algoritmi. Nyt tarkoituksena puhua globaalista rekisteriallokaatiosta. Avuksi tarvitaan eloisuusanalyysiä, josta tänään.
Impressionistinen esimerkki syötteestä push rbp mov rbp, rsp ; ASSUME $f is in RDI ; ASSUME $a is in RSI ; REQUIRE $rv is in a register xor $rv, $rv cmp $a, 0 jna.l2 mov $rv, 1.L1: cmp $a, 0 jna.l2 ; REQUIRE $a is in RDI ; RELEASE RAX, RSI, RDX, RCX, R8, R9, R10, R11 call [$f] ; ASSUME RAX and RDX are taken ; REQUIRE $rv is in a register mul $rv ; ASSUME $rv is in RAX jump.l1.l2: ; REQUIRE $rv is in RAX leave ret
Sisällys
Peruslohkot engl. basic block voidaan etsiä niin välikielisestä kuin kohdekielisestä esityksestä Peruslohko on maksimaalinen ohjelman osa, jolle pätee seuraavaa: Siihen kuuluvat käskyt esiintyvät ohjelmassa peräkkäin. Siihen ei sisälly yhtään hyppykäskyä, paitsi mahdollisesti viimeisenä käskynä. Mistään ei hypätä sen keskelle. Määritelmästä seuraa mm. seuraavaa: Peruslohko vaihtuu aina hyppykäskyn jälkeen. Hyppykäskyn kohde aloittaa aina peruslohkon. Jokainen käsky kuuluu täsmälleen yhteen peruslohkoon.
Etsi peruslohkot push rbp mov rbp, rsp ; ASSUME $f is in RDI ; ASSUME $a is in RSI ; REQUIRE $rv is in a register xor $rv, $rv cmp $a, 0 jna.l2 mov $rv, 1.L1: cmp $a, 0 jna.l2 ; REQUIRE $a is in RDI ; RELEASE RAX, RSI, RDX, RCX, R8, R9, R10, R11 call [$f] ; ASSUME RAX and RDX are taken ; REQUIRE $rv is in a register mul $rv ; ASSUME $rv is in RAX jump.l1.l2: ; REQUIRE $rv is in RAX leave ret
engl. control flow graph suunnattu graafi, jossa solmuja ovat peruslohkot ja kaaret edustavat peruslohkojen välisiä hyppyjä mahdollista myös määritellä niin, että solmut ovat yksittäisiä käskyjä
Piirrä kontrollivuograafi push rbp mov rbp, rsp ; ASSUME $f is in RDI ; ASSUME $a is in RSI ; REQUIRE $rv is in a register xor $rv, $rv cmp $a, 0 jna.l2 mov $rv, 1.L1: cmp $a, 0 jna.l2 ; REQUIRE $a is in RDI ; RELEASE RAX, RSI, RDX, RCX, R8, R9, R10, R11 call [$f] ; ASSUME RAX and RDX are taken ; REQUIRE $rv is in a register mul $rv ; ASSUME $rv is in RAX jump.l1.l2: ; REQUIRE $rv is in RAX leave ret
Terminologiaa Solmulla on lähteviä kaaria (out-edges), tulevia kaaria (in-edges), seuraajasolmuja (successor nodes) ja edeltäjäsolmuja (predecessor nodes). Solmun n seuraajasolmujen joukko on succ(n) ja edeltäjäsolmujen joukko on pred(n).
Sisällys
engl. liveness analysis yksi tietovuoanalyysin (engl. data flow analysis) ilmentymä Muuttujalla tarkoitetaan tässä aliohjelman parametreja, muita paikallisia muuttujia sekä kääntäjän luomia väliaikaisia paikallisia muuttujia ei siis globaaleja muuttujia. Tarkastellaan kontrollivuograafia, jossa solmut ovat yksittäisiä käskyjä. mahdollista toki käyttää myös peruslohkoja peruslohkograafilla analyysi olisi nopeampaa mutta hieman sotkuisempaa
Muuttujan eloisuus Solmu käyttää muuttujaa, jos sen sisältämä käsky lukee muuttujan arvon. Solmu määrittelee muuttujan, jos sen sisältämä käsky kirjoittaa muuttujaan arvon. Muuttuja on elossa (engl. live) tietyssä kontrollivuograafin kaaressa, jos on olemassa suunnattu polku ko. kaaresta solmuun, joka käyttää kyseistä muuttujaa niin, etttä polulla ei ole kyseistä muuttujaa määrittelevää solmua. Muuttuja tulee elossa (engl. is live-in) solmuun, jos se on elossa jossain siihen tulevassa kaaressa. Muuttuja lähtee elossa (engl. is live-out) solmusta, jos se on elossa jossain siitä lähtevästä kaaresta.
Merkintöjä use(n) on solmun n käyttämien muuttujien joukko. def (n) on solmun n määrittelemien muuttujien joukko. in(n) on solmuun n elossa tulevien muuttujien joukko. out(n) on solmusta n elossa lähtevien muuttujien joukko.
Abstrakti analyysialgoritmi Syöte, jossa solmuja ovat käskyt, sekä kullekin solmulle use- ja def -joukot. Tulos Kullekin solmulle in- ja out-joukot. Algoritmi Tulokset ovat pienimmät in- ja out-joukot, joille pätee seuraavaa: Jos v use(n), niin v in(n). Jos v in(n), niin kaikilla n pred(n) pätee v out(n ). Jos v out(n) ja v def (n), niin v in(n).
Eloisuuden tietovuoyhtälöt Toisin sanoen: in(n) = use(n) (out(n) def (n)) out(n) = in(n ) n succ(n) Knasterin ja Tarskin lauseen 1 mukaan näillä joukkoyhtälöillä on vähintään yksi ratkaisu sekä yksikäsitteiset pienin ja suurin ratkaisu. 1 Alfred Tarski: A lattice-theoretical fixpoint theorem and its applications, Pacific Journal of Mathematics 5:2: 285-309, 1955.
Knasterin ja Tarskin lause 2 Olkoon meillä joukkoyhtälöryhmä X 1 = F 1 (X 1,..., X n ) X n = F n (X 1,..., X n ) Jos kullekin F i pätee, että se on aidosti monotoninen, eli jos väitteestä X j X j kaikilla j seuraa F i (X 1,..., X n ) F i (X 1,..., X n), niin yhtälöryhmällä on ainakin yksi ratkaisu, jos (X 1,..., X n ) ja (X 1,..., X n) ovat ratkaisuja, niin joko kaikilla i pätee X i X i tai kaikilla i pätee X i X i, on olemassa ratkaisu (X1,..., X n ) siten, että kaikilla ratkaisuilla (X 1,..., X n ) kaikille i pätee Xi X i, ja on olemassa ratkaisu (X1,..., X n ) siten, että kaikilla ratkaisuilla (X 1,..., X n ) kaikille i pätee X i Xi. 2 joukkoyhtälöryhmien tapauksesssa
Joukkoyhtälöryhmän ratkaiseminen Yleinen Knaster Tarskin täyttävien joukkoyhtälöryhmien ratkaisumenetelmä (pienimmän ratkaisun löytämiseksi) on ns. kiintopisteiteraatio: X1 = emptyset;... Xn = emptyset; do { X1 = X1;... Xn = Xn; X1 = F(X1,...,Xn );... Xn = F(X1,...Xn ); } while (X1!= X1... Xn!= Xn );
Konkreettinen algoritmi foreach n in(n) := out(n) := do foreach n in (n) := in(n) out (n) := out(n) in(n) := use(n) (out(n) def (n)) out(n) := in(n ) n succ(n) while n: in (n) = in(n) out (n) = out(n)
Tehokkuus pahin tapaus O(n 4 ), missä n on lauseiden määrä ohjelmassa solmut kannattaa käydä läpi mahdollisimman paljon kaarien vastaisessa järjestyksessä; tällöin yleensä o(n) ja O(n 2 ).
Kysymys Mistä on kyse, jos muuttuja tulee elossa aliohjelman ensimmäiseen käskyyn?
Sisällys
Seuraava deadline Vaihe E tiistai 1.12. klo 10 koodigenerointi (ilman rekisteriallokaatiota) Vaihe F maanantai 14.12. klo 10 rekisteriallokaatio