瀏覽代碼

- Mov2Nop 5a and Mov2Nop 5b optimisations upgraded.

J. Gareth "Curious Kit" Moreton 1 年之前
父節點
當前提交
1bc0ae3d18
共有 1 個文件被更改,包括 91 次插入68 次删除
  1. 91 68
      compiler/x86/aoptx86.pas

+ 91 - 68
compiler/x86/aoptx86.pas

@@ -4218,6 +4218,97 @@ unit aoptx86;
               end;
           end;
 
+        if taicpu(p).oper[0]^.typ = top_reg then
+          begin
+            { oper[1] is a reference }
+
+            { Saves on a large number of dereferences }
+            p_SourceReg := taicpu(p).oper[0]^.reg;
+
+            if NotFirstIteration and (cs_opt_level3 in current_settings.optimizerswitches) then
+              GetNextInstruction_p := GetNextInstructionUsingReg(p, hp1, p_SourceReg)
+            else
+              GetNextInstruction_p := GetNextInstruction(p, hp1);
+
+            if GetNextInstruction_p and (hp1.typ = ait_instruction) then
+              begin
+
+                if taicpu(p).oper[1]^.typ = top_reg then
+                  begin
+                    p_TargetReg := taicpu(p).oper[1]^.reg;
+
+                    { Change:
+                        movl %reg1,%reg2
+                        ...
+                        movl x(%reg1),%reg1  (If something other than %reg1 is written to, DeepMOVOpt would have caught it)
+                        ...
+                        movl x(%reg2),%regX  (%regX can be %reg2 or something else)
+                      To:
+                        movl %reg1,%reg2 (if %regX = %reg2, then remove this instruction)
+                        ...
+                        movl x(%reg1),%reg1
+                        ...
+                        movl %reg1,%regX
+                    }
+                    if MatchInstruction(hp1, A_MOV, [taicpu(p).opsize]) and
+                      (taicpu(hp1).oper[0]^.typ = top_ref) { The other operand will be a register } and
+                      (taicpu(hp1).oper[1]^.reg = p_SourceReg) and
+                      RegInRef(p_SourceReg, taicpu(hp1).oper[0]^.ref^) and
+                      not RegModifiedBetween(p_TargetReg, p, hp1) and
+                      GetNextInstructionUsingReg(hp1, hp2, p_TargetReg) and
+                      MatchInstruction(hp2, A_MOV, [taicpu(p).opsize]) and
+                      (taicpu(hp2).oper[0]^.typ = top_ref) { The other operand will be a register } and
+                      not RegModifiedBetween(p_SourceReg, hp1, hp2) then
+                      begin
+                        SourceRef := taicpu(hp2).oper[0]^.ref^;
+                        if RegInRef(p_TargetReg, SourceRef) and
+                          { If %reg1 also appears in the second reference, then it will
+                            not refer to the same memory block as the first reference }
+                          not RegInRef(p_SourceReg, SourceRef) then
+                          begin
+                            { Check to see if the references match if %reg2 is changed to %reg1 }
+                            if SourceRef.base = p_TargetReg then
+                              SourceRef.base := p_SourceReg;
+
+                            if SourceRef.index = p_TargetReg then
+                              SourceRef.index := p_SourceReg;
+
+                            { RefsEqual also checks to ensure both references are non-volatile }
+                            if RefsEqual(taicpu(hp1).oper[0]^.ref^, SourceRef) then
+                              begin
+                                taicpu(hp2).loadreg(0, p_SourceReg);
+
+                                DebugMsg(SPeepholeOptimization + 'Optimised register duplication and memory read (MovMovMov2MovMovMov)', p);
+                                Result := True;
+                                if taicpu(hp2).oper[1]^.reg = p_TargetReg then
+                                  begin
+                                    DebugMsg(SPeepholeOptimization + 'Mov2Nop 5a done', p);
+                                    RemoveCurrentP(p);
+                                    Exit;
+                                  end
+                                else
+                                  begin
+                                    { Check to see if %reg2 is no longer in use }
+                                    TransferUsedRegs(TmpUsedRegs);
+                                    UpdateUsedRegsBetween(TmpUsedRegs, tai(p.Next), hp1);
+                                    UpdateUsedRegsBetween(TmpUsedRegs, tai(hp1.Next), hp2);
+
+                                    if not RegUsedAfterInstruction(p_TargetReg, hp2, TmpUsedRegs) then
+                                      begin
+                                        DebugMsg(SPeepholeOptimization + 'Mov2Nop 5b done', p);
+                                        RemoveCurrentP(p);
+                                        Exit;
+                                      end;
+                                  end;
+                                { If we reach this point, p and hp1 weren't actually modified,
+                                  so we can do a bit more work on this pass }
+                              end;
+                          end;
+                      end;
+                  end;
+              end;
+          end;
+
         GetNextInstruction_p:=GetNextInstruction(p, hp1);
 
         { All the next optimisations require a next instruction }
