Browse Source

* x86: TEST and CMP optimisations now perform jump optimisations prematurely to remove unnecessary TEST/CMPs

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

+ 93 - 1
compiler/x86/aoptx86.pas

@@ -5019,6 +5019,7 @@ unit aoptx86;
         hp1, p_label, p_dist, hp1_dist: tai;
         hp1, p_label, p_dist, hp1_dist: tai;
         JumpLabel, JumpLabel_dist: TAsmLabel;
         JumpLabel, JumpLabel_dist: TAsmLabel;
         FirstValue, SecondValue: TCGInt;
         FirstValue, SecondValue: TCGInt;
+        TempBool: Boolean;
       begin
       begin
         Result := False;
         Result := False;
         if (taicpu(p).oper[0]^.typ = top_const) and
         if (taicpu(p).oper[0]^.typ = top_const) and
@@ -5064,6 +5065,44 @@ unit aoptx86;
             Exit;
             Exit;
           end;
           end;
 
 
+        if MatchInstruction(hp1, A_Jcc, []) then
+          begin
+            TempBool := True;
+            if DoJumpOptimizations(hp1, TempBool) or
+              not TempBool then
+              begin
+                Result := True;
+
+                if Assigned(hp1) then
+                  begin
+                    if (hp1.typ in [ait_align]) then
+                      SkipAligns(hp1, hp1);
+
+                    { CollapseZeroDistJump will be set to the label after the
+                      jump if it optimises, whether or not it's live or dead }
+                    if (hp1.typ in [ait_label]) and
+                      not (tai_label(hp1).labsym.is_used) then
+                      GetNextInstruction(hp1, hp1);
+                  end;
+
+                TransferUsedRegs(TmpUsedRegs);
+                UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
+
+                if not Assigned(hp1) or
+                  (
+                    not MatchInstruction(hp1, A_Jcc, A_SETcc, A_CMOVcc, []) and
+                    not RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs)
+                  ) then
+                  begin
+                    { No more conditional jumps; conditional statement is no longer required }
+                    DebugMsg(SPeepholeOptimization + 'Removed unnecessary condition (Test2Nop)', p);
+                    RemoveCurrentP(p);
+                  end;
+
+                Exit;
+              end;
+          end;
+
         { Search for:
         { Search for:
             test  $x,(reg/ref)
             test  $x,(reg/ref)
             jne   @lbl1
             jne   @lbl1
@@ -7233,7 +7272,7 @@ unit aoptx86;
        var
        var
          v: TCGInt;
          v: TCGInt;
          hp1, hp2, p_dist, p_jump, hp1_dist, p_label, hp1_label: tai;
          hp1, hp2, p_dist, p_jump, hp1_dist, p_label, hp1_label: tai;
-         FirstMatch: Boolean;
+         FirstMatch, TempBool: Boolean;
          NewReg: TRegister;
          NewReg: TRegister;
          JumpLabel, JumpLabel_dist, JumpLabel_far: TAsmLabel;
          JumpLabel, JumpLabel_dist, JumpLabel_far: TAsmLabel;
        begin
        begin
@@ -7263,7 +7302,60 @@ unit aoptx86;
            begin
            begin
              if IsJumpToLabel(taicpu(p_jump)) then
              if IsJumpToLabel(taicpu(p_jump)) then
                begin
                begin
+                 { Do jump optimisations first in case the condition becomes
+                   unnecessary }
+
+                 TempBool := True;
+                 if DoJumpOptimizations(p_jump, TempBool) or
+                   not TempBool then
+                   begin
+
+                     if Assigned(p_jump) then
+                       begin
+                         hp1 := p_jump;
+                         if (p_jump.typ in [ait_align]) then
+                           SkipAligns(p_jump, p_jump);
+
+                         { CollapseZeroDistJump will be set to the label after the
+                           jump if it optimises, whether or not it's live or dead }
+                         if (p_jump.typ in [ait_label]) and
+                           not (tai_label(p_jump).labsym.is_used) then
+                           GetNextInstruction(p_jump, p_jump);
+                       end;
+
+                     TransferUsedRegs(TmpUsedRegs);
+                     UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
+
+                     if not Assigned(p_jump) or
+                       (
+                         not MatchInstruction(p_jump, A_Jcc, A_SETcc, A_CMOVcc, []) and
+                         not RegUsedAfterInstruction(NR_DEFAULTFLAGS, p_jump, TmpUsedRegs)
+                       ) then
+                       begin
+                         { No more conditional jumps; conditional statement is no longer required }
+                         DebugMsg(SPeepholeOptimization + 'Removed unnecessary condition (Cmp2Nop)', p);
+                         RemoveCurrentP(p);
+                         Result := True;
+                         Exit;
+                       end;
+
+                     hp1 := p_jump;
+                     Include(OptsToCheck, aoc_ForceNewIteration);
+                     Continue;
+                   end;
+
                  JumpLabel := TAsmLabel(taicpu(p_jump).oper[0]^.ref^.symbol);
                  JumpLabel := TAsmLabel(taicpu(p_jump).oper[0]^.ref^.symbol);
+                 if GetNextInstruction(p_jump, hp2) and
+                   (
+                     OptimizeConditionalJump(JumpLabel, p_jump, hp2, TempBool) or
+                     not TempBool
+                   ) then
+                   begin
+                     hp1 := p_jump;
+                     Include(OptsToCheck, aoc_ForceNewIteration);
+                     Continue;
+                   end;
+
                  p_label := nil;
                  p_label := nil;
                  if Assigned(JumpLabel) then
                  if Assigned(JumpLabel) then
                    p_label := getlabelwithsym(JumpLabel);
                    p_label := getlabelwithsym(JumpLabel);