Browse Source

* arm: "OpCmp2OpS" moved to Pass 2 so it doesn't conflict with AND; CMP -> TST optimisation

J. Gareth "Curious Kit" Moreton 1 year ago
parent
commit
6b2e4fa413
1 changed files with 58 additions and 47 deletions
  1. 58 47
      compiler/arm/aoptcpu.pas

+ 58 - 47
compiler/arm/aoptcpu.pas

@@ -86,6 +86,7 @@ Type
     function OptPass1Push(var p: tai): Boolean;
     function OptPass1Push(var p: tai): Boolean;
 
 
     function OptPass2Bcc(var p: tai): Boolean;
     function OptPass2Bcc(var p: tai): Boolean;
+    function OptPass2CMP(var p: tai): Boolean;
     function OptPass2STM(var p: tai): Boolean;
     function OptPass2STM(var p: tai): Boolean;
     function OptPass2STR(var p: tai): Boolean;
     function OptPass2STR(var p: tai): Boolean;
   End;
   End;
@@ -853,53 +854,6 @@ Implementation
                 else
                 else
                   hp1 := hp2;
                   hp1 := hp2;
             end;
             end;
-
-          {
-            change
-            <op> reg,x,y
-            cmp reg,#0
-            into
-            <op>s reg,x,y
-          }
-          if (taicpu(p).oppostfix = PF_None) and
-            (taicpu(p).oper[1]^.val = 0) and
-            { be careful here, following instructions could use other flags
-              however after a jump fpc never depends on the value of flags }
-            { All above instructions set Z and N according to the following
-              Z := result = 0;
-              N := result[31];
-              EQ = Z=1; NE = Z=0;
-              MI = N=1; PL = N=0; }
-            (MatchInstruction(hp1, A_B, [C_EQ,C_NE,C_MI,C_PL], []) or
-            { mov is also possible, but only if there is no shifter operand, it could be an rxx,
-              we are too lazy to check if it is rxx or something else }
-            (MatchInstruction(hp1, A_MOV, [C_EQ,C_NE,C_MI,C_PL], []) and (taicpu(hp1).ops=2))) and
-            GetLastInstruction(p, hp_last) and
-            MatchInstruction(hp_last, [A_ADC,A_ADD,A_BIC,A_SUB,A_MUL,A_MVN,A_MOV,A_ORR,
-              A_EOR,A_AND,A_RSB,A_RSC,A_SBC,A_MLA], [C_None], [PF_None]) and
-            (
-              { mlas is only allowed in arm mode }
-              (taicpu(hp_last).opcode<>A_MLA) or
-              (current_settings.instructionset<>is_thumb)
-            ) and
-            (taicpu(hp_last).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
-            assigned(FindRegDealloc(NR_DEFAULTFLAGS,tai(hp1.Next))) then
-            begin
-              DebugMsg(SPeepholeOptimization + 'OpCmp2OpS done', hp_last);
-
-              taicpu(hp_last).oppostfix:=PF_S;
-
-              { move flag allocation if possible }
-              hp1:=FindRegAlloc(NR_DEFAULTFLAGS,tai(hp_last.Next));
-              if assigned(hp1) then
-                begin
-                  asml.Remove(hp1);
-                  asml.insertbefore(hp1, hp_last);
-                end;
-
-              RemoveCurrentP(p);
-              Result:=true;
-            end;
         end;
         end;
     end;
     end;
 
 
@@ -2135,6 +2089,61 @@ Implementation
     end;
     end;
 
 
 
 
+  function TCpuAsmOptimizer.OptPass2CMP(var p: tai): Boolean;
+    var
+      hp1, hp_last: tai;
+    begin
+      Result := False;
+      {
+        change
+        <op> reg,x,y
+        cmp reg,#0
+        into
+        <op>s reg,x,y
+      }
+      if (taicpu(p).oppostfix = PF_None) and
+        (taicpu(p).oper[1]^.val = 0) and
+        GetNextInstruction(p, hp1) and
+        { be careful here, following instructions could use other flags
+          however after a jump fpc never depends on the value of flags }
+        { All above instructions set Z and N according to the following
+          Z := result = 0;
+          N := result[31];
+          EQ = Z=1; NE = Z=0;
+          MI = N=1; PL = N=0; }
+        (MatchInstruction(hp1, A_B, [C_EQ,C_NE,C_MI,C_PL], []) or
+        { mov is also possible, but only if there is no shifter operand, it could be an rxx,
+          we are too lazy to check if it is rxx or something else }
+        (MatchInstruction(hp1, A_MOV, [C_EQ,C_NE,C_MI,C_PL], []) and (taicpu(hp1).ops=2))) and
+        GetLastInstruction(p, hp_last) and
+        MatchInstruction(hp_last, [A_ADC,A_ADD,A_BIC,A_SUB,A_MUL,A_MVN,A_MOV,A_ORR,
+          A_EOR,A_AND,A_RSB,A_RSC,A_SBC,A_MLA], [C_None], [PF_None]) and
+        (
+          { mlas is only allowed in arm mode }
+          (taicpu(hp_last).opcode<>A_MLA) or
+          (current_settings.instructionset<>is_thumb)
+        ) and
+        (taicpu(hp_last).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
+        assigned(FindRegDealloc(NR_DEFAULTFLAGS,tai(hp1.Next))) then
+        begin
+          DebugMsg(SPeepholeOptimization + 'OpCmp2OpS done', hp_last);
+
+          taicpu(hp_last).oppostfix:=PF_S;
+
+          { move flag allocation if possible }
+          hp1:=FindRegAlloc(NR_DEFAULTFLAGS,tai(hp_last.Next));
+          if assigned(hp1) then
+            begin
+              asml.Remove(hp1);
+              asml.insertbefore(hp1, hp_last);
+            end;
+
+          RemoveCurrentP(p);
+          Result:=true;
+        end;
+    end;
+
+
   function TCpuAsmOptimizer.OptPass2STR(var p: tai): Boolean;
   function TCpuAsmOptimizer.OptPass2STR(var p: tai): Boolean;
     var
     var
       hp1: tai;
       hp1: tai;
@@ -2390,6 +2399,8 @@ Implementation
           case taicpu(p).opcode of
           case taicpu(p).opcode of
             A_AND:
             A_AND:
               Result := OptPass2AND(p);
               Result := OptPass2AND(p);
+            A_CMP:
+              Result := OptPass2CMP(p);
             A_B:
             A_B:
               Result := OptPass2Bcc(p);
               Result := OptPass2Bcc(p);
             A_STM:
             A_STM: