Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
14
Добавлен:
02.05.2014
Размер:
10.51 Кб
Скачать
unit TrdOpt;

interface

{ Модуль реализующий два алгоритма оптимизации:
- оптимизация путём свёртки объектного кода;
- оптимизация за счёт исключения лишних операций. }
uses Classes, TblElem, LexElem, TrdType, Triads;

type
{ Информационная структура для таблицы идентификаторов,
предназначенная для алгоритма свёртки объектного кода }
TConstInfo = class(TAddVarInfo)
protected
{ Поле для записи значения переменной }
iConst: longint;
{ Конструктор для создания структуры }
constructor Create(iInfo: longint);
public
{ Функции для чтения и записи информации }
function GetInfo(iIdx: integer): longint; override;
procedure SetInfo(iIdx: integer; iInfo: longint);
override;
end;

{ Информационная структура для таблицы идентификаторов,
предназначенная для алгоритма исключения лишних операций }
TDepInfo = class(TAddVarInfo)
protected
{ Поле для записи числа зависимости переменной }
iDep: longint;
{ Конструктор для создания структуры }
constructor Create(iInfo: longint);
public
{ Функции для чтения и записи информации }
function GetInfo(iIdx: integer): longint; override;
procedure SetInfo(iIdx: integer; iInfo: longint);
override;
end;

{ Процедура оптимизации методом свёртки объектного кода }
procedure OptimizeConst(listTriad: TTriadList);
{ Процедура оптимизации методом
исключения лишних операций }
procedure OptimizeSame(listTriad: TTriadList);

implementation

uses SysUtils, FncTree, LexType, TrdCalc;

constructor TConstInfo.Create(iInfo: longint);
{ Конструктор создания информационной структуры
для свёртки объектного кода }
begin
inherited Create;
iConst := iInfo;
end;

procedure TConstInfo.SetInfo(iIdx: integer;
iInfo: longint);
{ Функция записи инфоримации }
begin
iConst := iInfo;
end;

function TConstInfo.GetInfo(iIdx: integer): longint;
{ Функция чтения инфоримации }
begin
Result := iConst;
end;

function TestOperConst(Op: TOperand; listTriad: TTriadList;
var iConst: integer): Boolean;
{ Функция проверки того, что операнд является константой
и получения его значения в переменную iConst }
var pInfo: TConstInfo;
begin
Result := False;
{ Выборка по типу операнда }
case Op.OpType of
OP_CONST:
{ Если оператор - константа, то всё просто... }
begin
iConst := Op.ConstVal;
Result := True;
end;
OP_VAR:
{ Если оператор - переменная }
begin
{ тогда проверяем наличие у нее
информационной структуры }
pInfo := TConstInfo(Op.VarLink.Info);
if pInfo <> nil then
begin
{ и если такая структура есть,
берём ее значение }
iConst := pInfo[0];
Result := True;
end;
end;
OP_LINK:
{ Если оператор - ссылка на триаду }
begin
{ то он является константой,
если триада имеет тип "CONST" }
if listTriad[Op.TriadNum].TrdType = TRD_CONST
then
begin
iConst := listTriad[Op.TriadNum][1].ConstVal;
Result := True;
end;
end;
end{case};
end;

procedure OptimizeConst(listTriad: TTriadList);
{ Процедура оптимизации методом свёртки объектного кода }
var
i,j,iCnt,iOp1,iOp2: integer;
Ops: TOpArray;
Trd: TTriad;
begin
{ Очищаем информационные структуры
таблицы идентификаторов }
ClearTreeInfo;
{ Заполняем операнды для триады типа "CONST" }
Ops[1].OpType := OP_CONST;
Ops[2].OpType := OP_CONST;
Ops[2].ConstVal := 0;
iCnt := listTriad.Count-1;
{ Для всех триад списка выполняем алгоритм }
for i:=0 to iCnt do
begin
Trd := listTriad[i];
if Trd.TrdType in TriadLineSet then
begin
{ Если любой операнд линейной триады ссылается
на триаду типа "CONST",
то берём и запоминаем её значение }
for j:=1 to 2 do
if (Trd[j].OpType = OP_LINK)
and (listTriad[Trd.Links[j]].TrdType = TRD_CONST)
then
begin
Trd.OpTypes[j] := OP_CONST;
Trd.Values[j] :=
listTriad[Trd.Links[j]][1].ConstVal;
end;
end
else
if Trd.TrdType = TRD_IF then
begin
{ Если первый операнд условной триады ссылается
на триаду типа "CONST",
то берём и запоминаем её значение }
if (Trd[1].OpType = OP_LINK)
and (listTriad[Trd.Links[1]].TrdType = TRD_CONST)
then
begin
Trd.OpTypes[1] := OP_CONST;
Trd.Values[1] :=
listTriad[Trd.Links[1]][1].ConstVal;
end;
end
else
if Trd.TrdType = TRD_ASSIGN then
begin
{ Если второй операнд триады присвоения
ссылается на триаду типа "CONST",
то берём и запоминаем её значение }
if (Trd[2].OpType = OP_LINK)
and (listTriad[Trd.Links[2]].TrdType = TRD_CONST)
then
begin
Trd.OpTypes[2] := OP_CONST;
Trd.Values[2] :=
listTriad[Trd.Links[2]][1].ConstVal;
end;
end;
{ Если триада помечена ссылкой, то линейный участок
кода закончен - опять очищаем информационные
структуры таблицы идентификаторов }
if Trd.IsLinked then ClearTreeInfo;
{ Если триада имеет тип "присвоение" }
if Trd.TrdType = TRD_ASSIGN then
begin
{ И если её второй операнд - константа }
if TestOperConst(Trd[2],listTriad,iOp2) then
{ запоминаем его значение в информационной
структуре переменной }
Trd[1].VarLink.Info := TConstInfo.Create(iOp2);
end
else
{ Если триада - одна из линейных операций }
if Trd.TrdType in TriadLineSet then
begin
{ И если оба её операнда - константы }
if TestOperConst(Trd[1],listTriad,iOp1)
and TestOperConst(Trd[2],listTriad,iOp2) then
begin
{ тогда вычисляем значение операции }
Ops[1].ConstVal :=
CalcTriad(Trd.TrdType,iOp1,iOp2);
{ запоминаем его в триаде типа "CONST",
которую записываем в список
вместо прежней триады }
listTriad.Items[i] := TTriad.Create(TRD_CONST,Ops);
{ Если на прежнюю триаду была ссылка,
сохраняем её }
listTriad[i].IsLinked := Trd.IsLinked;
{ Уничтожаем прежнюю триаду }
Trd.Free;
end;
end;
end;
end;