@@ -4447,74 +4538,6 @@ unit aoptx86;
               end;
 
               { mov x,reg1; mov y,reg1 -> mov y,reg1 is handled by the Mov2Nop 5 optimisation }
-
-            { Change:
-                movl %reg1,%reg2
-                movl x(%reg1),%reg1  (If something other than %reg1 is written to, DeepMOVOpt would have caught it)
-                movl x(%reg2),%regX  (%regX can be %reg2 or something else)
-              To:
-                movl %reg1,%reg2 (if %regX = %reg2, then remove this instruction)
-                movl x(%reg1),%reg1
-                movl %reg1,%regX
-            }
-            if MatchOpType(taicpu(p), top_reg, top_reg) then
-              begin
-                p_SourceReg := taicpu(p).oper[0]^.reg;
-                { Remember that p_TargetReg contains taicpu(p).oper[1]^.reg }
-
-                if (taicpu(hp1).oper[0]^.typ = top_ref) { The other operand will be a register } and
-                  (taicpu(hp1).oper[1]^.reg = p_SourceReg) and
-                  RegInRef(p_SourceReg, taicpu(hp1).oper[0]^.ref^) and
-                  GetNextInstruction(hp1, hp2) and
-                  MatchInstruction(hp2, A_MOV, [taicpu(p).opsize]) and
-                  (taicpu(hp2).oper[0]^.typ = top_ref) { The other operand will be a register } then
-                  begin
-                    SourceRef := taicpu(hp2).oper[0]^.ref^;
-                    if RegInRef(p_TargetReg, SourceRef) and
-                      { If %reg1 also appears in the second reference, then it will
-                        not refer to the same memory block as the first reference }
-                      not RegInRef(p_SourceReg, SourceRef) then
-                      begin
-                        { Check to see if the references match if %reg2 is changed to %reg1 }
-                        if SourceRef.base = p_TargetReg then
-                          SourceRef.base := p_SourceReg;
-
-                        if SourceRef.index = p_TargetReg then
-                          SourceRef.index := p_SourceReg;
-
-                        { RefsEqual also checks to ensure both references are non-volatile }
-                        if RefsEqual(taicpu(hp1).oper[0]^.ref^, SourceRef) then
-                          begin
-                            taicpu(hp2).loadreg(0, p_SourceReg);
-
-                            DebugMsg(SPeepholeOptimization + 'Optimised register duplication and memory read (MovMovMov2MovMovMov)', p);
-                            Result := True;
-                            if taicpu(hp2).oper[1]^.reg = p_TargetReg then
-                              begin
-                                DebugMsg(SPeepholeOptimization + 'Mov2Nop 5a done', p);
-                                RemoveCurrentP(p, hp1);
-                                Exit;
-                              end
-                            else
-                              begin
-                                { Check to see if %reg2 is no longer in use }
-                                TransferUsedRegs(TmpUsedRegs);
-                                UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
-                                UpdateUsedRegs(TmpUsedRegs, tai(hp1.Next));
-
-                                if not RegUsedAfterInstruction(p_TargetReg, hp2, TmpUsedRegs) then
-                                  begin
-                                    DebugMsg(SPeepholeOptimization + 'Mov2Nop 5b done', p);
-                                    RemoveCurrentP(p, hp1);
-                                    Exit;
-                                  end;
-                              end;
-                            { If we reach this point, p and hp1 weren't actually modified,
-                              so we can do a bit more work on this pass }
-                          end;
-                      end;
-                  end;
-              end;
           end;
 
         { search further than the next instruction for a mov (as long as it's not a jump) }