Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
15
Добавлен:
02.05.2014
Размер:
11 Кб
Скачать
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