konstrukce p řekladačů

146
Konstrukce překladačů David Bednárek www.ksi.mff.cuni.cz

Upload: meara

Post on 19-Jan-2016

23 views

Category:

Documents


0 download

DESCRIPTION

Konstrukce p řekladačů. David Bednárek www.ksi.mff.cuni.cz. Pravidla studia. SWI109 2/ 1 Z,Zk. Pravidla studia. Cvičení Každých 14 dní Zápis v SIS Z ápočtové testy Hromadný termín na cvičení koncem semestru Opravné termíny individuálně ve zkušebních termínech - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Konstrukce p řekladačů

Konstrukce překladačů

David Bednárek

www.ksi.mff.cuni.cz

Page 2: Konstrukce p řekladačů

Pravidla studia

SWI109

2/1

Z,Zk

Page 3: Konstrukce p řekladačů

3 Pravidla studia

CvičeníKaždých 14 dníZápis v SISZápočtové testy

Hromadný termín na cvičení koncem semestru Opravné termíny individuálně ve zkušebních termínech

Alternativa: Implementace části překladače Podle zadání ze šk.r. 2010/11

PřednáškaZkouška - písemná

Page 4: Konstrukce p řekladačů

Literatura

Page 5: Konstrukce p řekladačů

5 Literatura A.V. Aho, R. Sethi, J.D. Ullman

Compiler: Principles, Techniques and Tools (1986) Grune, Bal, Jacobs, Langendoen

Modern Compiler Design (2000)• Přehled včetně front-endů a překladu neprocedurálních jazyků

Steven S. MuchnickAdvanced Compiler Design and Implementation (1997)

• Přehled optimalizací v back-endech Randy Allen, Ken Kennedy

Optimizing Compilers for Modern Architectures (2001)• Hardwarově závislé optimalizace

R. MorganBuilding an Optimized Compiler (1998)

Srikant, Shankar (eds.)The Compiler Design Handbook (2003)– Optimizations and Machine Code Generation

• Sbírka 22 článků J. R. Levine

Linkers and Loaders (1999)

Page 6: Konstrukce p řekladačů

Architektura překladače

Page 7: Konstrukce p řekladačů

7 Architektura překladače

Amatérský pohled

Lexikální analyzátor

Parser

Sémantický analyzátor

Generátor kódu

Posloupnost tokenů

Derivační strom

Derivační stromDerivační strom

Cílový kód

Page 8: Konstrukce p řekladačů

8 Architektura překladače

Z velké dálky

Generátor mezikódu

Lexikální analyzátor

Parser

Sémantický analyzátor

Generátor kódu

Posloupnost tokenů

Derivační strom

Derivační strom

Mezikód

Derivační strom

Cílový kód

front-endzávislý na vstupním jazyku

back-endzávislý na cílovém stroji

Page 9: Konstrukce p řekladačů

9 Architektura překladače

S optimalizacemi

Optimalizace

Generátor mezikódu

Strojově závislé optimalizace

Lexikální analyzátor

Parser

Sémantický analyzátor

Optimalizace

Generátor kódu

Strojově závislé optimalizace

Posloupnost tokenů

Derivační strom

Derivační strom

Derivační strom

Mezikód (střední úrovně)

Derivační strom

Mezikód (střední úrovně)

Mezikód (střední úrovně)

Mezikód nízké úrovně

Cílový kód

front-endzávislý na vstupním jazyku

back-endzávislý na cílovém stroji

Page 10: Konstrukce p řekladačů

10 Architektura překladače

Detailní pohled akademika (pouze optimalizace)• Muchnick: Advanced Compiler Design and Implementation

Scalar replacement of array referencesData-cache optimizations

Procedure integrationTail-call optimizationScalar replacement of aggregatesSparse conditional constant propagationInterprocedural constant propagationProcedure specialization and cloningSparse conditional constant propagation

Global value numberingLocal and global copy propagationSparse conditional constant propagationDead-code eliminationLocal and global common-subexpression eliminationLoop-invariant code motionDead-code eliminationCode hoistingInduction-variable strength reductionLinear-function test replacementInduction-variable removalUnnecessary bounds-checking eliminationControl-flow optimizations

In-line expansionLeaf-routine optimizationShrink wrappingMachine idiomsTail mergingBranch optimizations and conditional movesDead-code eliminationSoftware pipelining, loop unrollingBasic-block and branch schedulingRegister allocationBasic-block and branch schedulingIntraprocedural I-cache optimizationInstruction prefetchingData prefetchingBranch prediction

Interprocedural register allocationAggregation of global referencesInterprocedural I-cache optimization

Constant foldingAlgebraic simplification and reassociation

Page 11: Konstrukce p řekladačů

11 Architektura překladače

Realita GNU

CompilerCollectionInternals

Remove useless statements Mudflap declaration registration Lower control flow Lower exception handling control flow Build the control flow graph Find all referenced variables

RTL generation Generate exception handling landing pads Cleanup control flow graph Common subexpression elimination Global common subexpression elimination. Loop optimization Jump bypassing If conversion Web construction Life analysis Instruction combination Register movement Optimize mode switching Modulo scheduling Instruction scheduling Register class preferencingLocal register allocationGlobal register allocationReloadingBasic block reordering Variable tracking Delayed branch scheduling Branch shortening Register-to-stack conversion Final Debugging information output

Enter static single assignment form Warn for uninitialized variables Dead code elimination Dominator optimizations Redundant phi elimination Forward propagation of single-use variables Copy renaming PHI node optimizations May-alias optimization Profiling Lower complex arithmetic Scalar replacement of aggregates Dead store elimination

Tail recursion elimination Forward store motion Partial redundancy elimination Loop invariant motionCanonical induction variable creationInduction variable optimizationsLoop unswitchingVectorizationTree level if-conversion for vectorizer Conditional constant propagation Folding builtin functions Split critical edges Partial redundancy elimination Control dependence dead code elimination Tail call elimination Warn for function return without value Mudflap statement annotation Leave static single assignment form

Page 12: Konstrukce p řekladačů

Názvosloví

Page 13: Konstrukce p řekladačů

13 Základní bloky

Procedura Procedura nebo funkce

Call graph Graf (možného) volání mezi procedurami

Základní blok (BB – basic block) Část procedury bez větvení a smyček, se vstupem pouze na

začátku a výstupem pouze na konci Volání procedury může a nemusí být považováno za předěl BB

Tok řízení - control-flow (graph) Možnosti předávání řízení mezi základními bloky v proceduře Reprezentováno orientovaným (cyklickým) grafem

Tok dat - data-flow Předávání dat, obvykle uvnitř jednoho základního bloku Pro jeden BB může být reprezentováno dagem

Page 14: Konstrukce p řekladačů

14 Dag

Závislost (dependence) Povinnost provést jednu operaci/instrukci po jiné Částečné uspořádání operací/instrukcí v jednom BB

Datová závislost (dependence) Závislost producent-konzument v toku dat

Antidependence Read-Write: Čtení se musí stihnout před zápisem Write-Write: Pořadí zápisů se nesmí změnit Jiné důvody, obvykle nízkoúrovňového původu

Dag (directed acyclic graph) Orientovaný acyklický graf použitý pro zaznamenání

• data-flow

• závislostí

Page 15: Konstrukce p řekladačů

15 Typy

Skalární/jednoduchý/atomický typ (scalar) Typ, s nímž dokáže přímo pracovat cílový stroj

Složený typ (aggregate) Pole, struktura, třída, řetězec apod.

Zarovnání (alignment) Požadavek na umístění proměnné/paměťového místa na adrese

dělitelné 2, 4, 8, nebo 16 Striktní: Při nedodržení procesor vyvolá výjimku Optimalizační: Při nedodržení bude kód pomalejší

Page 16: Konstrukce p řekladačů

16 Proměnné

Proměnná (variable) Proměnná deklarovaná ve vstupním jazyce, včetně parametrů Pomocná proměnná (temporary) vytvořená překladačem

Statická/globální proměnná Proměnná s jedinou instancí přístupná všem procedurám

(Lokální) proměnná Parametr, deklarovaná či pomocná proměnná přístupná pouze

jedné proceduře

Jazyky s vnořenými procedurami vyžadují další kategorii proměnných přístupných z vnořených procedur

Paměťové místo Část proměnné nebo dynamicky alokované paměti

Page 17: Konstrukce p řekladačů

17 Alias

Alias Situace (nebo možnost výskytu situace), kdy k jedné proměnné, její

části, či paměťovému místu, vedou dvě různé přistupové cesty

int x; int a[ 20];int * p = & x; a[ i] = ...;

a[ j] = ...;

Rozhodnutí, zda může jít o alias, je obecně algoritmicky neřešitelná úloha

Pokud si překladač není jist, že o alias nejde, musí se chovat, jako by to alias byl

• Nejistý alias je ještě horší, než jistý

Proměnná bez aliasu Lokální proměnná, která prokazatelně nemá alias

• Všechny přístupy k ní lze jednoznačně určit

Page 18: Konstrukce p řekladačů

18 Live range

Doba života/rozsah platnosti proměnné (live range) Množina míst v proceduře, kdy je proměnná zapotřebí

• Tedy existuje možnost, že by ještě byla čtena (před zápisem)

Zkoumá se obvykle pouze pro skalární lokální proměnné bez aliasu

Variable splitting/renaming Proměnnou s nesouvislým rozsahem platnosti lze nahradit několika

jinými• Odpadne omezení na shodnou alokaci v jednotlivých souvislých

oblastích rozsahu platnosti

Page 19: Konstrukce p řekladačů

19 Alokace – přidělování místaStatická alokace (static allocation)

Pro statické proměnné Vyhrazení místa na „pevné“ adrese

• Podléhá relokaci při spojování linkerem a zavádění loaderem

Registrová alokace (register allocation) Pro skalární lokální proměnné bez aliasu Umístění do fyzického registru cílového stroje

• Pouze po dobu života proměnné• Omezeno počtem fyzických registrů

Zásobníková alokace (stack allocation) Umístění na zásobníku

• Zásobník může být definován procesorem nebo emulován Složené nebo aliasované lokální proměnné Proměnné, které se nevešly do registrů

Spill-code Kód „navíc“, který musel být přidán pro manipulaci s proměnnými, které se

nevešly do registrů

Page 20: Konstrukce p řekladačů

20 Volací konvence

Volací konvence• Úmluva o způsobu spolupráce volající a volané procedury• Definována cílovým prostředím nebo autorem překladače

Umístění parametrů• Zásobník nebo registry• Pořadí• Přesné umístění je komplikováno zarovnáním

Umístění návratové hodnoty• Obvykle registr• Složené typy se obvykle řeší jako parametry předávané odkazem

