Browse Source

+ m68k: LEA, MOVE(M) to MOVE(M) predecremented optimization and MOVE(M), LEA to MOVE(M) postincremented optimization

git-svn-id: trunk@47762 -
florian 4 years ago
parent
commit
0ab69ea0ad
1 changed files with 80 additions and 16 deletions
  1. 80 16
      compiler/m68k/aoptcpu.pas

+ 80 - 16
compiler/m68k/aoptcpu.pas

@@ -40,6 +40,8 @@ unit aoptcpu;
 
         function TryToOptimizeMove(var p: tai): boolean;
         function MaybeRealConstOperSimplify(var p: tai): boolean;
+        function OptPass1LEA(var p: tai): Boolean;
+        function OptPass1MOVEM(var p: tai): Boolean;
 
         { outputs a debug message into the assembler file }
         procedure DebugMsg(const s: string; p: tai);
@@ -48,7 +50,8 @@ unit aoptcpu;
   Implementation
 
     uses
-      cutils, aasmcpu, cgutils, globtype, globals, verbose, cpuinfo, itcpugas, procinfo, cpupi;
+      cutils, aasmcpu, cgutils, globtype, globals, verbose, cpuinfo, itcpugas, procinfo, cpupi,
+      aoptutils;
 
 { Range check must be disabled explicitly as conversions between signed and unsigned
   32-bit values are done without explicit typecasts }
@@ -344,6 +347,79 @@ unit aoptcpu;
         end;
     end;
 
+  function TCpuAsmOptimizer.OptPass1LEA(var p: tai): Boolean;
+    var
+      next: tai;
+    begin
+      Result:=false;
+      { LEA (Ax),Ax is a NOP if src and dest reg is equal, so remove it. }
+      if not assigned(taicpu(p).oper[0]^.ref^.symbol) and
+         (((taicpu(p).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) and
+         (taicpu(p).oper[0]^.ref^.index = NR_NO)) or
+         ((taicpu(p).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) and
+         (taicpu(p).oper[0]^.ref^.base = NR_NO))) and
+         (taicpu(p).oper[0]^.ref^.offset = 0) then
+        begin
+          DebugMsg('Optimizer: LEA 0(Ax),Ax removed',p);
+          GetNextInstruction(p,next);
+          asml.remove(p);
+          p.free;
+          p:=next;
+          result:=true;
+          exit;
+        end;
+      if (taicpu(p).oper[1]^.reg=NR_A7) and
+        (taicpu(p).oper[0]^.ref^.base=NR_A7) and
+        (taicpu(p).oper[0]^.ref^.index=NR_NO) and
+        (taicpu(p).oper[0]^.ref^.symbol=nil) and
+        (taicpu(p).oper[0]^.ref^.direction=dir_none) and
+        GetNextInstruction(p,next) and
+        MatchInstruction(next,A_MOVEM,[S_L]) and
+        MatchOpType(taicpu(next),top_regset,top_ref) and
+        ((taicpu(p).oper[0]^.ref^.offset=-(PopCnt(Byte(taicpu(next).oper[0]^.dataregset))+PopCnt(Byte(taicpu(next).oper[0]^.addrregset)))*4)) and
+        (taicpu(next).oper[1]^.ref^.base=NR_A7) and
+        (taicpu(next).oper[1]^.ref^.index=NR_NO) and
+        (taicpu(next).oper[1]^.ref^.symbol=nil) and
+        (taicpu(next).oper[1]^.ref^.direction=dir_none) then
+        begin
+          DebugMsg('Optimizer: LEA, MOVE(M) to MOVE(M) predecremented',p);
+          taicpu(next).oper[1]^.ref^.direction:=dir_dec;
+          asml.remove(p);
+          p.free;
+          p:=next;
+          result:=true;
+          exit;
+        end;
+    end;
+
+  function TCpuAsmOptimizer.OptPass1MOVEM(var p: tai): Boolean;
+    var
+      next: tai;
+    begin
+      Result:=false;
+      if MatchOpType(taicpu(p),top_ref,top_regset) and
+        (taicpu(p).oper[0]^.ref^.base=NR_A7) and
+        (taicpu(p).oper[0]^.ref^.index=NR_NO) and
+        (taicpu(p).oper[0]^.ref^.symbol=nil) and
+        (taicpu(p).oper[0]^.ref^.direction=dir_none) and
+        GetNextInstruction(p,next) and
+        MatchInstruction(next,A_LEA,[S_L]) and
+        (taicpu(next).oper[1]^.reg=NR_A7) and
+        (taicpu(next).oper[0]^.ref^.base=NR_A7) and
+        (taicpu(next).oper[0]^.ref^.index=NR_NO) and
+        (taicpu(next).oper[0]^.ref^.symbol=nil) and
+        (taicpu(next).oper[0]^.ref^.direction=dir_none) and
+        ((taicpu(next).oper[0]^.ref^.offset=(PopCnt(Byte(taicpu(p).oper[1]^.dataregset))+PopCnt(Byte(taicpu(p).oper[1]^.addrregset)))*4)) then
+        begin
+          DebugMsg('Optimizer: MOVE(M), LEA to MOVE(M) postincremented',p);
+          taicpu(p).oper[0]^.ref^.direction:=dir_inc;
+          asml.remove(next);
+          next.free;
+          result:=true;
+          exit;
+        end;
+    end;
+
   function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
     var
       next: tai;
@@ -358,22 +434,10 @@ unit aoptcpu;
             case taicpu(p).opcode of
               A_MOVE:
                 result:=TryToOptimizeMove(p);
-              { LEA (Ax),Ax is a NOP if src and dest reg is equal, so remove it. }
+              A_MOVEM:
+                result:=OptPass1MOVEM(p);
               A_LEA:
-                if not assigned(taicpu(p).oper[0]^.ref^.symbol) and
-                   (((taicpu(p).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) and
-                   (taicpu(p).oper[0]^.ref^.index = NR_NO)) or
-                   ((taicpu(p).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) and
-                   (taicpu(p).oper[0]^.ref^.base = NR_NO))) and
-                   (taicpu(p).oper[0]^.ref^.offset = 0) then
-                  begin
-                    DebugMsg('Optimizer: LEA 0(Ax),Ax removed',p);
-                    GetNextInstruction(p,next);
-                    asml.remove(p);
-                    p.free;
-                    p:=next;
-                    result:=true;
-                  end;
+                Result:=OptPass1LEA(p);
               { Address register sub/add can be replaced with ADDQ/SUBQ or LEA if the value is in the
                 SmallInt range, which is shorter to encode and faster to execute on most 68k }
               A_SUB,A_SUBA,A_ADD,A_ADDA: