Browse Source

+ peepholeoptimizations to remove swap instructions

git-svn-id: trunk@31456 -
Jonas Maebe 10 years ago
parent
commit
32c3f05522
2 changed files with 126 additions and 16 deletions
  1. 126 1
      compiler/jvm/aoptcpu.pas
  2. 0 15
      compiler/jvm/rgcpu.pas

+ 126 - 1
compiler/jvm/aoptcpu.pas

@@ -32,9 +32,15 @@ uses cpubase, aasmtai, aopt, aoptcpub;
 
 
 Type
 Type
   TCpuAsmOptimizer = class(TAsmOptimizer)
   TCpuAsmOptimizer = class(TAsmOptimizer)
+   protected
+    function RemoveDoubleSwap(var p: tai): boolean;
+    function RemoveCommutativeSwap(var p: tai): boolean;
+    function RemoveLoadLoadSwap(var p: tai): boolean;
+   public
     { uses the same constructor as TAopObj }
     { uses the same constructor as TAopObj }
     function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
     function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
     procedure PeepHoleOptPass2;override;
     procedure PeepHoleOptPass2;override;
+    function PostPeepHoleOptsCpu(var p: tai): boolean; override;
   End;
   End;
 
 
 Implementation
 Implementation
@@ -42,9 +48,94 @@ Implementation
   uses
   uses
     aasmbase,aasmcpu,cgbase;
     aasmbase,aasmcpu,cgbase;
 
 
+
+  function TCpuAsmOptimizer.RemoveDoubleSwap(var p: tai): boolean;
+    var
+      next, next2: tai;
+    begin
+      result:=false;
+      { remove two successive "swap" instructions }
+      if (taicpu(p).opcode=a_swap) and
+         GetNextInstruction(p,next) and
+         (next.typ=ait_instruction) and
+         (taicpu(next).opcode=a_swap) then
+        begin
+          { can't be the instruction, must end in a return or so }
+          next2:=tai(next.next);
+          asml.remove(p);
+          asml.remove(next);
+          p.free;
+          next.free;
+          p:=next2;
+          result:=true;
+        end;
+    end;
+
+
+  { returns whether p is an instruction that does not consume any stack slots,
+    and adds a new item on the stack that is one stack slot wide }
+  function OpCreatesSingleStackSlot(p: tai): boolean;
+    begin
+      result:=
+        (p.typ=ait_instruction) and
+        (taicpu(p).opcode in
+          [a_aload, a_aload_0, a_aload_1, a_aload_2, a_aload_3,
+           a_bipush,
+           a_fconst_0, a_fconst_1, a_fconst_2,
+           a_fload, a_fload_0, a_fload_1, a_fload_2, a_fload_3,
+           a_getstatic,
+           a_iconst_m1, a_iconst_0, a_iconst_1, a_iconst_2, a_iconst_3,
+           a_iconst_4, a_iconst_5,
+           a_iload, a_iload_0, a_iload_1, a_iload_2, a_iload_3,
+           a_new,
+           a_sipush]);
+    end;
+
+
+  function OpIsCommutativeSingleSlots(p: tai): boolean;
+    begin
+      result:=
+        (p.typ=ait_instruction) and
+        (taicpu(p).opcode in
+          [a_fadd, a_fmul,
+           a_iadd, a_iand, a_imul, a_ior, a_ixor,
+           a_pop2])
+    end;
+
+
+  function TCpuAsmOptimizer.RemoveCommutativeSwap(var p: tai): boolean;
+    var
+      next: tai;
+    begin
+      result:=false;
+      if (taicpu(p).opcode<>a_swap) then
+        exit;
+      { if the next opcode is commutative operation, we can remove the swap }
+      if GetNextInstruction(p,next) and
+         OpIsCommutativeSingleSlots(next) then
+        begin
+          asml.remove(p);
+          p.free;
+          p:=next;
+          result:=true;
+          exit;
+        end;
+    end;
+
+
   function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
   function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+    var
+      next, next2: tai;
     begin
     begin
-      result := false;
+      result:=false;
+      case p.typ of
+        ait_instruction:
+          begin
+            if RemoveDoubleSwap(p) or
+               RemoveCommutativeSwap(p) then
+              exit(true)
+          end;
+      end;
     end;
     end;
 
 
 
 
@@ -52,6 +143,40 @@ Implementation
     begin
     begin
     end;
     end;
 
 
+
+  function TCpuAsmOptimizer.RemoveLoadLoadSwap(var p: tai): boolean;
+    var
+      next, prev1, prev2: tai;
+    begin
+      result:=false;
+      if (taicpu(p).opcode<>a_swap) then
+        exit;
+      { if we can swap the previous two instructions that put the items on the
+        stack, we can remove the swap -- only do this in PostPeepholeOpts,
+        because this may make the temp alloc information invalid. Ideally, we
+        should move the tempallocs around too }
+      if GetLastInstruction(p,prev1) and
+         OpCreatesSingleStackSlot(prev1) and
+         GetLastInstruction(prev1,prev2) and
+         OpCreatesSingleStackSlot(prev2) then
+        begin
+          next:=tai(p.next);
+          asml.remove(prev2);
+          asml.InsertAfter(prev2,prev1);
+          asml.remove(p);
+          p.free;
+          p:=next;
+          result:=true;
+        end;
+    end;
+
+
+  function TCpuAsmOptimizer.PostPeepHoleOptsCpu(var p: tai): boolean;
+    begin
+      result:=
+        RemoveLoadLoadSwap(p);
+    end;
+
 begin
 begin
   casmoptimizer:=TCpuAsmOptimizer;
   casmoptimizer:=TCpuAsmOptimizer;
 End.
 End.

+ 0 - 15
compiler/jvm/rgcpu.pas

@@ -312,21 +312,6 @@ implementation
                         removedsomething:=true;
                         removedsomething:=true;
                         continue;
                         continue;
                       end;
                       end;
-                    { todo in peephole optimizer:
-                        alloc regx // not double precision
-                        store regx // not double precision
-                        load  regy or memy
-                        dealloc regx
-                        load regx
-                      -> change into
-                        load regy or memy
-                        swap       // can only handle single precision
-
-                      and then
-                        swap
-                        <commutative op>
-                       -> remove swap
-                    }
                   end;
                   end;
               end;
               end;
               p:=tai(p.next);
               p:=tai(p.next);