Advertisement
Guest User

Untitled

a guest
Jan 2nd, 2012
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 7.30 KB | None | 0 0
  1. unit optremovereload;
  2.  
  3. {$i fpcdefs.inc}
  4.  
  5. {$DEFINE DEBUG}
  6. //{$DEFINE DEBUGVERBOSE}
  7. {$DEFINE DEBUGPRINTREMOVED}
  8.  
  9. interface
  10. uses
  11.   aasmtai,
  12.   aasmdata;
  13.  
  14. function RemoveReload(asml: TAsmList; first, last: tai; pass: longint): boolean;
  15.  
  16. implementation
  17. uses
  18.   {$IFDEF DEBUG}
  19.   sysutils,
  20.   globtype,
  21.   fmodule,
  22.   {$ENDIF}
  23.   aasmcpu,
  24.   cpubase,
  25.   cgbase,
  26.   cgutils,
  27.   daopt386;
  28.  
  29. var
  30.   List: array of taicpu;
  31.   ListCount: Integer;
  32.  
  33. {$IFDEF DEBUG}
  34. function DebugRegName(AReg: TSuperRegister): String;
  35. begin
  36.   case AReg of
  37.     RS_EAX: Result := 'EAX';
  38.     RS_EBX: Result := 'EBX';
  39.     RS_ECX: Result := 'ECX';
  40.     RS_EDX: Result := 'EDX';
  41.     RS_ESI: Result := 'ESI';
  42.     RS_EDI: Result := 'EDI';
  43.     RS_ESP: Result := 'ESP';
  44.     RS_EBP: Result := 'EBP';
  45.     else Result := 'reg';
  46.   end;
  47. end;
  48.  
  49. { return human readable source position for this instruction }
  50. function DebugSourcePosInfo(p: taicpu): String;
  51. var
  52.   fi : tfileposinfo;
  53. begin
  54.   fi := p.fileinfo;
  55.   Result := get_source_file(fi.moduleindex, fi.fileindex).name^ + ' ';
  56.   Result := Result + IntToStr(fi.line) + ',' + IntToStr(fi.column);
  57. end;
  58.  
  59. { return human readable string representation (incomplete) for instruction }
  60. function DebugInstString(p: taicpu): String;
  61. var
  62.   I : Integer;
  63.   op: toper;
  64.   ref: treference;
  65. begin
  66.   Result := std_op2str[p.opcode] + ' ';
  67.   for I := 0 to p.ops-1 do begin
  68.     op := p.oper[i]^;
  69.     if op.typ = top_reg then begin
  70.       Result := Result + std_regname(op.reg) + ' ';
  71.     end
  72.     else if op.typ = top_const then begin
  73.       Result := Result + IntToHex(op.val, 8) + ' ';
  74.     end
  75.     else if op.typ = top_ref then begin
  76.       Result := Result + '[';
  77.       ref := op.ref^;
  78.       if ref.offset < 0 then begin
  79.         Result := Result + '-' + IntToHex(-ref.offset, 8);
  80.       end
  81.       else begin
  82.         Result := Result + IntToHex(ref.offset, 8);
  83.       end;
  84.       if ref.base <> NR_NO then
  85.         Result := Result + '+' + std_regname(ref.base);
  86.  
  87.       if ref.scalefactor > 0 then begin
  88.         Result := Result + '+' + IntToHex(ref.scalefactor, 1) + '*';
  89.         Result := Result + std_regname(ref.index) + ' ';
  90.       end;
  91.       Result := Result + '] ';
  92.     end
  93.     else begin
  94.       Result := Result + '??? ';
  95.     end;
  96.   end;
  97. end;
  98. {$ENDIF}
  99.  
  100. {we only care about one kind of instruction.
  101.  currently this is only: mov reg, [ofs+reg] }
  102. function IsEligible(p: taicpu): Boolean;
  103. var
  104.   opin, opout: toper;
  105.   regout: TSuperRegister;
  106. begin
  107.   Result := False;
  108.   // mov
  109.   if (p.opcode = A_MOV) and (p.ops = 2) then begin
  110.     opin := p.oper[0]^;
  111.     opout := p.oper[1]^;
  112.  
  113.     // only mem to register are of interest to us
  114.     if opout.typ = top_reg then begin
  115.       if opin.typ = top_ref then begin
  116.         Result := True;
  117.  
  118.         if opin.ref^.base = NR_NO then
  119.           exit(False);
  120.  
  121.         if opin.ref^.index <> NR_NO then
  122.           exit(False);
  123.  
  124.         // instructions like mov edx, [something+edx]
  125.         // cannot be repeated, they invalidate themselves.
  126.         regout := getsupreg(opout.reg);
  127.         if getsupreg(opin.ref^.base) = regout then
  128.           exit(False);
  129.         if getsupreg(opin.ref^.index) = regout then
  130.           exit(False);
  131.  
  132.       end;
  133.     end;
  134.   end;
  135. end;
  136.  
  137. function IsIdentical(p1, p2: taicpu): Boolean;
  138. var
  139.   I : Integer;
  140. begin
  141.   Result := True;
  142.   if p1.opcode <> p2.opcode then exit(False);
  143.   if p1.ops <> p2.ops then exit(False);
  144.   for I := 0 to p1.ops-1 do
  145.     if not OpsEqual(p1.oper[I]^, p2.oper[I]^) then exit(False);
  146. end;
  147.  
  148. function IsInvalidating(pnew, pold: taicpu): Boolean;
  149. var
  150.   R : TSuperRegister;
  151.   opnew_out, opold_in, opold_out: toper;
  152.   I : Integer;
  153. begin
  154.   Result := False;
  155.  
  156.   // in this function we rely on a certain structure of pold
  157.   // because we know it has passed the IsEligible() function,
  158.   // it can only ever be a certain kind of mov instruction.
  159.  
  160.   opold_in := pold.oper[0]^;  // is always top_ref
  161.   opold_out := pold.oper[1]^; // is always top_reg
  162.  
  163.   // but pnew can be anything
  164.   for I := 0 to pnew.ops-1 do begin
  165.     if pnew.spilling_get_operation_type(I) in [operand_write, operand_readwrite] then
  166.     begin
  167.       opnew_out := pnew.oper[I]^;
  168.  
  169.       if opnew_out.typ = top_reg then begin
  170.         // if it writes to any of the 2 old registers then it is invalidating
  171.         if  getsupreg(opnew_out.reg) = getsupreg(opold_out.reg) then
  172.           exit(True);
  173.         if  getsupreg(opnew_out.reg) = getsupreg(opold_in.ref^.base) then
  174.           exit(True);
  175.       end;
  176.  
  177.       if opnew_out.typ = top_ref then begin
  178.         if opnew_out.ref^.offset = opold_in.ref^.offset then
  179.           // writing to something with the same offset is suspicious,
  180.           // better risk a false positive, better save than sorry
  181.           exit(True);
  182.       end;
  183.     end;
  184.   end;
  185. end;
  186.  
  187. procedure ListAdd(p: taicpu);
  188. begin
  189.   if Length(List) = ListCount then
  190.     SetLength(List, Length(List)*2 + 1);
  191.   List[ListCount] := p;
  192.   Inc(ListCount);
  193. end;
  194.  
  195. procedure ListRemove(i: Integer);
  196. begin
  197.   if i < ListCount-1 then
  198.     List[i] := List[ListCount-1];
  199.   Dec(ListCount);
  200. end;
  201.  
  202. procedure ListEmpty;
  203. begin
  204.   ListCount := 0;
  205. end;
  206.  
  207. function ListContains(p: taicpu): Boolean;
  208. var
  209.   I : Integer;
  210. begin
  211.   Result := False;
  212.   for I := 0 to ListCount-1 do begin
  213.     if IsIdentical(p, List[i]) then
  214.       exit(True);
  215.   end;
  216. end;
  217.  
  218. procedure ListRemoveInvalidated(p: taicpu);
  219. var
  220.   I : Integer;
  221. begin
  222.   for I := ListCount-1 downto 0 do begin
  223.     if IsInvalidating(p, List[I]) then
  224.       ListRemove(I);
  225.   end;
  226. end;
  227.  
  228. { remove certain redundant mov instructions from asml }
  229. function RemoveReload(asml: TAsmList; first, last: tai; pass: longint): boolean;
  230. var
  231.   p, pnext : taicpu;
  232.   was_removed: Boolean;
  233.   is_eligible: Boolean;
  234. begin
  235.   Result := False;
  236.   if pass < 3 then exit; // peephole would crash in earlier passes. why?
  237.  
  238.   p := taicpu(first);
  239.   repeat
  240.     was_removed := False;
  241.     is_eligible := False;
  242.     pnext := taicpu(p.Next);
  243.  
  244.     case p.typ of
  245.       ait_label:
  246.       begin
  247.         {$IFDEF DEBUGVERBOSE}
  248.         writeln('label');
  249.         {$ENDIF}
  250.         ListEmpty;
  251.       end;
  252.  
  253.       ait_instruction:
  254.       begin
  255.         {$IFDEF DEBUGVERBOSE}
  256.         write('  ', DebugInstString(p));
  257.         {$ENDIF}
  258.         if IsEligible(p) then // only care about certain kind of mov
  259.         begin
  260.           if taicpu(p).oper[1]^.typ = top_reg then
  261.           begin
  262.             is_eligible := True;
  263.             if ListContains(p) then begin
  264.               {$IFDEF DEBUG}
  265.               write(IntToStr(ListCount), ' ');
  266.               {$ENDIF}
  267.               {$IFDEF DEBUGPRINTREMOVED}
  268.               write(DebugInstString(p), '   in ');
  269.               writeln(DebugSourcePosInfo(p));
  270.               {$ENDIF}
  271.               asml.Remove(p);
  272.               p.Free;
  273.               Result := True;
  274.               was_removed := true;
  275.             end;
  276.           end;
  277.         end
  278.  
  279.         else if p.opcode = A_CALL then
  280.         begin
  281.           ListEmpty;
  282.         end;
  283.  
  284.         // all instructions
  285.  
  286.         if not was_removed then begin
  287.           ListRemoveInvalidated(p);
  288.  
  289.           if is_eligible then begin
  290.             ListAdd(p);
  291.           end;
  292.         end;
  293.  
  294.         {$IFDEF DEBUGVERBOSE}
  295.         writeln;
  296.         {$ENDIF}
  297.       end;
  298.     end;
  299.     p := pnext;
  300.   until p = last;
  301.   ListEmpty;
  302. end;
  303.  
  304.  
  305. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement