Browse Source

Bug fix to MovMov2Mov 6 optimisation exposed by 4012c3dbd47f661805bb7a831c6c687807ede3b4 (and miscellaneous code refactors)

J. Gareth "Curious Kit" Moreton 3 years ago
parent
commit
342803532d
1 changed files with 17 additions and 12 deletions
  1. 17 12
      compiler/x86/aoptx86.pas

+ 17 - 12
compiler/x86/aoptx86.pas

@@ -111,7 +111,7 @@ unit aoptx86;
 
         { Replaces all references to AOldReg in an instruction to ANewReg,
           except where the register is being written }
-        function ReplaceRegisterInInstruction(const p: taicpu; const AOldReg, ANewReg: TRegister): Boolean;
+        class function ReplaceRegisterInInstruction(const p: taicpu; const AOldReg, ANewReg: TRegister): Boolean; static;
 
         { Returns true if the reference only refers to ESP or EBP (or their 64-bit equivalents),
           or writes to a global symbol }
@@ -2198,7 +2198,7 @@ unit aoptx86;
 
 
     { Replaces all references to AOldReg in an instruction to ANewReg }
-    function TX86AsmOptimizer.ReplaceRegisterInInstruction(const p: taicpu; const AOldReg, ANewReg: TRegister): Boolean;
+    class function TX86AsmOptimizer.ReplaceRegisterInInstruction(const p: taicpu; const AOldReg, ANewReg: TRegister): Boolean;
       const
         ReadFlag: array[0..3] of TInsChange = (Ch_Rop1, Ch_Rop2, Ch_Rop3, Ch_Rop4);
       var
@@ -3436,7 +3436,7 @@ unit aoptx86;
                               }
                               CurrentReg := taicpu(p).oper[0]^.reg; { Saves on a handful of pointer dereferences }
                               RegName1 := debug_regname(taicpu(hp2).oper[0]^.reg);
-                              if taicpu(hp2).oper[1]^.reg = CurrentReg then
+                              if MatchOperand(taicpu(hp2).oper[1]^, CurrentReg) then
                                 begin
                                   { %reg = y - remove hp2 completely (doing it here instead of relying on
                                     the "mov %reg,%reg" optimisation might cut down on a pass iteration) }
@@ -3468,22 +3468,27 @@ unit aoptx86;
                                 begin
                                   AllocRegBetween(CurrentReg, p, hp2, UsedRegs);
                                   taicpu(hp2).loadReg(0, CurrentReg);
-                                  if TempRegUsed then
-                                    begin
-                                      { Don't remove the first instruction if the temporary register is in use }
-                                      DebugMsg(SPeepholeOptimization + RegName1 + ' = ' + debug_regname(CurrentReg) + '; changed to minimise pipeline stall (MovMov2Mov 6a}',hp2);
 
-                                      { No need to set Result to True. If there's another instruction later on
-                                        that can be optimised, it will be detected when the main Pass 1 loop
-                                        reaches what is now hp2 and passes it through OptPass1MOV. [Kit] };
-                                    end
-                                  else
+                                  DebugMsg(SPeepholeOptimization + RegName1 + ' = ' + debug_regname(CurrentReg) + '; changed to minimise pipeline stall (MovMov2Mov 6a}',hp2);
+
+                                  { Check to see if the register also appears in the reference }
+                                  if (taicpu(hp2).oper[1]^.typ = top_ref) then
+                                    ReplaceRegisterInRef(taicpu(hp2).oper[1]^.ref^, ActiveReg, CurrentReg);
+
+                                  { Don't remove the first instruction if the temporary register is in use }
+                                  if not TempRegUsed and
+                                    { ReplaceRegisterInRef won't actually replace the register if it's a different size }
+                                    not RegInOp(ActiveReg, taicpu(hp2).oper[1]^) then
                                     begin
                                       DebugMsg(SPeepholeOptimization + 'MovMov2Mov 6 done',p);
                                       RemoveCurrentP(p, hp1);
                                       Result:=true;
                                       Exit;
                                     end;
+
+                                  { No need to set Result to True here. If there's another instruction later
+                                    on that can be optimised, it will be detected when the main Pass 1 loop
+                                    reaches what is now hp2 and passes it through OptPass1MOV. [Kit] }
                                 end;
                             end;
                           top_const: