Browse Source

* x86: PostPeepholeOptCmp and PostPeepholeOptTestOr
now do a final attempt of TrySwapMovCmp to
clean up Pass 2 optimisations

J. Gareth "Curious Kit" Moreton 2 years ago
parent
commit
dd7320ec13
1 changed files with 74 additions and 0 deletions
  1. 74 0
      compiler/x86/aoptx86.pas

+ 74 - 0
compiler/x86/aoptx86.pas

@@ -15096,8 +15096,46 @@ unit aoptx86;
 
 
 
 
     function TX86AsmOptimizer.PostPeepholeOptCmp(var p : tai) : Boolean;
     function TX86AsmOptimizer.PostPeepholeOptCmp(var p : tai) : Boolean;
+      var
+        hp1: tai;
       begin
       begin
         Result:=false;
         Result:=false;
+
+        { Final check to see if CMP/MOV pairs can be changed to MOV/CMP }
+        while GetNextInstruction(p, hp1) and
+          TrySwapMovCmp(p, hp1) do
+          begin
+            if MatchInstruction(hp1, A_MOV, []) then
+              begin
+                if RegInUsedRegs(NR_DEFAULTFLAGS, UsedRegs) then
+                  begin
+                    { A little hacky, but since CMP doesn't read the flags, only
+                      modify them, it's safe if they get scrambled by MOV -> XOR }
+                    ExcludeRegFromUsedRegs(NR_DEFAULTFLAGS, UsedRegs);
+                    Result := PostPeepholeOptMov(hp1);
+{$ifdef x86_64}
+                    if Result and MatchInstruction(hp1, A_XOR, [S_Q]) then
+                      { Used to shrink instruction size }
+                      PostPeepholeOptXor(hp1);
+{$endif x86_64}
+                    IncludeRegInUsedRegs(NR_DEFAULTFLAGS, UsedRegs);
+                  end
+                else
+                  begin
+                    Result := PostPeepholeOptMov(hp1);
+{$ifdef x86_64}
+                    if Result and MatchInstruction(hp1, A_XOR, [S_Q]) then
+                      { Used to shrink instruction size }
+                      PostPeepholeOptXor(hp1);
+{$endif x86_64}
+                  end;
+              end;
+
+            { Enabling this flag is actually a null operation, but it marks
+              the code as 'modified' during this pass }
+            Include(OptsToCheck, aoc_ForceNewIteration);
+          end;
+
         { change "cmp $0, %reg" to "test %reg, %reg" }
         { change "cmp $0, %reg" to "test %reg, %reg" }
         if MatchOpType(taicpu(p),top_const,top_reg) and
         if MatchOpType(taicpu(p),top_const,top_reg) and
            (taicpu(p).oper[0]^.val = 0) then
            (taicpu(p).oper[0]^.val = 0) then
@@ -15116,6 +15154,42 @@ unit aoptx86;
         hp1,hp2 : tai;
         hp1,hp2 : tai;
       begin
       begin
         Result:=false;
         Result:=false;
+        { Final check to see if TEST/MOV pairs can be changed to MOV/TEST }
+        if (taicpu(p).opcode = A_TEST) then
+          while GetNextInstruction(p, hp1) and
+            TrySwapMovCmp(p, hp1) do
+            begin
+              if MatchInstruction(hp1, A_MOV, []) then
+                begin
+                  if RegInUsedRegs(NR_DEFAULTFLAGS, UsedRegs) then
+                    begin
+                      { A little hacky, but since TEST doesn't read the flags, only
+                        modify them, it's safe if they get scrambled by MOV -> XOR }
+                      ExcludeRegFromUsedRegs(NR_DEFAULTFLAGS, UsedRegs);
+                      Result := PostPeepholeOptMov(hp1);
+{$ifdef x86_64}
+                      if Result and MatchInstruction(hp1, A_XOR, [S_Q]) then
+                        { Used to shrink instruction size }
+                        PostPeepholeOptXor(hp1);
+{$endif x86_64}
+                      IncludeRegInUsedRegs(NR_DEFAULTFLAGS, UsedRegs);
+                    end
+                  else
+                    begin
+                      Result := PostPeepholeOptMov(hp1);
+{$ifdef x86_64}
+                      if Result and MatchInstruction(hp1, A_XOR, [S_Q]) then
+                        { Used to shrink instruction size }
+                        PostPeepholeOptXor(hp1);
+{$endif x86_64}
+                    end;
+                end;
+
+              { Enabling this flag is actually a null operation, but it marks
+                the code as 'modified' during this pass }
+              Include(OptsToCheck, aoc_ForceNewIteration);
+            end;
+
         { If x is a power of 2 (popcnt = 1), change:
         { If x is a power of 2 (popcnt = 1), change:
             or  $x, %reg/ref
             or  $x, %reg/ref