Odpovědnost za úklid zásobníku• Volající/volaný

Povinnost zachovat obsah registrů• Všechny, některé, nebo žádné

Další technické definice• Úprava jména procedury jako symbolu pro linker

• Pokročilá interprocedurální optimalizace: Automatická úprava volací konvence podle místních podmínek volaného a všech volajících

Page 21: Konstrukce p řekladačů

21 Činnost překladače, optimalizace

Intraprocedurální Uvnitř jedné procedury

Lokální Uvnitř jednoho základního bloku

• Příklad: Jednodušší verze schedulingu nebo CSE

Globální Pro celou proceduru najednou

• Příklad: Přidělování registrů, složitější CSE

Interprocedurální Pro celý program najednou Při separátním překladu modulů je součástí linkeru Obvykle exponenciální nebo algoritmicky neřešitelné úlohy

• Příklad: Interprocedurální analýza aliasů

• Srovnání: In-line expanze procedury patří formálně mezi intraprocedurální optimalizace

Page 22: Konstrukce p řekladačů

22 Typy

Logický typ Datový typ definovaný vstupním jazykem Základní typy + typové konstrukce Neomezená množina typů

Fyzický typ Typ rozeznávaný cílovým strojem Konečná množina vestavěných typů

• Celá čísla několika velikostí (znaménková a bezznaménková)

• Ukazatel (pokud nesplývá s celým číslem)

• Reálná čísla několika velikostí/přesností

Na ostatní typy se pohlíží jako na posloupnost bajtů• Rozhoduje délka, případně požadavek na zarovnání

Page 23: Konstrukce p řekladačů

23 Mezikódy Vysokoúrovňový mezikód

Reprezentace vstupního programu• Během fází, řešících konstrukce a pravidla vstupního jazyka• Užívá logické typy a operace vstupního jazyka

Nejčastěji ve formě anotovaného AST (abstract syntax tree)• Derivační strom podle abstraktní gramatiky

Mezikód střední úrovně Nejčastější hranice mezi front- a back-endem Na vstupním jazyce nezávislá reprezentace

• Užívá fyzické typy a operace na nich

Nejčastěji ve formě čtveřic• Tříadresové pseudoinstrukce, pomocné proměnné• Někdy ve speciálních formách (SSA – static single assignment)• Control-flow může být ve formě grafu BB (základních bloků)

Nízkoúrovňový mezikód Ekvivalent strojových instrukcí

• Nekompaktní forma, symbolické a relokované operandy• Před alokací registrů forma s neomezeným počtem virtuálních registrů

Někdy v univerzální strojově nezávislé formě (GCC RTL)

Page 24: Konstrukce p řekladačů

Mezikódy

Page 25: Konstrukce p řekladačů

25 Mezikódy

Informace uložené v mezikódu střední úrovněSeznam globálních proměnnýchDalší globální informace pro generovaný kódSeznam procedurDalší informace pro debugger

Page 26: Konstrukce p řekladačů

26 Mezikódy

Informace uložené v mezikódu střední úrovněSeznam globálních proměnných

• Velikost

• Inicializace

• Příznak konstantnosti

• Jméno (pro linker)

• Logický typ (pro debugger)

Další globální informace pro generovaný kód Konstanty (reálné, řetězcové, strukturované) Tabulky virtuálních funkcí, RTTI Často splývají s globálními proměnnými

Seznam procedurDalší informace pro debugger

Jména a konstrukce typů

Page 27: Konstrukce p řekladačů

27 Mezikódy

Popis procedury Jméno (pro linker a chybová hlášení)

Seznam parametrů Fyzický typ (+ velikost) Umístění podle volací konvence Jméno (pro debugger a chybová hlášení) Logický typ (pro debugger a určení aliasů)

Seznam lokálních proměnných Fyzický typ (+ velikost) Jméno (pro debugger a chybová hlášení) Logický typ (pro debugger a určení aliasů) Proměnné ve vnořených blocích se obvykle povyšují na úroveň

procedury

Kód proceduryDalší informace (popisy výjimek apod.)

Page 28: Konstrukce p řekladačů

28 Mezikódy

Kód proceduryPlně sekvenční forma

Posloupnost (pseudo-)instrukcí virtuálního stroje Tok řízení popsán skokovými instrukcemi

Částečně sekvenční forma Tok řízení popsán grafem, jehož uzly jsou základní bloky Každý základní blok obsahuje posloupnost (pseudo-)instrukcí

• Skokové instrukce pouze na konci BB nebo zaznamenány jinak

Nesekvenční forma Tok řízení popsán grafem, jehož uzly jsou základní bloky Tok dat uvnitř základního bloku popsán dagem

• Různé formy podle stupně analýzy aliasů a rozsahů platnosti

• Pokročilejší formy nahrazují lokální proměnné rozhraními bloků

Page 29: Konstrukce p řekladačů

29 Plně sekvenční čtveřicový mezikódint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

TMP:(T1,B),(T2,B),(T3,I32)

ENTER

GT_I32 T1,Px,Py

JF T1,L1

MOV_I32 Vz,Py

MOV_I32 Py,Px

MOV_I32 Px,Vz

L1:

GT_I32 T2,Px,C1

JF T2,L2

MOD_I32 T3,Py,Px

MOV_I32 Vz,T3

MOV_I32 Py,Px

MOV_I32 Px,Vz

JMP L1

L2:

RET_I32 Py

Page 30: Konstrukce p řekladačů

30 Částečně sekvenční čtveřicový mezikódint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

TMP:(T1,B),(T2,B),(T3,I32)

ENTERGT_I32 T1,Px,PyJC T1

GT_I32 T2,Px,C1JC T2

RET_I32 Py

MOV_I32 Vz,PyMOV_I32 Py,PxMOV_I32 Px,Vz

MOD_I32 T3,Py,PxMOV_I32 Vz,T3MOV_I32 Py,PxMOV_I32 Px,Vz

Page 31: Konstrukce p řekladačů

31 Nesekvenční mezikód (před analýzou aliasů)int gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

LD_I32(Py)

RET_I32

Control-Flow

vždy

if true

if false

Dag

Data-flow

Závislosti

Page 32: Konstrukce p řekladačů

32 Mezikódy střední úrovně

Plně sekvenční formaČástečně sekvenční formaNesekvenční forma

Všechny tyto formy lze generovat přímoz abstraktního syntaktického stromu

Jedním průchodem zdola nahoru• goto je nutné ošetřit dodatečnými zásahy (backpatching)

Strom nemusí fyzicky existovat,postačí průchod myšleným stromem

• LR analýza: pravá derivace pozpátku

• LL analýza rekurzivním sestupem

Většina front-endů přesto strom konstruuje• Složité konstrukce jazyka (šablony, předkompilované části)

• Rozhraní mezi syntaktickým a sémantickým analyzátorem

• Optimalizace

Page 33: Konstrukce p řekladačů

33 Mezikódy střední úrovně

Plně sekvenční formaČástečně sekvenční formaNesekvenční forma

Táž forma se obvykle v průběhu překladu upravuje Připojují se odvozené informace a optimalizační rozhodnutí Provádějí se ekvivalentní úpravy (optimalizace)

Jedna forma může mít různé variace A to i uvnitř jednoho překladače Odráží různé způsoby a/nebo různé stupně analýzy

Řada překladačů užívá dvě z těchto forem Z historických důvodů (stabilita rozhraní front-end/back-end) Pro vytvoření druhé formy je nutná analýza první formy

Page 34: Konstrukce p řekladačů

34 Detekce základních blokůCONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

TMP:(T1,B),(T2,B),(T3,I32)

ENTER

GT_I32 T1,Px,Py

JF T1,L1

MOV_I32 Vz,Py

MOV_I32 Py,Px

MOV_I32 Px,Vz

L1:

GT_I32 T2,Px,C1

JF T2,L2

MOD_I32 T3,Py,Px

MOV_I32 Vz,T3

MOV_I32 Py,Px

MOV_I32 Px,Vz

JMP L1

L2:

RET_I32 Py

V sekvenčním mezikódu Základní blok

Začíná• Na začátku procedury• V cíli skoku• Za podmíněným skokem

Končí• Podmíněným skokem• Nepodmíněným skokem• Návratem z procedury• Před cílem skoku

Page 35: Konstrukce p řekladačů

35 Detekce základních blokůCONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

TMP:(T1,B),(T2,B),(T3,I32)

ENTER

GT_I32 T1,Px,Py

JF T1,L1

MOV_I32 Vz,Py

MOV_I32 Py,Px

MOV_I32 Px,Vz

L1:

GT_I32 T2,Px,C1

JF T2,L2

MOD_I32 T3,Py,Px

MOV_I32 Vz,T3

MOV_I32 Py,Px

MOV_I32 Px,Vz

JMP L1

L2:

RET_I32 Py

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

TMP:(T1,B),(T2,B),(T3,I32)

ENTERGT_I32 T1,Px,PyJC T1

GT_I32 T2,Px,C1JC T2

RET_I32 Py

MOV_I32 Vz,PyMOV_I32 Py,PxMOV_I32 Px,Vz

MOD_I32 T3,Py,PxMOV_I32 Vz,T3MOV_I32 Py,PxMOV_I32 Px,Vz

Page 36: Konstrukce p řekladačů

36 Detekce základních blokůint gcd( int x, int y){ int z; if ( x > y ) { z = y; y = x; x = z; } while ( x > 0 ) { z = y % x; y = x; x = z; } return y;}

Ve zdrojovém kódu Základní blok

Začíná• Na začátku procedury• Na začátku then a else bloku• Na začátku těla cyklu• Za if příkazem• Za while cyklem

Končí• Na konci procedury• Na konci then a else bloku• Na konci těla cyklu• Na konci podmínky v if• Na konci podmínky ve while• Příkazem return/break apod.

Komplikace Zkrácené vyhodnocování

booleovských výrazů Podmíněný výraz Příkaz goto

Page 37: Konstrukce p řekladačů

37 Detekce základních blokůint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

TMP:(T1,B),(T2,B),(T3,I32)

ENTERGT_I32 T1,Px,PyJC T1

GT_I32 T2,Px,C1JC T2

RET_I32 Py

MOV_I32 Vz,PyMOV_I32 Py,PxMOV_I32 Px,Vz

MOD_I32 T3,Py,PxMOV_I32 Vz,T3MOV_I32 Py,PxMOV_I32 Px,Vz

Page 38: Konstrukce p řekladačů

38 Nesekvenční mezikód s hranicemi příkazůint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

LD_I32(Py)

RET_I32

Control-Flow

vždy

if true

if false

Dag

operand