constructor TDepInfo.Create(iInfo: longint);
{ Конструктор создания информационной структуры
для чисел зависимости }
begin
inherited Create;
iDep := iInfo;
end;

procedure TDepInfo.SetInfo(iIdx: integer; iInfo: longint);
{ Функция записи числа зависимости }
begin
iDep := iInfo;
end;

function TDepInfo.GetInfo(iIdx: integer): longint;
{ Функция чтения числа зависимости }
begin
Result := iDep;
end;

function CalcDepOp(listTriad: TTriadList;
Op: TOperand): longint;
{ Функция вычисления числа зависимости
для операнда триады }
begin
Result := 0;
{ Выборка по типу операнда }
case Op.OpType of
OP_VAR:
{ Если это переменная - смотрим ее информационную
структуру, и если такая структура есть,
то берем оттуда число зависимости }
if Op.VarLink.Info <> nil then Result :=
Op.VarLink.Info.Info[0];
OP_LINK:
{ Если это ссылка на триаду,
то берем число зависимости триады }
Result := listTriad[Op.TriadNum].Info;
end{case};
end;

function CalcDep(listTriad: TTriadList;
Trd: TTriad): longint;
{ Функция вычисления числа зависимости триады }
var iDepTmp: longint;
begin
Result := CalcDepOp(listTriad,Trd[1]);
iDepTmp := CalcDepOp(listTriad,Trd[2]);
{ Число зависимости триады есть на единицу большее,
чем максимальное из чисел зависимости её операндов }
if iDepTmp > Result then Result := iDepTmp+1
else Inc(Result);
Trd.Info := Result;
end;

procedure OptimizeSame(listTriad: TTriadList);
{ Процедура оптимизации методом исключения
лишних операций }
var
i,j,iStart,iCnt,iNum: integer;
Ops: TOpArray;
Trd: TTriad;
begin
{ Ставим начало линейного участка равным
началу списка триад }
iStart := 0;
{ Очищаем информационные структуры
таблицы идентификаторов }
ClearTreeInfo;
iCnt := listTriad.Count-1;
{ Заполняем операнды для триады типа "SAME" }
Ops[1].OpType := OP_LINK;
Ops[2].OpType := OP_CONST;
Ops[2].ConstVal := 0;
{ Для всех триад списка выполняем алгоритм }
for i:=0 to iCnt do
begin
Trd := listTriad[i];
{ Если триада помечена ссылкой, то линейный участок
кода закончен - опять очищаем информационные
структуры таблицы идентификаторов,
и запоминаем начало нового линейного участка }
if Trd.IsLinked then
begin
ClearTreeInfo;
iStart := i;
end;
{ Если любой операнд триады ссылается на триаду
типа "SAME", то переставляем ссылку на предыдущую,
совпадающую с ней триаду }
for j:=1 to 2 do
if Trd[j].OpType = OP_LINK then
begin
iNum := Trd[j].TriadNum;
if listTriad[iNum].TrdType = TRD_SAME then
Trd.Links[j] := listTriad[iNum].Links[1];
end;
{ Если триада типа "присвоение",
то запоминаем число зависимости переменной }
if Trd.TrdType = TRD_ASSIGN then
begin
Trd[1].VarLink.Info := TDepInfo.Create(i+1);
end
else
{ Если триада - одна из линейных операций }
if Trd.TrdType in TriadLineSet then
begin
{ Вычисляем число зависимости триады }
CalcDep(listTriad,Trd);
{ На всем линейном участке ищем совпадающую с ней
триаду с таким же числом зависимости }
for j:=iStart to i-1 do
begin
if Trd.IsEqual(listTriad[j])
and (Trd.Info = listTriad[j].Info) then
begin
{ Если такая триада найдена, запоминаем
ссылку на нее }
Ops[1].TriadNum := j;
{ запоминаем её в триаде типа "SAME", которую
записываем в список вместо прежней триады }
listTriad.Items[i] :=
TTriad.Create(TRD_SAME,Ops);
{ Если на прежнюю триаду была ссылка,
сохраняем её }
listTriad[i].IsLinked := Trd.IsLinked;
{ Уничтожаем прежнюю триаду }
Trd.Free;
{ Прерываем поиск }
Break;
end;
end;
end{if};
end{for};
end;

end.
Соседние файлы в папке Common