Browse Source

* arm/a64: New sbfx/ubfx -> mov optimisation

J. Gareth "Curious Kit" Moreton 3 years ago
parent
commit
d6ff4ed967
3 changed files with 75 additions and 0 deletions
  1. 17 0
      compiler/aarch64/aoptcpu.pas
  2. 17 0
      compiler/arm/aoptcpu.pas
  3. 41 0
      compiler/armgen/aoptarm.pas

+ 17 - 0
compiler/aarch64/aoptcpu.pas

@@ -40,6 +40,7 @@ Interface
     Type
       TCpuAsmOptimizer = class(TARMAsmOptimizer)
         { uses the same constructor as TAopObj }
+        function PrePeepHoleOptsCpu(var p: tai): boolean; override;
         function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
         function PeepHoleOptPass2Cpu(var p: tai): boolean; override;
         function PostPeepHoleOptsCpu(var p: tai): boolean; override;
@@ -945,6 +946,22 @@ Implementation
     end;
 
 
+  function TCpuAsmOptimizer.PrePeepHoleOptsCpu(var p: tai): boolean;
+    begin
+      result := false;
+      if p.typ=ait_instruction then
+        begin
+          case taicpu(p).opcode of
+            A_SBFX,
+            A_UBFX:
+              Result:=OptPreSBFXUBFX(p);
+            else
+              ;
+          end;
+        end;
+    end;
+
+
   function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
     begin
       result := false;

+ 17 - 0
compiler/arm/aoptcpu.pas

@@ -44,6 +44,7 @@ Type
     function CanDoJumpOpts: Boolean; override;
 
     { uses the same constructor as TAopObj }
+    function PrePeepHoleOptsCpu(var p: tai): Boolean; override;
     function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
     function PeepHoleOptPass2Cpu(var p: tai): boolean; override;
     Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;override;
@@ -2280,6 +2281,22 @@ Implementation
     end;
 
 
+  function TCpuAsmOptimizer.PrePeepHoleOptsCpu(var p: tai): Boolean;
+    begin
+      result := false;
+      if p.typ=ait_instruction then
+        begin
+          case taicpu(p).opcode of
+            A_SBFX,
+            A_UBFX:
+              Result:=OptPreSBFXUBFX(p);
+            else
+              ;
+          end;
+        end;
+    end;
+
+
   function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
     begin
       result := false;

+ 41 - 0
compiler/armgen/aoptarm.pas

@@ -45,11 +45,14 @@ Type
     function RedundantMovProcess(var p: tai; var hp1: tai): boolean;
     function GetNextInstructionUsingReg(Current: tai; out Next: tai; const reg: TRegister): Boolean;
 
+    function OptPreSBFXUBFX(var p: tai): Boolean;
+
     function OptPass1UXTB(var p: tai): Boolean;
     function OptPass1UXTH(var p: tai): Boolean;
     function OptPass1SXTB(var p: tai): Boolean;
     function OptPass1SXTH(var p: tai): Boolean;
 
+
     function OptPass1LDR(var p: tai): Boolean; virtual;
     function OptPass1STR(var p: tai): Boolean; virtual;
     function OptPass1And(var p: tai): Boolean; virtual;
@@ -1070,6 +1073,44 @@ Implementation
     end;
 
 
+  function TARMAsmOptimizer.OptPreSBFXUBFX(var p: tai): Boolean;
+    begin
+      Result := False;
+      { Convert:
+          s/ubfx reg1,reg2,#0,#64 (or #32 for 32-bit registers)
+        To:
+          mov    reg1,reg2
+      }
+      if (taicpu(p).oper[2]^.val = 0) and
+{$ifdef AARCH64}
+        (
+          (
+            (getsubreg(taicpu(p).oper[0]^.reg) = R_SUBQ) and
+            (taicpu(p).oper[3]^.val = 64)
+          ) or
+          (
+            (getsubreg(taicpu(p).oper[0]^.reg) = R_SUBD) and
+            (taicpu(p).oper[3]^.val = 32)
+          )
+        )
+{$else AARCH64}
+        (taicpu(p).oper[3]^.val = 32)
+{$endif AARCH64}
+        then
+        begin
+          DebugMsg(SPeepholeOptimization + 'SBFX or UBFX -> MOV (full bitfield extract)', p);
+          taicpu(p).opcode := A_MOV;
+          taicpu(p).ops := 2;
+          taicpu(p).clearop(2);
+          taicpu(p).clearop(3);
+
+          Result := True;
+          Exit;
+        end;
+
+    end;
+
+
   function TARMAsmOptimizer.OptPass1LDR(var p : tai) : Boolean;
     var
       hp1: tai;