Page 39: Konstrukce p řekladačů

39 Nesekvenční mezikód před analýzou aliasůint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

LD_I32(Py)

RET_I32

Control-Flow

vždy

if true

if false

Dag

operand

pořadí

Page 40: Konstrukce p řekladačů

40 Odstranění závislostí po analýze aliasů

LD_I32(Py)

ST_I32(Vz)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

MOD_I32

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

LD_I32(Px)

Page 41: Konstrukce p řekladačů

41 Odstranění závislostí po analýze aliasů

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

RET_I32

LD_I32(Py)

ST_I32(Vz)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

LD_I32(Py)

RET_I32

Page 42: Konstrukce p řekladačů

42 Nesekvenční mezikód po analýze aliasůint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

RET_I32

LD_I32(Py)

ST_I32(Vz)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

Control-Flow

vždy

if true

if false

Dag

dependence:

operand

w-r

w-?

antidependence:

r-w

?-w

Page 43: Konstrukce p řekladačů

43 Nesekvenční mezikód s rozsahy platnostiint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

Dag

operand

antidependence:

r-w GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

RET_I32

LD_I32(Py)

ST_I32(Vz)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

Oblasti platnosti

Px

Py

Vz/1

Vz/2

Page 44: Konstrukce p řekladačů

44 Algoritmus: Určení rozsahů platnosti VAR – množina proměnných Orientovaný graf control-flow v proceduře: (BB,CF)

BB – množina základních bloků CF BB BB – přechody mezi základními bloky

Lokální analýza Vnitřní chování každého základního bloku W : BB VAR → Bool – blok zapisuje do proměnné R : BB VAR → Bool – blok čte proměnnou před prvním zápisem Triviální algoritmus

Globální analýza Platnost proměnných na začátku každého základního bloku L : BB VAR → Bool – proměnná je živá na začátku bloku Polynomiální algoritmus

Dopočet Platnost proměnných na koncích bloků a uvnitř bloků Detekce čtení nezapsaných proměnných Triviální algoritmus

Vylepšení Určení komponent souvislosti a přeznačení proměnných

Page 45: Konstrukce p řekladačů

45 Algoritmus: Určení rozsahů platnostiVstup

(BB,CF) – graf control flow W(b,v) – blok b zapisuje do proměnné v R(b,v) – blok b čte proměnnou v před prvním zápisem do ní

Výstup L(b,v) – proměnná v je živá na začátku bloku b

for each b in BB L(b,v) = R(b,v);do { for each <b1,b2> in CF L(b1,v) |= ~ W(b1,v) & L(b2,v);} while changed;

Algoritmus se provádí vektorově Pro všechny proměnné (v) najednou

• Překladač využije SIMD instrukce O(|BB|*|CF|*|VAR|)

Page 46: Konstrukce p řekladačů

46 Určení rozhraní BB

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

RET_I32

LD_I32(Py)

ST_I32(Vz)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Py)

ST_I32(Vz)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

RET_I32

Page 47: Konstrukce p řekladačů

47 Nesekvenční mezikód s rozhraními BBint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

VAR:(Vz,I32,”z”)

Rozhraní 1

Px

Py

Rozhraní 2

Px

Py

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Py)

ST_I32(Vz)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

RET_I32

Dag

operand

antidependence:

r-w

Page 48: Konstrukce p řekladačů

48 Náhrada proměnných rozhraním BB

GT_I32

JC

ENTER

GTC_I32(C1)

JC

RET_I32

MOD_I32

GT_I32

LD_I32(Px) LD_I32(Py)

JC

ENTER

LD_I32(Py)

ST_I32(Vz)

LD_I32(Px)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Py)

ST_I32(Vz)

ST_I32(Py)

LD_I32(Vz)

ST_I32(Px)

LD_I32(Px)

MOD_I32

GTC_I32(C1)

JC

LD_I32(Px)

LD_I32(Py)

RET_I32

Page 49: Konstrukce p řekladačů

49 Nesekvenční mezikód bez proměnnýchint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

Dag

data

Rozhraní 1

Px

Py

Rozhraní 2

Px

Py

GT_I32

JC

ENTER

GTC_I32(C1)

JC

RET_I32

MOD_I32

Page 50: Konstrukce p řekladačů

50 Nesekvenční mezikód po duplikaci BBint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

Dag

data

Rozhraní 1

Px

Py

Rozhraní 2

Px

PyRET_I32

GTC_I32(C1)

JC

GT_I32

JC

ENTER

MOD_I32

MOD_I32

GTC_I32(C1)

JC

RET_I32

Page 51: Konstrukce p řekladačů

51 Nesekvenční mezikód po přeznačeníint gcd( int x, int y)

{ int z;

if ( x > y )

{

z = y;

y = x;

x = z;

}

while ( x > 0 )

{

z = y % x;

y = x;

x = z;

}

return y;

}

CONST:(C1,I32,0)

PROC ”gcd”

PARAM:(Px,I32,”x”),(Py,I32,”y”)

RET_I32

GTC_I32(C1)

JC

GT_I32

JC

ENTER

MOD_I32

MOD_I32

GTC_I32(C1)

JC

RET_I32

Page 52: Konstrukce p řekladačů

52 Nesekvenční mezikód po přeznačení

int gcd( int x, int y)

{ if ( x > y )

goto L2;

L1:

if ( x <= 0 )

return y;

y = y % x;

L2:

if ( y <= 0 )

return x;

x = x % y;

goto L1;

}

RET_I32

GTC_I32(C1)

JC

GT_I32

JC

ENTER

MOD_I32

MOD_I32

GTC_I32(C1)

JC

RET_I32

Page 53: Konstrukce p řekladačů

53 Nesekvenční mezikód po optimalizaci skoků

int gcd( int x, int y)

{ if ( x > y )

goto L4;

if ( x <= 0 )

goto L3;

L1:

if ( (y = y % x) <= 0 )

goto L5;

L2:

if ( (x = x % y) > 0 )

goto L1;

L3:

return y;

L4:

if ( y > 0 )

goto L2;

L5:

return x;

}

GTC_I32(C1)

JC

MOD_I32

GTC_I32(C1)

JC

GTC_I32(C1)

JC

GTC_I32(C1)

JC

MOD_I32

RET_I32

GT_I32

JC

ENTER

RET_I32

L4

L3

L1

L2 L5

Page 54: Konstrukce p řekladačů

54 Architektura back-endu

Různé vnitřní reprezentaceMezikód střední úrovně

Nezávislá sada operací• ADD_I32 a,b,c

Forma• Nesekvenční

• Částečně sekvenční

Mezikód nízké úrovně Ekvivalenty strojových instrukcí

• add r1,r2

Forma• Nesekvenční

• Částečně sekvenční

• SekvenčníStrojově závislé optimalizace

Optimalizace

Generátor kódu

Strojově závislé optimalizace

Mezikód (střední úrovně)

Mezikód (střední úrovně)

Mezikód nízké úrovně

Cílový kód

Mezikód (střední úrovně)

Page 55: Konstrukce p řekladačů

55 Architektura back-endu

Sekvenční mezikód

Strojově závislé optimalizace

Alokace registrů

Sekvenční mezikódnízké úrovněs fyzickými registry

Strojově závislé optimalizace

Optimalizace

Instruction selection= Výběr instrukcí

Strojově závislé optimalizace

Sekvenční mezikód(střední úrovně)

Sekvenční mezikód(střední úrovně)

Sekvenční mezikódnízké úrovně s virtuálními registry

Sekvenčnímezikódnízké úrovněs virtuálními registry

Sekvenční mezikód(střední úrovně)

Finalizer

Sekvenční mezikód

Strojový kód

Page 56: Konstrukce p řekladačů

56 Architektura back-endu

Sekvenční mezikód

Alokace registrů

Optimalizace

Optimalizace

Instruction selection= Výběr instrukcí

Finalizer

Zjednodušená analýza rozsahů platnosti

Sekvenční mezikód (střední úrovně)

Sekvenční mezikód nízké úrovně s virtuálními registry

Sekvenční mezikód nízké úrovně s fyzickými registry

Strojový kód

Analýza aliasů

Optimalizace

Page 57: Konstrukce p řekladačů

57 Architektura back-endu

Částečně sekvenční mezikód bez schedulingu

Optimalizace

Alokace registrů

Optimalizace

Optimalizace

Instruction selection= Výběr instrukcí

Finalizer

Detekce základních bloků

Live-range analysis= Analýza rozsahů platnosti

Basic-block (re)ordering= Serializace control-flow

Sekvenční mezikód (střední úrovně)

Částečně sekvenční mezikód (střední úrovně)

Částečně sekvenční mezikód nízké úrovně s virtuálními registry

Částečně sekvenční mezikód nízké úrovně s fyzickými registry

Sekvenční mezikód nízké úrovně s fyzickými registry

Strojový kód

Analýza aliasů

Optimalizace

Page 58: Konstrukce p řekladačů

58 Architektura back-endu

Částečně sekvenční mezikód se schedulingem

Optimalizace

Alokace registrů

Optimalizace

Optimalizace

Instruction selection= Výběr instrukcí

Finalizer

Detekce základních bloků

Live-range analysis= Analýza rozsahů platnosti

Basic-block (re)ordering= Serializace control-flow

Sekvenční mezikód (střední úrovně)

Částečně sekvenční mezikód (střední úrovně)

Částečně sekvenční mezikód nízké úrovně s virtuálními registry

Částečně sekvenční mezikód nízké úrovně s fyzickými registry

Sekvenční mezikód nízké úrovně s fyzickými registry

Strojový kód

Analýza aliasů

Optimalizace

Instruction scheduling= Řazení instrukcí

Instruction scheduling= Řazení instrukcí

Page 59: Konstrukce p řekladačů

59 Architektura back-endu

Nesekvenční mezikód

Optimalizace

Alokace registrů

Optimalizace

Optimalizace

Instruction selection= Výběr instrukcí

Finalizer

Detekce základních bloků

Live-range analysis= Analýza rozsahů platnosti

Basic-block (re)ordering= Serializace control-flow

Sekvenční mezikód (střední úrovně)

Nesekvenční mezikód (střední úrovně)

Částečně sekvenční mezikód nízké úrovně s virtuálními registry

Částečně sekvenční mezikód nízké úrovně s fyzickými registry

Sekvenční mezikód nízké úrovně s fyzickými registry

Strojový kód

Analýza aliasů

Optimalizace

Instruction scheduling= Řazení instrukcí

Instruction scheduling= Řazení instrukcí

Nesekvenční mezikód nízké úrovně s virtuálními registry

Page 60: Konstrukce p řekladačů

60 Architektura back-endu

Instruction selection Výběr strojových instrukcí

• 1:n – přímočaré řešení

• m:n – stromové/grafové gramatiky apod.

Vliv na kvalitu kódu poklesl• RISC, load-store kód apod.

Instruction scheduling Řazení instrukcí pro lepší využití ILP (instruction-level parallelism)

• NP-úplná úloha

Lokální v BB• Speciální řešení smyček (software pipelining)

• Částečně globální varianty (trace scheduling)

Zrychluje kód o 30-150%

Register allocation Přidělování fyzických registrů

• NP-úplná úloha

• Standardní řešení: Barvení grafu

Page 61: Konstrukce p řekladačů

61 Architektura back-endu

ILP (instruction-level parallelism)Pipeline

Instrukce se zpracovává v několika fázích (stages)• fetch – read – execute – write

V jednom okamžiku se provádějí různé fáze různých instrukcí Závislosti po sobě jdoucích instrukcí způsobují:

• Pipeline stall – zdržení (i486)• Nekorektní provedení kódu (Sparc)

Superskalární procesory (MIMD) Několik výkonných jednotek (Pentium: 2) V jednom okamžiku se provádějí stejné fáze několika instrukcí

Vektorové procesory (SIMD) Mnoho výkonných jednotek (Cray: 64)

• Slabší varianty: Pentium MMX/SSE V jednom okamžiku se provádí tatáž instrukce mnohokrát Využití nepatří pod pojem scheduling

• Automatická vektorizace používá podobné algoritmy jako některé metody schedulingu

Page 62: Konstrukce p řekladačů

62 Alokace registrů

VstupČástečně sekvenční kód

Možnost přesně definovat rozsahy platnosti

Ekvivalenty strojových instrukcí Speciální zpracování přesunových instrukcí

Instrukce pracují s virtuálními registryOptimistický kód

Všechny jednoduché proměnné bez aliasu v registrech

Spočtené rozsahy platnosti proměnných Množina bodů v mezikódu, kde je proměnná živá

• Hranice základních bloků

• Hranice mezi instrukcemi

• Přesnější informace v místech, kde je proměnná čtena/zapisována

VýstupPřiřazení virtuálních registrů fyzickým

Page 63: Konstrukce p řekladačů

63 Alokace registrů

Optimalizace: Minimalizace přesunových instrukcíVytvoření matice kolizí

C : VAR VAR → Bool Matice je velká, ale potřebujeme rychlý přístup

Kolize = neprázný průnik oblastí platnosti Zvláštní posouzení okrajových doteků oblastí

Odhad ceny za spill-kódP : VAR → Integer

Odhad počtu použití proměnné v průměrném provedení procedury

Vlastní algoritmus alokaceBarvení grafu (VAR,C) n barvami

n je počet fyzických registrů NP-úplná úloha, dobré heuristické řešení

Doplnění spill-kódu

Page 64: Konstrukce p řekladačů

64 Alokace registrů

Barvení grafu (VAR,C) n barvamin je počet fyzických registrůNP-úplná úloha, dobré heuristické řešení

PrincipMá-li vrchol méně než n sousedů, lze jej vždy obarvit

Dvě fázePostupné odebírání vrcholů

Ve vhodném pořadí tak, aby později měly šanci na obarvení Odebrané vrcholy se ukládají na zásobník

Zpětná rekonstrukce grafu Vrcholy se odebírají ze zásobníku Pokud je lze obarvit, obarví se a přidají do grafu Neobarvitelné nebudou přiděleny do registru

Page 65: Konstrukce p řekladačů

65 Alokace registrů

Vstup: graf (VAR,C), ceny P, počet n(VAR2,C2) := (VAR,C)

while not empty(VAR2) do

if not exists v:VAR2 st deg(v,C2) < n then

select v st P(v) is minimal; // or deg(v,C2) is maximal

end if;

(VAR2,C2) := (VAR2-{v},C2-edges(v))

stack.push(v);

end while;

while not empty(stack) do

stack.pop(v)

M = {u VAR2; <v,u> C} if exists i {1..n} st not i color(M) then color(v) := i

(VAR2,C2) := (VAR2+{v},C2+)

else

spill(v) := true

end if

end while

Výstup: přidělení registrů color, nepřidělené registry spill

Page 66: Konstrukce p řekladačů

66 Alokace registrů

Optimalizace: Minimalizace přesunových instrukcíJednoduché řešení: Ztotožnit virtuální registry spojené

přesunovou instrukcí Nelze vždy – ztotožňované registry mohou spolu kolidovat Duplikace kódu může pomoci

Složitější řešení: Úprava algoritmu alokace Určení skupin uzlů svázaných přesunovými instrukcemi Při obarvování vybírat zároveň všechny obarvitelné uzly skupiny

Page 67: Konstrukce p řekladačů

67 Alokace registrů

Doplnění spill-kóduAlokovat neobarvené uzly na zásobníku

Podobný algoritmus barvení grafu s neomezeným n

Opatřit každou instrukci spill-kódem Prefix: Přesun neobarvených vstupních operandů do registrů Suffix: Přesun neobarvených výstupních operandů do paměti

Problém: kde vzít registry pro tyto operandy Jednoduché řešení: Rezervované nepřidělované registry Lepší řešení: Alokovat pomocné registry v rámci normální alokace

• Vstupy a výstupy každé instrukce označeny jako uzly grafu

• Nekolidují s virtuálními registry, na které se vážou

• Kolidují mezi sebou a s ostatními živými virtuálními registry

• Opatřeny nejvyšší cenou

Problém: spill-kód je často zbytečný Dodatečná optimalizace – eliminace redundantních přesunů

Page 68: Konstrukce p řekladačů

68 Alokace registrů

Množiny povolených registrůPro každý operand každé instrukce je určena množina

registrů, v nichž může být tento operandOrtogonální sada instrukcí

Každé dvě množiny povolených registrů jsou buď identické nebo disjunktní

Alokace registrů se spouští pro každou množinu zvlášťNeortogonální sada instrukcí

Množiny povolených registrů se simulují v grafu kolizí Přidat úplný podgraf uzlů vysoké priority - reprezentují fyzické

registry Spojit hranou všechny virtuální registry s těmi fyzickými, do kterých

nesmí být přiděleny

Problém: Nemusí existovat obarvení Odložení do paměti, přestože stačí přesun mezi registry

Page 69: Konstrukce p řekladačů

69 Alokace registrů

Další problémySubregistry

Intel IA-32: al-ax-eax-edx:eax Řešení:

• Povýšení na větší registr - neoptimální

• Různé triky při vytváření grafů kolizí

Registrové volací konvence Volání procedury se chová jako instrukce používající několik

registrů Neortogonální – volací konvence předepisuje, ve kterém registru má

být který operand• Často vede k neřešitelným kolizím – zbytečný spill-kód

Řešení: Rozsah platnosti proměnné se rozdělí na oblasti• Kolem každé instrukce, používající proměnnou, jedna oblast

• Oblasti se dotýkají v místě, kde by byla přesunová instrukce, pokud by byla zapotřebí

• Uzly reprezentující oblasti téže proměnné se přednostně obarvují toutéž barvou

Page 70: Konstrukce p řekladačů

70 Scheduling

Provádí se na jednom základním blokuTrace scheduling: Vybraná posloupnost BB slita do jednohoSoftware pipelining: Speciální řešení pro BB jako cyklus

VstupDag

Uzly = instrukce Hrany = závislosti

Model procesoru Latence – časování závislých dvojic instrukcí Rezervační tabulky – schopnosti paralelního zpracování

VýstupPřiřazení času každému uzlu dagu

Čas měřen cykly procesoru Instrukce trvá několik cyklů – zvolen referenční bod

• Obvykle začátek zpracování po načtení a dekódování instrukce

Page 71: Konstrukce p řekladačů

71 Scheduling

DagUzly = instrukceHrany = závislosti

Dependence vzniklé z předávání dat v registrech Dependence a antidependence z přístupů do paměti

• Opatrný přístup: Možná závislost => závislost

Antidependence vzniklé ze soupeření o registry• Při schedulingu po alokaci registrů

Další závislosti z technických příčin• Manipulace se zásobníkem, skoky apod.

Instrukce volání procedury „Nekonečně“ dlouhé časování Často považována za hranici mezi BB

• Omezená optimalizace přesunem přes volání

Page 72: Konstrukce p řekladačů

72 Scheduling

VýstupPřiřazení času každému uzlu dagu

Aplikace výstupu schedulinguBěžné procesory (Intel IA-32, včetně x86_64)

Seřazení instrukcí podle schedulovaného času Procesor nemusí dodržet předpokládaný čas

Procesory se sekvenčními body (Intel IA-64) V kódu jsou mezi instrukcemi označeny sekvenční body (stops) Procesor má právo přeházet pořadí instrukcí mezi sekvenčními

body• Ignorují se antidependence i některé dependence

Výstupem scheduleru jsou i sekvenční body

VLIW procesory Very Large Instruction Word

• Instrukce řídí paralelní činnost jednotek procesoru

Jeden schedulovaný čas = jedna instrukce

Page 73: Konstrukce p řekladačů

73 Scheduling

Scheduling pouze odhaduje skutečné časováníSkutečné časování je ovlivněno nepředvídatelnými jevy

Zbytky rozpracovaných instrukcí z předchozího BB• Řešení: Trace-scheduling, řízení profilem

Paměťová hierarchie• Doba přístupu k paměti závisí na přítomnosti v cache

• Obvykle se předpokládá nejlepší možný průběh

• Speciální problém: Multithreaded aplikace na multiprocesorech

Fetch bandwidth• Instrukce nemusí být načteny a dekódovány včas

• Zdržují skoky a soupeření o přístup do paměti

• Přesné simulování fetch jednotky by neúměrně komplikovalo scheduler

Scheduler nezná skutečné závislosti přístupů do paměti Musí postupovat opatrně a zohledňuje i nejisté závislosti Procesor zná skutečné adresy přístupů a detekuje pouze skutečné

závislosti• Agresivně optimalizující procesor může zvolit zcela jiné pořadí instrukcí

Page 74: Konstrukce p řekladačů

74 Scheduling

Model procesoruLatence – časování závislých dvojic instrukcí

Počet cyklů procesoru, který musí proběhnout mezi referenčními body závislých instrukcí

U antidependencí a ve speciálních případech může být nulová U procesorů se sekvenčními body může být záporná Latence se obvykle zapisuje ke hranám dagu

• Přiřazena na základě klasifikace závislosti podle tabulek latencí

Page 75: Konstrukce p řekladačů

75 Scheduling

Model procesoruRezervační tabulky – schopnosti paralelního zpracování

