Browse Source

+ added an optimization pass, that optimizes x86 references

git-svn-id: trunk@37494 -
nickysn 7 years ago
parent
commit
80226e3af4

+ 1 - 0
compiler/i386/aoptcpu.pas

@@ -1462,6 +1462,7 @@ begin
       end;
       end;
       p := tai(p.next)
       p := tai(p.next)
     end;
     end;
+  OptReferences;
 end;
 end;
 
 
 
 

+ 8 - 0
compiler/i8086/aoptcpu.pas

@@ -34,6 +34,7 @@ unit aoptcpu;
     Type
     Type
       TCpuAsmOptimizer = class(TX86AsmOptimizer)
       TCpuAsmOptimizer = class(TX86AsmOptimizer)
         function PeepHoleOptPass1Cpu(var p : tai) : boolean; override;
         function PeepHoleOptPass1Cpu(var p : tai) : boolean; override;
+        procedure PostPeepHoleOpts; override;
       End;
       End;
 
 
   Implementation
   Implementation
@@ -112,6 +113,13 @@ unit aoptcpu;
         end;
         end;
       end;
       end;
 
 
+
+    procedure TCpuAsmOptimizer.PostPeepHoleOpts;
+      begin
+        inherited;
+        OptReferences;
+      end;
+
 begin
 begin
   casmoptimizer:=TCpuAsmOptimizer;
   casmoptimizer:=TCpuAsmOptimizer;
 end.
 end.

+ 43 - 0
compiler/x86/aasmcpu.pas

@@ -496,6 +496,7 @@ interface
     function is_16_bit_ref(const ref:treference):boolean;
     function is_16_bit_ref(const ref:treference):boolean;
     function get_ref_address_size(const ref:treference):byte;
     function get_ref_address_size(const ref:treference):byte;
     function get_default_segment_of_ref(const ref:treference):tregister;
     function get_default_segment_of_ref(const ref:treference):tregister;
+    procedure optimize_ref(var ref:treference; inlineasm: boolean);
 
 
     function spilling_create_load(const ref:treference;r:tregister):Taicpu;
     function spilling_create_load(const ref:treference;r:tregister):Taicpu;
     function spilling_create_store(r:tregister; const ref:treference):Taicpu;
     function spilling_create_store(r:tregister; const ref:treference):Taicpu;
@@ -1868,6 +1869,48 @@ implementation
       end;
       end;
 
 
 
 
+    procedure optimize_ref(var ref:treference; inlineasm: boolean);
+      var
+        ss_equals_ds: boolean;
+      begin
+        if inlineasm then
+          ss_equals_ds:=False
+        else
+          ss_equals_ds:=segment_regs_equal(NR_DS,NR_SS);
+        { remove redundant segment overrides }
+        if (ref.segment<>NR_NO) and (ref.segment=get_default_segment_of_ref(ref)) then
+          ref.segment:=NR_NO;
+        if not is_16_bit_ref(ref) then
+          begin
+            { Switching index to base position gives shorter assembler instructions.
+              Converting index*2 to base+index also gives shorter instructions. }
+            if (ref.base=NR_NO) and (ref.index<>NR_NO) and (ref.scalefactor<=2) and
+               (ss_equals_ds or (ref.segment<>NR_NO) or (ref.index<>NR_EBP)) then
+              begin
+                ref.base:=ref.index;
+                if ref.scalefactor=2 then
+                  ref.scalefactor:=1
+                else
+                  begin
+                    ref.index:=NR_NO;
+                    ref.scalefactor:=0;
+                  end;
+              end;
+            { Switching EBP+reg to reg+EBP sometimes gives shorter instructions (if there's no offset) }
+            if (ref.base=NR_EBP) and (ref.index<>NR_NO) and (ref.index<>NR_EBP) and
+               (ref.scalefactor<=1) and (ref.offset=0) and (ref.refaddr=addr_no) and
+               (ss_equals_ds or (ref.segment<>NR_NO)) then
+              begin
+                ref.base:=ref.index;
+                ref.index:=NR_EBP;
+              end;
+          end;
+        { remove redundant segment overrides again }
+        if (ref.segment<>NR_NO) and (ref.segment=get_default_segment_of_ref(ref)) then
+          ref.segment:=NR_NO;
+      end;
+
+
     function taicpu.needaddrprefix(opidx:byte):boolean;
     function taicpu.needaddrprefix(opidx:byte):boolean;
       begin
       begin
 {$if defined(x86_64)}
 {$if defined(x86_64)}

+ 21 - 0
compiler/x86/aoptx86.pas

@@ -73,6 +73,8 @@ unit aoptx86;
         function OptPass2Jcc(var p : tai) : boolean;
         function OptPass2Jcc(var p : tai) : boolean;
 
 
         procedure PostPeepholeOptMov(const p : tai);
         procedure PostPeepholeOptMov(const p : tai);
+
+        procedure OptReferences;
       end;
       end;
 
 
     function MatchInstruction(const instr: tai; const op: TAsmOp; const opsize: topsizes): boolean;
     function MatchInstruction(const instr: tai; const op: TAsmOp; const opsize: topsizes): boolean;
@@ -2665,5 +2667,24 @@ unit aoptx86;
       end;
       end;
     end;
     end;
 
 
+
+    procedure TX86AsmOptimizer.OptReferences;
+      var
+        p: tai;
+        i: Integer;
+      begin
+        p := BlockStart;
+        while (p <> BlockEnd) Do
+          begin
+            if p.typ=ait_instruction then
+              begin
+                for i:=0 to taicpu(p).ops-1 do
+                  if taicpu(p).oper[i]^.typ=top_ref then
+                    optimize_ref(taicpu(p).oper[i]^.ref^,false);
+              end;
+            p:=tai(p.next);
+          end;
+      end;
+
 end.
 end.
 
 

+ 8 - 0
compiler/x86_64/aoptcpu.pas

@@ -35,6 +35,7 @@ type
     function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
     function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
     function PeepHoleOptPass2Cpu(var p: tai): boolean; override;
     function PeepHoleOptPass2Cpu(var p: tai): boolean; override;
     function PostPeepHoleOptsCpu(var p : tai) : boolean; override;
     function PostPeepHoleOptsCpu(var p : tai) : boolean; override;
+    procedure PostPeepHoleOpts; override;
   end;
   end;
 
 
 implementation
 implementation
@@ -146,6 +147,13 @@ uses
         end;
         end;
       end;
       end;
 
 
+
+    procedure TCpuAsmOptimizer.PostPeepHoleOpts;
+      begin
+        inherited;
+        OptReferences;
+      end;
+
 begin
 begin
   casmoptimizer := TCpuAsmOptimizer;
   casmoptimizer := TCpuAsmOptimizer;
 end.
 end.