Избор инструкција (1/2) Машинска инструкција се може приказати као део стабла међукода, који се назива шаблон стабла (енгл. tree pattern). Избор инструкција је проблем поплочавања стабла међукода минималним скупом шаблона стабла. Најбоље поплочавање стабла међукода доводи до низа инструкција са најмањим трошком. 1
Избор инструкција (2/2) Тип трошка описује жељени критеријум оптималности. Идеализовано посматрано то може бити број инструкција, ако се код оптимизује по величини, или потребно време процесора ако се код оптимизује по брзини извршења. У стварности, инструкције се не могу посматрати изоловано пошто између њих постоји интеракција, нпр. проточна обрада. 2
Динамичко програмирање Проблем тражења најјефтинијег поплочавања стабла решава се применом динамичког програмирања Технике за проналажење оптималног решења проблема тражењем оптималних решења потпроблема, односно подстабла 3
Поплочавање стабла применом Динамичког програмирања Алгоритам динамичког програмирања додељује трошак сваком чвору стабла. Трошак посматраног чвора је дефинисан као збир трошкова појединачних инструкција из најбољег низа инструкција које поплочавају подстабло чији корен је посматрани чвор. Овај алгоритам ради од доле ка горе, тј. од листова ка корену. 4
Алгоритам поплочавања За сваки шаблон t, трошка c, који се може употребити у чвору n, постоји нула или више подстабала s i. Цена c i сваког подстабла је већ позната (иде се од листова), тако да је трошак подстабла за избор шаблона t просто c+σc i. Од свих шаблона t i који се могу употребити у чвору n бира се шаблон са најмањим трошком. 5
Емитовање инструкција Након што се одреди трошак корена, започиње фаза емитовања инструкција која се обавља тако што се за сваки чвор n најпре емитују инструкције листова изабраног шаблона, а онда се емитује и инструкција која одговара изабраном шаблону. 6
IBURG Писање модула за избор инструкција је сложен задатак, који укључује моделирање одредишног процесора и реализацију алгоритма динамичког програмирања. Данас се уместо ручног писања користе генератори код генератора. За MASx процесор коришћен је генератор под називом IBURG. 7
IBURG улаз-излаз Улаз: датотека InstructionSelection.brg низ правила, са по три елемента: опис шаблона, придружен трошак и семантичка акција. Излаз: датотека Selection.cpp Це/Це++ код који реализује динамичко програмирање користећи дате шаблоне 8
IBURG спецификација (1/4) Секције: Конфигурациона секција, између '%{ и %} Садржај се преписује у Selection.h Дефинише макрое за спрегу са другим модулима компајлера; могућ је рад над различитим IR у форми стабла Дефиниције симбола, сви нетерминали и терминали Декларације шаблона, између %% и %% Reduce функција, иза друге ознаке %% 9
IBURG спецификација (2/4) Конфигурациона секција Макрои LEFT_CHILD, RIGHT_CHILD: приступ чворовима потомцима у стаблу међукода Макро OP_LABEL: приступ оператору одређеног чвора Макро STATE_LABEL: Приступ променљивој која садржи стање чвора Макро PANIC: Користи се када је откривена нека грешка 10
IBURG спецификација (3/4) Декларације шаблона Формат: naziv: opis opis има формат: definicija = identifikacija (cena) definicija користи нетерминалне и терминалне Сваком шаблону додељена: Јединствена идентификација Омогућава повезивање одређеног шаблона са одговарајућом семантичком акцијом Цена Омогућава да се, у ситуацијама када постоји више алтернатива за прекривање стабла међукода, пронађе субоптимално решење 11
IBURG спецификација (4/4) Функција Reduce Reduce на основу изабраног оптималног прекривања међукода извршава одговарајуће семантичке акције Извршавањем ових акција обично се генерише листа инструкција, било у виду: записа у одговарајућу датотеку или у облику меморијске структуре погодне за рад каснијих фаза компајлера 12
Пример IBURG спецификације (1/5) Конфигурациона секција %{ #include <stdio.h> #include <assert.h> #include <stdlib.h> #define STATE_TYPE int* typedef IRNode* NODEPTR_TYPE; #define OP_LABEL(p) ((p)->getnodeoperator()) #define LEFT_CHILD(p) ((p)->getleftnode()) #define RIGHT_CHILD(p) ((p)->getrightnode()) #define STATE_LABEL(p) ((p)->pstatelabel) #define PANIC printf %} 13
Пример IBURG спецификације (2/5) Декларације симбола и шаблона %start register %term PLUS_NO=1 SCONST_NO=107 MOVE_NO=115 TEMPD_NO=112 SLIST_NO=121EMPTY_NO=123 %% statement: SLIST_NO(MOVE_NO(TEMPD_NO(EMPTY_NO),register),statement) =31 (1); register: PLUS_NO(register,small_constant_op) = 101 (1); small_constant_op: SCONST_NO = 305 (0); %% 14
Пример IBURG спецификације (3/5) Функција Reduce за MASx компајлер (1/3) Даје значења шаблонима генерисањем инстанци класе CInstruction Ови објекти се уланчавају у листу инструкција Инструкције су праве али недовршене У њима се користе привремене променљиве уместо правих регистара Додела конкретних ресурса могућа тек након анализе животног века променљивих (наредна фаза компајлера) Не респектује се структура проточне обраде Након доделе ресурса мора обавити уметање NOP инструкција на местима где је то потребно (дистанцер) 15
Пример IBURG спецификације (4/5) Функција Reduce за MASx компајлер (2/3) CAsmOperand* InstructionSelector::Reduce(NODEPTR_TYPE p, int nonterm) { burm_kids(p, rulenumber, kids); switch(rulenumber) {... case 305:{ if(((const*)p)->getconstkind()==int_c) return new CImmediateOperand( new CValue(((Const*)p)->GetInteger())); else return new CImmediateOperand( new CValue(((Const*)p)->GetFloat())); }... } 16
Пример IBURG спецификације (3/5) Функција Reduce за MASx компајлер (1/3) case 101:{ CAsmOperand*src1,*src2,*dst,*op; instr = new CInstruction(ALU_GROUP_WITH_..._D1_INPUT_OC); instr->setcline(extractlineno((irnode*)p)); src1 = Reduce(kids[0], nts[0]); src2 = Reduce(kids[1], nts[1]); dst = new CAccOperand(((Expr*)p)->GetDestTemp()->GetName()); op = new CALUOperator(PLUS_ALU); instr->addsource(src1); instr->addsource(src2); instr->adddestination(dst); instr->addaditional(op); pinstrlst->push_back(instr); return dst; }... 17
Фаза побољшања генерисаног кода Прва техника побољшања кода се заснива на тражењу могућност примене сложенијих облика MAC машинске инструкције (CMAC, MAC, MACN, NMAC, NMACN). Друга техника побољшања генерисаног кода се односи на тражење могућности за коришћење адресних регистара. Трећа техника је избацивање сувишних машинских инструкција. 18
Примена сложених MAC У ту сврху тражи се комбинација једноставне MUL и ALU инструкције (не морају бити суседне, али MUL мора претходити ALU инструкцији), у којој се резултат множења два операнда из прве инструкције акумулира другом инструкцијом. Кад се таква комбинација пронађе, прва инструкција се замењује сложенијом MAC инструкцијом. 19
Коришћење адресних регистара Након доделе адресног регистра показивачу из полазног програма, најпре се анализирају све машинске инструкције које користе показивач ради препознавања могућности примене адресног режима самоувећања (auto increment), или самоумањења (auto decrement), адресног регистра. 20
Избацивање сувишних машинских инструкција Метода DeadCodeElimination уклања инструкције из ALU и MAC групе, уколико резултат инструкције не користи ни једна друга инструкција до краја посматраног блока. Метода RemoveUnnecessaryVarLoads уклања дефиниције променљиве која је изгубила важност новом дефиницијом (енгл. overridden). 21