Procesor je rozdělen na funkční jednotky různých druhů Je určen počet jednotek každého druhu

• Limit: Kind -> N

Pro každou instrukci definována rezervační tabulka• Res(instr): Time × Kind → N

• Počet jednotek daného druhu, který instrukce potřebuje v daném čase (měřeno od referenčního bodu)

Rezervační tabulky jsou nutné i pro procesory, které nejsou super-skalární

• Mají Limit(k)=1, ale různé a tudíž konfliktní rezervační tabulky

Page 76: Konstrukce p řekladačů

76 Příklad – mezikód střední úrovně

char chksum( char * p, int i)

{

char s = 0;

while ( i > 0 )

{

s ^= *p++;

--i;

}

return s;

}

GTC_I32(C1)

JC

XLD_I8

RET_I32

GTC_I32(C1)

JC

ENTER

C_I8(C2)

ADDC_P(C3)

SUBC_I32(C4) XOR_I8

Page 77: Konstrukce p řekladačů

77 Příklad – mezikód nízké úrovně

char chksum( char * p, int i)

{

char s = 0;

while ( i > 0 )

{

s ^= *p++;

--i;

}

return s;

}

cmp ri,0

jgt

mov r1,[rp]

ret

cmp i,0

jgt

mov rs,0

inc rp

dec ri xor rs,r1

Page 78: Konstrukce p řekladačů

78 Příklad – latence Tabulka latencí

Instrukce-instrukce

Instrukce-konec BB• Pesimistická varianta

(instrukce musí být dokončena v tomto BB)

• Pesimistický přístup na konci BBumožňuje optimistiký přístup na začátku: Latence začátek BB-instrukce jsou považovány za nulové

• Instrukce jgt musí být poslední• Latence vůči konci BB se

normalizují odečtením latence jgt

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r1

4

2

1

z instrukce do instrukce čas

cmp ri,0 jgt 1

mov r1,[rp] xor rs,r1 4

dec ri cmp ri,c 2

mov r1,[rp] inc rp 0

z instrukce čas

inc rp 2

jgt 1

dec ri 2

xor rs,r1 2

1

11

0

Page 79: Konstrukce p řekladačů

79

Rezervační tabulky

Příklad – rezervační tabulky

Kapacita procesoru

inc r1dec r1xor r1,r2cmp r1,r2

R MEM ALU W

0 1

1 1

2 1

mov r1,[r2] R MEM ALU W

0 1

1 1

2 1

3 1

4 1

jgt R MEM ALU W

0 1

R MEM ALU W

1 1 2 1

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r1

4

2

1

1

11

0

Page 80: Konstrukce p řekladačů

80

Krok 1Připravené instrukce

inc rp dec ri mov r1,[rp]

Kritická cesta mov r1,[rp] – 5

Vybrána instrukce mov r1,[rp]

Umístěna do času 0

Příklad – scheduling

čas R MEM ALU W

0 mov

1 mov

2 mov

3 mov

4 mov

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r1

4

2

1

1

11

0

Page 81: Konstrukce p řekladačů

81

Krok 2Připravené instrukce

inc rp dec ri xor rs,r1

Kritická cesta xor rs,r1 – 5

Vybrána instrukce xor rs,r1

Čas 4 určen latencí

Příklad – scheduling

čas R MEM ALU W

0 mov

1 mov

2 mov

3 mov

4 xor mov

5 xor

6 xor

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r1

4

2

1

1

11

0

0

Page 82: Konstrukce p řekladačů

82

Krok 3Připravené instrukce

inc rp dec ri

Kritická cesta dec ri - 4

Vybrána instrukce dec ri

Čas 0 vyhovuje latenci Rezervační tabulky jsou

obsazeny

Zvolen čas 1

Příklad – scheduling

čas R MEM ALU W

0 mov

1 dec mov

2 mov dec

3 mov dec

4 xor mov

5 xor

6 xor

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r14

2

1

1

11

0

0

Page 83: Konstrukce p řekladačů

83

Krok 4Připravené instrukce

inc rp cmp ri,0

Kritická cesta cmp ri,0 – 4

Vybrána instrukce cmp ri,0 – 4

Čas 3 určen latencí

Příklad – scheduling

čas R MEM ALU W

0 mov

1 dec mov

2 mov dec

3 cmp mov dec

4 xor cmp mov

5 xor cmp

6 xor

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r1

4

2

1

1

11

0

1

0

Page 84: Konstrukce p řekladačů

84

Krok 5Připravené instrukce

inc rp (jgt) – musí být poslední

Vybrána instrukce inc rp

Čas 0 vyhovuje latenciRezervační tabulky pro

časy 0-4 obsazenyUmístěno v čase 5

Příklad – scheduling

čas R MEM ALU W

0 mov

1 dec mov

2 mov dec

3 cmp mov dec

4 xor cmp mov

5 inc xor cmp

6 inc xor

7 inc

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r1

4

3

1

1

11

0

1

0

Page 85: Konstrukce p řekladačů

85

Krok 6Připravené instrukce

jgt

Latenci vyhovuje čas 4 Instrukce však musí být

poslední

Vybrán čas 5

Příklad – scheduling

čas R MEM ALU W

0 mov

1 dec mov

2 mov dec

3 cmp mov dec

4 xor cmp mov

5 inc xor, jgt cmp

6 inc xor

7 inc

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r1

4

3

1

1

11

0

1

5

Page 86: Konstrukce p řekladačů

86

Čas 6Připravené instrukce

jgt

Příklad – scheduling

čas R MEM ALU W

0 mov

1 dec mov

2 mov dec

3 cmp mov dec

4 inc cmp mov

5 xor inc, jgt cmp

6 xor inc

7 xor

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r15

3

1

1

11

0

1

40

Page 87: Konstrukce p řekladačů

87

char chksum( char * p, int i)

{

char s = 0;

while ( i > 0 )

{

s ^= *p++;

--i;

}

return s;

}

Výsledný kód

mov r1,[rp]

dec ri

cmp ri,0

xor rs,r1

inc rp

jgt

Příklad – scheduling

čas R MEM ALU W

0 mov

1 dec mov

2 mov dec

3 cmp mov dec

4 xor cmp mov

5 inc xor, jgt cmp

6 inc xor

7 inc

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r14

3

5

1

11

0

1

5

Page 88: Konstrukce p řekladačů

88 Scheduling

Základní algoritmus: „List scheduling“V grafu závislostí s latencemi se pro každý uzel spočte

délka kritické, tj. nejdelší cesty ke konciV každém kroku se určí připravené instrukce a z nich se

vybere nejvhodnější Přednost mají instrukce s nejdelší kritickou cestou Mezi nimi se vybírá podle dalších heuristik

Při správné implementaci má tento postup složitost O(n2)Vylepšené algoritmy

Posun směrem k exhaustivnímu prohledávání všech možností

Branch-and-bound přístup: Zkouší se všechny možnosti v pořadí od nejnadějnější, nalezené list

schedulingem Beznadějné pokusy se včas zastaví porovnáváním odhadů

úspěšnosti výsledku pomocí kritických cest s doposud známým nejlepším řešením

Page 89: Konstrukce p řekladačů

89

Výsledný kód

mov r1,[rp]

dec ri

cmp ri,0

inc rp

xor rs,r1

jgt

Chování ve smyčce Za předpokladu správné

predikce skoku procesorem Výkon: 1/6 iterace/cyklus Využití jednotek:

• R: 5/6

• MEM: 3/6

• ALU: 5/12

• W: 5/6

Příklad – scheduling

čas R MEM ALU W

0 mov

1 dec mov

2 mov dec

3 cmp mov dec

4 inc cmp mov

5 xor inc, jgt cmp

6 mov xor inc

7 dec mov xor

8 mov dec

9 cmp mov dec

10 inc cmp mov

11 xor inc, jgt cmp

12 mov xor inc

13 dec mov xor

14 mov dec

15 cmp mov dec

Page 90: Konstrukce p řekladačů

90

Efekt kapacity procesoru

Stejné latence i res. tabulky

mov r1,[rp]

dec ri

inc rp

cmp ri,0

xor rs,r1

jgt

Výkon: 1/5 iterace/cyklus Využití jednotek:

• R: 5/10

• MEM: 3/5

• ALU: 5/10

• W: 5/10

Příklad – scheduling

čas R MEM ALU W

0 mov, dec

1 inc mov dec

2 cmp mov inc dec

3 mov cmp inc

4 xor jgt mov, cmp

5 mov, dec xor

6 inc mov dec xor

7 cmp mov inc dec

8 mov cmp inc

9 xor jgt mov, cmp

10 mov, dec xor

11 inc mov dec xor

12 cmp mov inc dec

13 mov cmp inc

14 xor jgt mov, cmp

R MEM ALU W

2 1 2 2

Page 91: Konstrukce p řekladačů

91

Závislosti uvnitř BB

Závislosti přes hranice BB(loop-carried dependences)

Příklad – software pipelining

z instrukce do instrukce čas

cmp ri,0 jgt 1

mov r1,[rp] xor rs,r1 4

dec ri cmp ri,c 2

mov r1,[rp] inc rp 0

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r1

4

2

1 0

2

2

2

1 0

z instrukce do instrukce čas

inc rp inc rp 2

inc rp mov r1,[rp] 2

dec ri dec ri 2

cmp ri,0 dec ri 0

xor rs,r1 xor rs,r1 2

xor rs,r1 mov r1,[rp] 0

jgt cmp ri,0 1

jgt mov r1,[rp] 1

1

0

2

Page 92: Konstrukce p řekladačů

92 Příklad – software pipelining

Jiná abstrakcelatence/iterace

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri

xor rs,r1

2/1

2/1

2/1

2/1 1/1

1/0

2/0

4/0

0/1

1/1

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri xor rs,r1

4

2

1 0

2

2

2

1 0

1

0

2

0/0

0/1

Page 93: Konstrukce p řekladačů

93 Příklad – software pipelining

čas R MEM ALU W

0 mov1, dec1

1 inc1 mov1 dec1

2 cmp1 mov1 inc1 dec1

3 dec2 mov1 cmp1, jgt1 inc1

4 xor1, mov2 dec2 mov1, cmp1

5 inc2, cmp2 mov2 xor1 dec2

6 dec3 mov2 inc2, cmp2 xor1

7 mov2 dec3, jgt2 inc2, cmp2

8 xor2, mov3 mov2, dec3

9 inc3, cmp3 mov3 xor2

10 dec4 mov3 inc3, cmp3 xor2

11 mov3 dec4, jgt3 inc3, cmp3

12 xor3, mov4 mov3, dec4

13 inc4, cmp4 mov4 xor3

14 dec5 mov4 inc4, cmp4 xor3

15 mov4 dec5, jgt4 inc4, cmp4

16 xor4, mov5 mov4, dec5

17 inc5, cmp5 mov5 xor4

18 dec6 mov5 inc5, cmp5 xor4

19 mov5 dec6, jgt5 inc5, cmp5

20 xor5 mov5, dec6

21 xor5

22 xor5

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri

xor rs,r1

2/1

2/1

2/1

2/1 1/1

1/0

2/0

4/0

0/1

1/1

0/0

0/1

Page 94: Konstrukce p řekladačů

94 Příklad – software pipelining

čas R MEM ALU W

0 mov1, dec1

1 inc1 mov1 dec1

2 cmp1 mov1 inc1 dec1

3 dec2 mov1 cmp1, jgt1 inc1

4 xor1, mov2 dec2 mov1, cmp1

5 inc2, cmp2 mov2 xor1 dec2

6 dec3 mov2 inc2, cmp2 xor1

7 mov2 dec3, jgt2 inc2, cmp2

8 xor2, mov3 mov2, dec3

9 inc3, cmp3 mov3 xor2

10 dec4 mov3 inc3, cmp3 xor2

11 mov3 dec4, jgt3 inc3, cmp3

12 xor3, mov4 mov3, dec4

13 inc4, cmp4 mov4 xor3

14 dec5 mov4 inc4, cmp4 xor3

15 mov4 dec5, jgt4 inc4, cmp4

16 xor4, mov5 mov4, dec5

17 inc5, cmp5 mov5 xor4

18 dec6 mov5 inc5, cmp5 xor4

19 mov5 dec6, jgt5 inc5, cmp5

20 xor5 mov5, dec6

21 xor5

22 xor5

Software pipelining“Unroll-and-compact”

Rozvrhuje se rozvinutý cyklus tak dlouho, dokud nevznikne opakující se vzorek

• Perioda opakování může odpovídat více iteracím

Problém: Není jasné, co je to kritická cesta

• Hledá se kritická smyčka

Page 95: Konstrukce p řekladačů

95 Software pipelining

„Modulo scheduling“ Analýzou grafu závislostí se

odhadne počet cyklů na iteraci

• Sčítají se ohodnocení hran ve smyčkách dvojicemi latence/iterace

• Rozhoduje nejvyšší podíl součtů na smyčce, např. 4/1

Hledá se rozvrh s daným počtem cyklů na iteraci

• Nemusí existovat – opakuje se pro větší počet

Složitější verze zvládají necelé počty cyklů na iteraci

• Pokud je v grafu závislostí kritická smyčka se součtem ohodnocení např. 5/2

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri

xor rs,r1

2/1

2/1

2/1

2/1 1/1

1/0

2/0

4/0

0/1

1/1

0/0

0/1

Page 96: Konstrukce p řekladačů

96 Modulo scheduling

Zvolená perioda M Rezervační tabulky jsou používány

modulo M: časy 0..(M-1) Instrukce jsou rozmisťovány do

dvojrozměrného prostoru čas/iterace

Rozvrh vyhovuje závislosti

pokud(TB-TA)-M*(IB-IA) ≥ L-M*D

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri

xor rs,r1

2/1

2/1

2/1

2/1 1/1

1/0

2/0

4/0

0/1

1/1

0/0

0/1

čas R MEM ALU W

T+0 xor[N], mov[N+1]

mov[N], dec[N+1]

T+1 inc[N+1], cmp[N+1]

mov[N+1] xor[N]

T+2 dec[N+2] mov[N+1] inc[N+1], cmp[N+1]

xor[N]

T+3 mov[N+1] dec[N+2], jgt[N+1]

inc[N+1], cmp[N+1]

1/11/1

2/2

3/1

0/1

0/0

BAL/D

TB/IBTA/IA

Page 97: Konstrukce p řekladačů

97 Modulo scheduling

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri

xor rs,r1

2/1

2/1

2/1

2/1 1/1

1/0

2/0

4/0

0/1

1/1

0/0

0/1

čas R MEM ALU W

0 xor2, mov3 mov2, dec3

1 inc3, cmp3 mov3 xor2

2 dec4 mov3 inc3, cmp3 xor2

3 mov3 dec4, jgt3 inc3, cmp3

4 xor3, mov4 mov3, dec4

5 inc4, cmp4 mov4 xor3

6 dec5 mov4 inc4, cmp4 xor3

7 mov4 dec5, jgt4 inc4, cmp4 1/11/1

2/2

3/1

0/1

0/0

Page 98: Konstrukce p řekladačů

98 Příklad – software pipelining

čas R MEM ALU W

0 mov1, dec1

1 inc1 mov1 dec1

2 cmp1 mov1 inc1 dec1

3 dec2 mov1 cmp1, jgt1 inc1

4 xor1, mov2 dec2 mov1, cmp1

5 inc2, cmp2 mov2 xor1 dec2

6 dec3 mov2 inc2, cmp2 xor1

7 mov2 dec3, jgt2 inc2, cmp2

8 xor2, mov3 mov2, dec3

9 inc3, cmp3 mov3 xor2

10 dec4 mov3 inc3, cmp3 xor2

11 mov3 dec4, jgt3 inc3, cmp3

12 xor3, mov4 mov3, dec4

13 inc4, cmp4 mov4 xor3

14 dec5 mov4 inc4, cmp4 xor3

15 mov4 dec5, jgt4 inc4, cmp4

16 xor4, mov5 mov4, dec5

17 inc5, cmp5 mov5 xor4

18 dec6 mov5 inc5, cmp5 xor4

19 mov5 dec6, jgt5 inc5, cmp5

20 xor5 mov5, dec6

21 xor5

22 xor5

Výsledek pro příklad Výkon: 1/4 iterace/cyklus

• Zlepšení o 25%

Využití jednotek:• R: 5/8

• MEM: 3/4

• ALU: 5/8

• W: 5/8

Poslední opakování vzorku provede zbytečně instrukci dec

• To není chyba

Vytvoření kódu z rozvrhuProlog-smyčka-epilogDokončení pro odbočky

Page 99: Konstrukce p řekladačů

99 Příklad – software pipelining

čas R MEM ALU W

0 mov1, dec1

1 inc1 mov1 dec1

2 cmp1 mov1 inc1 dec1

3 dec2 mov1 cmp1, jgt1 inc1

4 xor1, mov2 dec2 mov1, cmp1

5 inc2, cmp2 mov2 xor1 dec2

6 dec3 mov2 inc2, cmp2 xor1

7 mov2 dec3, jgt2 inc2, cmp2

8 xor2, mov3 mov2, dec3

9 inc3, cmp3 mov3 xor2

10 dec4 mov3 inc3, cmp3 xor2

11 mov3 dec4, jgt3 inc3, cmp3

12 xor3, mov4 mov3, dec4

13 inc4, cmp4 mov4 xor3

14 dec5 mov4 inc4, cmp4 xor3

15 mov4 dec5, jgt4 inc4, cmp4

16 xor4, mov5 mov4, dec5

17 inc5, cmp5 mov5 xor4

18 dec6 mov5 inc5, cmp5 xor4

19 mov5 dec6, jgt5 inc5, cmp5

20 xor5 mov5, dec6

21 xor5

22 xor5

mov r1,[rp]

dec ri

inc rp

cmp ri,0

jle l2

dec ri

l1:

xor rs,r1

mov r1,[rp]

inc rp

cmp ri,0

dec ri

jgt l1

l2:

xor rs,r1

Page 100: Konstrukce p řekladačů

100 Software pipelining

Duplikace proměnných (Variable expansion)

Duplikací proměnných lze odstranit některé antidependence

• Teoreticky všechny registrové, roste však počet použitých registrů i velikost kódu

Duplikace proměnných se provede duplikací kódu a vhodným přeznačením

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri

xor rs,r1

2/1

2/1

2/1

2/1 1/1

1/0

2/0

4/0

0/1

1/1

0/0

0/1

Page 101: Konstrukce p řekladačů

101 Variable expansion

Duplikace proměnných (Variable expansion)

Duplikací proměnných lze odstranit některé antidependence

• Teoreticky všechny registrové, roste však počet použitých registrů i velikost kódu

Duplikace proměnných se provede duplikací kódu a vhodným přeznačením

Příklad: Zdvojením proměnné r1 se kritický cyklus zkrátí z poměru 4/1 na 4/2

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri

xor rs,r1

2/1

2/1

2/1

2/11/1

1/0

2/0

4/0

0/2

1/1

0/0

0/1

cmp ri,0

jgt

mov r2,[rp]

inc rp

dec ri

xor rs,r2

2/1

2/1

2/1

2/1 1/1

1/0

2/0

4/0

0/2

1/1

0/0

0/1

Page 102: Konstrukce p řekladačů

102 Software pipelining

Duplikace proměnných (Variable expansion)

Duplikací proměnných lze odstranit některé antidependence

• Teoreticky všechny registrové, roste však počet použitých registrů i velikost kódu

Duplikace proměnných se provede duplikací kódu a vhodným přeznačením

• Duplikaci je možné provést až po schedulingu, který odhalí, která duplikace je užitečná

• Před schedulingem se odstraní antidependence odstranitelné duplikací

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri

xor rs,r1

2/1

2/1

2/1

2/1 1/1

1/0

2/0

4/0

1/1

Page 103: Konstrukce p řekladačů

103 Příklad – modulo scheduling s duplikací

čas R MEM ALU W

0 xor2, inc3 mov3 dec4, jgt3 mov2, cmp3

1 cmp4 mov3 xor2, inc3 dec4

2 mov4, dec5 mov3 cmp4 xor2, inc3

l1:

xor rs,r1 ; čas 0, iterace 2

inc rp ; čas 0, iterace 3

cmp ri,0 ; čas 1, iterace 4

mov r1,[rp] ; čas 2, iterace 4

dec ri ; čas 2, iterace 5

jle l2 ; čas 3, iterace 4

xor rs,r2 ; čas 3, iterace 3

inc rp ; čas 3, iterace 4

cmp ri,0 ; čas 4, iterace 5

mov r2,[rp] ; čas 5, iterace 5

dec ri ; čas 5, iterace 6

jgt l1 ; čas 6, iterace 5

l2:

cmp ri,0

jgt

mov r1,[rp]

inc rp

dec ri

xor rs,r1

2/1

2/1

2/1

2/1 1/1

1/0

2/0

4/0

1/1

0/0

0/1

0/11/2

2/3

0/1

2/2

0/0

0/2

Page 104: Konstrukce p řekladačů

104 Příklad – Intel compiler – x64

/*...*/

k = i >> 1;

j = 0;

do {

r8 = *p;

r9 = *(p+1);

s ^= r8;

s ^= r9;

p += 2;

j += 1;

} while ( j < k );

/* ... */

char chksum( char * p, int i)

{

char s = 0;

while ( i > 0 )

{

s ^= *p++;

--i;

}

return s;

}

..B1.4: movsbq (%rdi), %r8

movsbq 1(%rdi), %r9

xorl %r8d, %eax

xorl %r9d, %eax

addq $2, %rdi

addl $1, %ecx

cmpl %edx, %ecx

jb ..B1.4

Page 105: Konstrukce p řekladačů

Cray 1 105

Page 106: Konstrukce p řekladačů

Cray 1 106

Page 107: Konstrukce p řekladačů

Cray 1 107

Page 108: Konstrukce p řekladačů

Cray 1 108

Page 109: Konstrukce p řekladačů

109 Paralelizace

HardwareProč paralelizace?

Zrychlení stojí příliš mnoho energie•P = k f2

Místa je dost (108 tranzistorů/chip)

Jak paralelizovat?ve světě Intel (IA-32)

•Pipelining (1989: i486) – bez duplikace

•Superskalarita (1993: Pentium) – duplikace ALU, původní instrukce

•SIMD (1996: Pentium MMX) – duplikace ALU, nové instrukce

•Hyperthreading (1998: Xeon) – duplikace registrů

•Multi-core (2005: Core 2 Duo) – duplikace CPU

jinde•Vektorové instrukce (1974: Cray) – částečná duplikace

Page 110: Konstrukce p řekladačů

110 Paralelizace

Z pohledu softwareJemnozrnný paralelismus

ILP•Pipelining

•Superskalarita

SIMD•Mírně vektorové instrukce (2-8)

•Vektorové instrukce (64)

Hrubozrnný paralelismusSMP

•Hyperthreading

•Multi-core

•Multi-socket

NUMA•Multi-core a multi-socket (cc-NUMA)

•NUMA architektury

Cluster

Page 111: Konstrukce p řekladačů

111 Paralelizace

Z pohledu překladačeJemnozrnný paralelismus

ILP•Scheduling, software pipelining – změna pořadí instrukcí

Vektorizace - automatické použití SIMD instrukcí•Překladač vybírá speciální instrukce

•Překladač určuje pořadí provádění

Hrubozrnný paralelismusSMP – Multithreading

•Strip-Mining - Překladač dělí kód na nezávislé bloky

•Pořadí provádění je náhodné

Page 112: Konstrukce p řekladačů

112 Paralelizace

VektorizaceNízký stupeň (2-8)

Náhodné seskupovánía = b + c; d = e + f;

Vektorové seskupovánía[i] = b[i] + c[i]; a[i+1] = b[i+1] + c[i+1];

• Rozvíjení cyklů podle dostupného stupně vektorizace

Vysoký stupeň (64) Aplikovatelné na cykly s afinním chováním

• Numerické aplikace (FORTRAN 90)

• Nepoužitelné při nebezpečí aliasingu (objektové programování)

Řada afinních transformací cyklů• Loop Reversal

• Loop Skewing

Page 113: Konstrukce p řekladačů

Loop reversal

Výměna vzájemného zanoření cyklůPříklad: Učebnicový zápis násobení matic

for I := 1 to M do

for J := 1 to N do

for K := 1 to P do

C[I,J] := C[I,J]+A[I,K]*B[K,J]

Nelze paralelizovat - následující iterace závisí na předchozí

Po výměně zanoření cyklů K/Jfor I := 1 to M do

for K := 1 to P do

for J := 1 to N do

C[I,J] := C[I,J]+A[I,K]*B[K,J]

Překladač si musí být jistý zachováním semantiky• Je nutno vyloučit aliasing C=A resp. C=B

Tato úprava může zhoršit chování vzhledem k cache• Závisí na rozměrech P, N

V nenumerických aplikacích je užitečnost nejistá

113

Page 114: Konstrukce p řekladačů

Loop reversal

Původní průchod• Většina sousedů v průchodu je závislá

114

K

J

Page 115: Konstrukce p řekladačů

Loop reversal

Upravený průchod• Většina sousedů v průchodu je nezávislá

115

K

J

Page 116: Konstrukce p řekladačů

Loop skewing

Obecnější příklad

for J:=1 to N do

for K:=N-J to P do

A[J,K]:=A[J-1,K]+A[J,K-1]

116

K

J

Page 117: Konstrukce p řekladačů

Loop skewing

Obecnější příklad

for J:=1 to N do

for K:=N-J to P do

A[J,K]:=A[J-1,K]+A[J,K-1]

117

K

J

Page 118: Konstrukce p řekladačů

Loop skewing

Loop skewing

for J:=1 to N do

for K:=N-J to P do

A[J,K]:=A[J-1,K]+A[J,K-1]

Prostor iterací = prostor k-tic řídících proměnných• Hranice dány lineárními nerovnicemi (s konstantními koeficienty)

Detekce závislostí mezi iteracemi• Přístupy do paměti (indexy) určeny lineárními výrazy (s k. k.)

Směry (vektory) závislostí popisují zakázané směry iterací• Hledá se vektor ležící mimo konvexní obal vektorů závislostí

Výsledná smyčka pro jemnozrnnou paralelizaci• Vnější iterace: Vektor (vektory) v konvexním obalu závislostí• Vnitřní iterace: Vektor (vektory) mimo konvexní obal závislostí

Složitější případy: Prostor iterací se dělí na části řešené zvlášť• Zjednodušení mezí cyklů: dělení na části jednoduchých tvarů

118

Page 119: Konstrukce p řekladačů

Hrubozrnná paralelizace

Hrubozrnná paralelizace

Velká běhová režie• Vytváření vláken/úloh, plánování

Vyžaduje relativně velké na sobě nezávislé bloky Předvídatelně velké bloky: Počet bloků odpovídá počtu CPU Nepředvídatelně velké bloky: Počet bloků větší než počet CPU

• Bloky se přidělují na CPU dynamicky

Různé schopnosti běhového prostředí Vlákna bez vzájemné synchronizace

• Bloky na sobě nesmějí vůbec záviset

Pipeline parallelism, task parallelism• Plánovač respektuje vzájemné závislosti bloků

• Závislosti nesmějí být cyklické

119

Page 120: Konstrukce p řekladačů

Strip mining

Hledání zcela nezávislých bloků

120

K

J

Page 121: Konstrukce p řekladačů

Hrubozrnná paralelizace

Hrubozrnná paralelizace

Bloky k paralelizaci je třeba vybírat v horních patrech iterací Zajištění dostatečné velikosti bloků

Smyčku je vhodné upravit, aby vnější iterace nebyly závislé Stejné metody jako u jemnozrnné paralelizace, ale opačný cíl

Loop skewing pro hrubo- i jemnozrnnou paralelizaci Vnější iterace nezávislé (pro hrubozrnnou paralelizaci) Střední iterace závislé Vnitřní iterace nezávislé (pro jemnozrnnou paralelizaci)

Problém: Vrstev iterací je obvykle málo• Středních iterací musí být dost na pokrytí konvexního obalu závislostí

121

Page 122: Konstrukce p řekladačů

Hrubozrnná paralelizace

Problém: Vrstev iterací je obvykle málo

Řešení: BlockingProstor iterací se rozdělí na menší díly (bloky)

Tím vznikají další úrovně iterace

Iterace nad bloky se uspořádají pro hrubozrnný paralelismus

Vnější iterace řeší nezávislé skupiny bloků• Strip mining: Vlákna

Vnitřní iterace procházejí závislé bloky uvnitř skupin• Task parallelism: Tasky

Iterace uvnitř bloky se upraví pro jemnozrnný paralelismus Vnější iterace jsou závislé Vnitřní iterace jsou bez závislostí

• SIMD, ILP

122

Page 123: Konstrukce p řekladačů

Blocking

Vytvoření bloků

123

K

J

Page 124: Konstrukce p řekladačů

Blocking

Strip mining nad bloky

124

K

J

Page 125: Konstrukce p řekladačů

Blocking

Loop skewing uvnitř bloků

125

K

J

Page 126: Konstrukce p řekladačů

Blocking

Blocking Původní iterace rozděleny

na 2 patra• Vždy ekvivalentní

• Problémy se zbytky

Nové iterace promíchány• Pouze některé výměny

jsou možné

• Cílem je nezávislostv okrajových patrech

parallel for J1 := 0 to N-1 step SJ do

for K1 := 0 to P-1 step SK do

for K2 := 1 to SK do

parallel for J2 := 1 to SJ do

begin

J := J1 * SJ + J2;

K := K1 * SK + K2;

C[I,J] := C[I,J]+A[I,K]*B[K,J]

end

126

K

J

Page 127: Konstrukce p řekladačů

Blocking

Blocking Implementace vlákny

for J1 := 0 to N-1 step SJ do

create_thread( f, J1);

wait();

function f( J1)

begin

for K1 := 0 to P-1 step SK do

for K2 := 1 to SK do

parallel for J2 := 1 to SJ do

begin

J := J1 * SJ + J2;

K := K1 * SK + K2;

C[I,J] := C[I,J]+A[I,K]*B[K,J]

end

end

127

K

J

Page 128: Konstrukce p řekladačů

Blocking

Blocking Task parallelism

for J1 := 0 to N-1 step SJ do

for K1 := 0 to P-1 step SK do

begin

TN := new_task( f, J1, K1);

add_dep( TP, TN); TP := TN;

end;

run();

function f( J1, K1)

begin

for K2 := 1 to SK do

parallel for J2 := 1 to SJ do

begin

J := J1 * SJ + J2;

K := K1 * SK + K2;

C[I,J] := C[I,J]+A[I,K]*B[K,J]

end

end

128

K

J

Page 129: Konstrukce p řekladačů

Optimalizace pro cache

Podmínky dobrého využití cache Prostorová lokalita

• Jednotkou přístupu je cache line (typ. 64 B)

• Přístupy do sousedních míst mají být blízko, nejlépe najednou

• Zápisy také způsobují výpadky - antidependence se řeší také

Časová lokalita• Čím delší je doba mezi přístupy, tím větší je pravděpodobnost výpadku

• Přístupy k témuž paměťovému místu je výhodné v čase rozmístit nepravidelně

129

Page 130: Konstrukce p řekladačů

Další optimalizace

130

Page 131: Konstrukce p řekladačů

131 Architektura překladače

Detailní pohled akademika (pouze optimalizace)• Muchnick: Advanced Compiler Design and Implementation

Scalar replacement of array referencesData-cache optimizations

Procedure integrationTail-call optimizationScalar replacement of aggregatesSparse conditional constant propagationInterprocedural constant propagationProcedure specialization and cloningSparse conditional constant propagation

Global value numberingLocal and global copy propagationSparse conditional constant propagationDead-code eliminationLocal and global common-subexpression eliminationLoop-invariant code motionDead-code eliminationCode hoistingInduction-variable strength reductionLinear-function test replacementInduction-variable removalUnnecessary bounds-checking eliminationControl-flow optimizations

In-line expansionLeaf-routine optimizationShrink wrappingMachine idiomsTail mergingBranch optimizations and conditional movesDead-code eliminationSoftware pipelining, loop unrollingBasic-block and branch schedulingRegister allocationBasic-block and branch schedulingIntraprocedural I-cache optimizationInstruction prefetchingData prefetchingBranch prediction

Interprocedural register allocationAggregation of global referencesInterprocedural I-cache optimization

Constant foldingAlgebraic simplification and reassociation

Page 132: Konstrukce p řekladačů

132 Další optimalizace

Částečné vyhodnocení Část požadovaného výpočtu je vyhodnocována již překladačem

Výpočet konstantních výrazů Constant-expression evaluation (constant folding)

Výpočet podmíněně konstantních výrazů Sparse conditional constant propagation

Algebraické úpravy Využití algebraických identit ke zjednodušení kódu

Algebraické úpravy výrazůRedukce síly v cyklech

Strength reduction

Odstranění zbytečných kontrol mezí

Page 133: Konstrukce p řekladačů

133 Další optimalizace

Odstranění redundance Nahrazení opakovaných výpočtů uložením výsledku

Copy propagation Lokální/globální eliminace společných podvýrazů

Common-subexpression elimination Přesun invariantního kódu z cyklu

Loop-invariant code motion Partial-redundancy elimination

Lazy code motion

Odstranění neužitečného kódu Odstranění mrtvého kódu

Dead-code elimination Odstranění nedosažitelného kódu

Unreachable-code elimination Optimalizace skoků

Jump optimization

Page 134: Konstrukce p řekladačů

134 Částečné vyhodnocení

Výpočet (pod)výrazů obsahujících pouze konstanty

Constant-expression evaluation

Obvykle prováděn již front-endem

Určení proměnných s konstantním obsahem

Constant folding

Určení proměnných s podmíněně konstantním obsahem

Sparse conditional constant propagation

Upravuje control-flow!

a = b + (4 * 10);

c = 4 * 10;

d = c + 5;

e = f + (d * 2);

if ( g > h )

i = 1;

else

i = 0;

j = i + 1;

if ( j > 1 )

k = k + 1;

Page 135: Konstrukce p řekladačů

135 Částečné vyhodnocení

Výpočet (pod)výrazů obsahujících pouze konstanty

Constant-expression evaluation

Obvykle prováděn již front-endem

Určení proměnných s konstantním obsahem

Constant folding

Určení proměnných s podmíněně konstantním obsahem

Sparse conditional constant propagation

Upravuje control-flow!

Integrace procedur generuje nové příležitosti pro částečné vyhodnocení

void f( int i, bool f)

{

int j = i + 1;

if ( f )

g( j);

else

h( j);

}

f( k + 1, false);

Page 136: Konstrukce p řekladačů

136 Částečné vyhodnocení

a = b + 40;

c = 40;

d = 45;

e = f + 90;

if ( g > h )

{

i = 1;

j = 2;

k = k + 1;

}

else

{

i = 0;

j = 1;

}

a = b + (4 * 10);

c = 4 * 10;

d = c + 5;

e = f + (d * 2);

if ( g > h )

i = 1;

else

i = 0;

j = i + 1;

if ( j > 1 )

k = k + 1;

Page 137: Konstrukce p řekladačů

137 Algebraické úpravy

Algebraické úpravy výrazů Většinou v souvislosti s

přítomností konstant Důležité pro ukazatelovou

aritmetiku (přístup k polím) Úprava do kanonického

tvaru

Redukce síly v cyklech Důležité pro přístup k polím

Odstranění zbytečných kontrol mezí

Machine idioms Instrukce provádějící speciální

kombinace nebo varianty operací

a = ((b * 3) + 7) * 5

a = b * 15 + 35

for ( i = 1; i < 10; ++i )

a[ 4 * i] = 0;

for ( j = 4; j < 40; j += 40 )

a[ j] = 0;

int b[ 10];

for ( i = 0; i < 10; ++i )

b[ i] = 0;

Page 138: Konstrukce p řekladačů

138 Algebraické úpravy

Převedení control-flow na algebraické operace

Conditional move Ušetří podmíněné skoky Může přidat zbytečné operace

Užitečnost obtížně odhadnutelná

Cena podmíněných skoků závisí na úspěšnosti predikce

Překladač úspěšnost nedokáže odhadnout

Profilem řízené optimalizace

if ( a > b )

c = d + e;

CMP t,a,b

ADD u,d,e

CMOV t,c,u

Page 139: Konstrukce p řekladačů

139 Odstranění redundance

Copy propagationLokální/globální eliminace

společných podvýrazůPřesun invariantního kódu

z cyklu Častý výskyt u přístupu k

polím

Partial-redundancy elimination

Lazy code motion

Integrace procedur generuje nové redundance

b = a;

c = b; // c = a;

c = a + b;

d = a + b; // d = c;

for ( i = 0; i < 10; ++i)

a[ i] = k + l;

if ( a < b )

c = d + e;

f = d + e;

Page 140: Konstrukce p řekladačů

140 Odstranění neužitečného kódu

Odstranění mrtvého kódu Kód, jehož efekt nebude

využit• Přiřazení do proměnných,

které již nebudou čteny

Odstranění nedosažitelného kódu

Kód, ke kterému nevede cesta

Optimalizace skoků Skoky na skoky apod.

Řeší především chyby vyprodukované předchozími fázemi

Aplikuje se opakovaně

a = b + 40;

c = 40;

d = 45;

e = f + 90;

if ( g > h )

{

i = 1;

j = 2;

k = k + 1;

}

else

{

i = 0;

j = 1;

}

Page 141: Konstrukce p řekladačů

141 Přesouvání kódu

Code hoisting Provedení operace dříve,

než předepisoval původní program

Omezeno závislostmi „very busy“ expression =

operace, která bude provedena v každém pokračování

Algoritmus: Lazy code motion

Užitečnost úpravy je nejistá Paralelismus Omezený počet registrů

if ( g > h )

{

for ( i = 1; i < k; ++ i)

{ a[ i] = x + y;

}

u = x + y;

}

else

{

z = x + y;

}

Page 142: Konstrukce p řekladačů

142 Optimalizace režie volání

Integrace procedur a.k.a inline-expansion

Listové procedury Nevolají žádné další Není třeba kompletní prolog

a epilog procedury Užitečné zejména v

přítomnosti výjimek

Shrink wrapping Přesouvání prologu a

epilogu Ve větvích, které nevolají

další procedury, se prolog a epilog anihilují

• Tail merging• Ztotožnění identických konců

procedur• Poslední BB často

obsahuje pouze epilog a je tudíž shodný

• Šetří velikost kódu• Zlepšuje využití I-cache

Page 143: Konstrukce p řekladačů

143 Interprocedurální úpravy

Specializace procedur Procedury se naklonují Jednotlivé klony se

přizpůsobují okolnostem, které panují při jejich volání

Speciální tvary argumentů

Konstantní argumenty Aliasing

Interprocedurální alokace registrů

Volací konvence se upravuje podle místních podmínek

Efekt je obdobný jako u integrace procedur

Specializace vede k menší expanzi kódu

Specializace se obtížněji řídí

Integrace odstraňuje režii volání

Integrace umožňuje další optimalizace

Page 144: Konstrukce p řekladačů

144 Nápověda pro procesor

Intraprocedural I-cache optimization

Využití atomicity cache-line

Serializace BB tak, aby chování CPU vedlo k minimálnímu počtu výpadků I-cache

Instruction prefetchingData prefetching

Využití speciálních instrukcí pro nedestruktivní čtení

Branch predictionGenerování nápovědy

pro branch prediction

Page 145: Konstrukce p řekladačů

145 Architektura překladače

Detailní pohled akademika (pouze optimalizace)• Muchnick: Advanced Compiler Design and Implementation

Scalar replacement of array referencesData-cache optimizations

Procedure integrationTail-call optimizationScalar replacement of aggregatesSparse conditional constant propagationInterprocedural constant propagationProcedure specialization and cloningSparse conditional constant propagation

Global value numberingLocal and global copy propagationSparse conditional constant propagationDead-code eliminationLocal and global common-subexpression eliminationLoop-invariant code motionDead-code eliminationCode hoistingInduction-variable strength reductionLinear-function test replacementInduction-variable removalUnnecessary bounds-checking eliminationControl-flow optimizations

In-line expansionLeaf-routine optimizationShrink wrappingMachine idiomsTail mergingBranch optimizations and conditional movesDead-code eliminationSoftware pipelining, loop unrollingBasic-block and branch schedulingRegister allocationBasic-block and branch schedulingIntraprocedural I-cache optimizationInstruction prefetchingData prefetchingBranch prediction

Interprocedural register allocationAggregation of global referencesInterprocedural I-cache optimization

Constant foldingAlgebraic simplification and reassociation

Page 146: Konstrukce p řekladačů

146 Architektura překladače

Realita GNU

CompilerCollectionInternals

Remove useless statements Mudflap declaration registration Lower control flow Lower exception handling control flow Build the control flow graph Find all referenced variables

RTL generation Generate exception handling landing pads Cleanup control flow graph Common subexpression elimination Global common subexpression elimination. Loop optimization Jump bypassing If conversion Web construction Life analysis Instruction combination Register movement Optimize mode switching Modulo scheduling Instruction scheduling Register class preferencingLocal register allocationGlobal register allocationReloadingBasic block reordering Variable tracking Delayed branch scheduling Branch shortening Register-to-stack conversion Final Debugging information output

Enter static single assignment form Warn for uninitialized variables Dead code elimination Dominator optimizations Redundant phi elimination Forward propagation of single-use variables Copy renaming PHI node optimizations May-alias optimization Profiling Lower complex arithmetic Scalar replacement of aggregates Dead store elimination

Tail recursion elimination Forward store motion Partial redundancy elimination Loop invariant motionCanonical induction variable creationInduction variable optimizationsLoop unswitchingVectorizationTree level if-conversion for vectorizer Conditional constant propagation Folding builtin functions Split critical edges Partial redundancy elimination Control dependence dead code elimination Tail call elimination Warn for function return without value Mudflap statement annotation Leave static single assignment form