Quellcode durchsuchen

* moved InstructionLoadsFromReg and RegReadByInstruction from TCpuAsmOptimizer (i386) to TX86AsmOptimizer

git-svn-id: trunk@36200 -
florian vor 8 Jahren
Ursprung
Commit
f4a29bb75d
2 geänderte Dateien mit 218 neuen und 218 gelöschten Zeilen
  1. 0 218
      compiler/i386/aoptcpu.pas
  2. 218 0
      compiler/x86/aoptx86.pas

+ 0 - 218
compiler/i386/aoptcpu.pas

@@ -41,8 +41,6 @@ unit aoptcpu;
         procedure PeepHoleOptPass2; override;
         procedure PostPeepHoleOpts; override;
         function DoFpuLoadStoreOpt(var p : tai) : boolean;
-        function RegReadByInstruction(reg : TRegister; hp : tai) : boolean;
-        function InstructionLoadsFromReg(const reg : TRegister;const hp : tai) : boolean;override;
       end;
 
     Var
@@ -138,222 +136,6 @@ unit aoptcpu;
     end;
 
 
-  function TCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister;const hp: tai): boolean;
-    begin
-      Result:=RegReadByInstruction(reg,hp);
-    end;
-
-
-  function TCpuAsmOptimizer.RegReadByInstruction(reg: TRegister; hp: tai): boolean;
-    var
-      p: taicpu;
-      opcount: longint;
-    begin
-      RegReadByInstruction := false;
-      if hp.typ <> ait_instruction then
-        exit;
-      p := taicpu(hp);
-      case p.opcode of
-        A_CALL:
-          regreadbyinstruction := true;
-        A_IMUL:
-          case p.ops of
-            1:
-              regReadByInstruction := RegInOp(reg,p.oper[0]^) or
-                 (
-                  ((getregtype(reg)=R_INTREGISTER) and (getsupreg(reg)=RS_EAX)) and
-                  ((getsubreg(reg)<>R_SUBH) or (p.opsize<>S_B))
-                 );
-            2,3:
-              regReadByInstruction :=
-                reginop(reg,p.oper[0]^) or
-                reginop(reg,p.oper[1]^);
-          end;
-        A_MUL:
-          begin
-            regReadByInstruction := RegInOp(reg,p.oper[0]^) or
-               (
-                ((getregtype(reg)=R_INTREGISTER) and (getsupreg(reg)=RS_EAX)) and
-                ((getsubreg(reg)<>R_SUBH) or (p.opsize<>S_B))
-               );
-          end;
-        A_IDIV,A_DIV:
-          begin
-            regReadByInstruction := RegInOp(reg,p.oper[0]^) or
-               (
-                 (getregtype(reg)=R_INTREGISTER) and
-                 (
-                   (getsupreg(reg)=RS_EAX) or ((getsupreg(reg)=RS_EDX) and (p.opsize<>S_B))
-                 )
-               );
-          end;
-        else
-          begin
-            if (p.opcode=A_LEA) and is_segment_reg(reg) then
-              begin
-                RegReadByInstruction := false;
-                exit;
-              end;
-            for opcount := 0 to p.ops-1 do
-              if (p.oper[opCount]^.typ = top_ref) and
-                 RegInRef(reg,p.oper[opcount]^.ref^) then
-                begin
-                  RegReadByInstruction := true;
-                  exit
-                end;
-            { special handling for SSE MOVSD }
-            if (p.opcode=A_MOVSD) and (p.ops>0) then
-              begin
-                if p.ops<>2 then
-                  internalerror(2017042702);
-                regReadByInstruction := reginop(reg,p.oper[0]^) or
-                  (
-                   (p.oper[1]^.typ=top_reg) and (p.oper[0]^.typ=top_reg) and reginop(reg, p.oper[1]^)
-                  );
-                exit;
-              end;
-            with insprop[p.opcode] do
-              begin
-                if getregtype(reg)=R_INTREGISTER then
-                  begin
-                    case getsupreg(reg) of
-                      RS_EAX:
-                        if [Ch_REAX,Ch_RWEAX,Ch_MEAX]*Ch<>[] then
-                          begin
-                            RegReadByInstruction := true;
-                            exit
-                          end;
-                      RS_ECX:
-                        if [Ch_RECX,Ch_RWECX,Ch_MECX]*Ch<>[] then
-                          begin
-                            RegReadByInstruction := true;
-                            exit
-                          end;
-                      RS_EDX:
-                        if [Ch_REDX,Ch_RWEDX,Ch_MEDX]*Ch<>[] then
-                          begin
-                            RegReadByInstruction := true;
-                            exit
-                          end;
-                      RS_EBX:
-                        if [Ch_REBX,Ch_RWEBX,Ch_MEBX]*Ch<>[] then
-                          begin
-                            RegReadByInstruction := true;
-                            exit
-                          end;
-                      RS_ESP:
-                        if [Ch_RESP,Ch_RWESP,Ch_MESP]*Ch<>[] then
-                          begin
-                            RegReadByInstruction := true;
-                            exit
-                          end;
-                      RS_EBP:
-                        if [Ch_REBP,Ch_RWEBP,Ch_MEBP]*Ch<>[] then
-                          begin
-                            RegReadByInstruction := true;
-                            exit
-                          end;
-                      RS_ESI:
-                        if [Ch_RESI,Ch_RWESI,Ch_MESI]*Ch<>[] then
-                          begin
-                            RegReadByInstruction := true;
-                            exit
-                          end;
-                      RS_EDI:
-                        if [Ch_REDI,Ch_RWEDI,Ch_MEDI]*Ch<>[] then
-                          begin
-                            RegReadByInstruction := true;
-                            exit
-                          end;
-                    end;
-                  end;
-                if SuperRegistersEqual(reg,NR_DEFAULTFLAGS) then
-                  begin
-                    if (Ch_RFLAGScc in Ch) and not(getsubreg(reg) in [R_SUBW,R_SUBD,R_SUBQ]) then
-                      begin
-                        case p.condition of
-                          C_A,C_NBE,       { CF=0 and ZF=0  }
-                          C_BE,C_NA:       { CF=1 or ZF=1   }
-                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGCARRY,R_SUBFLAGZERO];
-                          C_AE,C_NB,C_NC,  { CF=0           }
-                          C_B,C_NAE,C_C:   { CF=1           }
-                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGCARRY];
-                          C_NE,C_NZ,       { ZF=0           }
-                          C_E,C_Z:         { ZF=1           }
-                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGZERO];
-                          C_G,C_NLE,       { ZF=0 and SF=OF }
-                          C_LE,C_NG:       { ZF=1 or SF<>OF }
-                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGZERO,R_SUBFLAGSIGN,R_SUBFLAGOVERFLOW];
-                          C_GE,C_NL,       { SF=OF          }
-                          C_L,C_NGE:       { SF<>OF         }
-                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGSIGN,R_SUBFLAGOVERFLOW];
-                          C_NO,            { OF=0           }
-                          C_O:             { OF=1           }
-                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGOVERFLOW];
-                          C_NP,C_PO,       { PF=0           }
-                          C_P,C_PE:        { PF=1           }
-                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGPARITY];
-                          C_NS,            { SF=0           }
-                          C_S:             { SF=1           }
-                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGSIGN];
-                          else
-                            internalerror(2017042701);
-                        end;
-                        if RegReadByInstruction then
-                          exit;
-                      end;
-                    case getsubreg(reg) of
-                      R_SUBW,R_SUBD,R_SUBQ:
-                        RegReadByInstruction :=
-                          [Ch_RCarryFlag,Ch_RParityFlag,Ch_RAuxiliaryFlag,Ch_RZeroFlag,Ch_RSignFlag,Ch_ROverflowFlag,
-                           Ch_RWCarryFlag,Ch_RWParityFlag,Ch_RWAuxiliaryFlag,Ch_RWZeroFlag,Ch_RWSignFlag,Ch_RWOverflowFlag,
-                           Ch_RDirFlag,Ch_RFlags,Ch_RWFlags,Ch_RFLAGScc]*Ch<>[];
-                      R_SUBFLAGCARRY:
-                        RegReadByInstruction:=[Ch_RCarryFlag,Ch_RWCarryFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
-                      R_SUBFLAGPARITY:
-                        RegReadByInstruction:=[Ch_RParityFlag,Ch_RWParityFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
-                      R_SUBFLAGAUXILIARY:
-                        RegReadByInstruction:=[Ch_RAuxiliaryFlag,Ch_RWAuxiliaryFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
-                      R_SUBFLAGZERO:
-                        RegReadByInstruction:=[Ch_RZeroFlag,Ch_RWZeroFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
-                      R_SUBFLAGSIGN:
-                        RegReadByInstruction:=[Ch_RSignFlag,Ch_RWSignFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
-                      R_SUBFLAGOVERFLOW:
-                        RegReadByInstruction:=[Ch_ROverflowFlag,Ch_RWOverflowFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
-                      R_SUBFLAGINTERRUPT:
-                        RegReadByInstruction:=[Ch_RFlags,Ch_RWFlags]*Ch<>[];
-                      R_SUBFLAGDIRECTION:
-                        RegReadByInstruction:=[Ch_RDirFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
-                      else
-                        internalerror(2017042601);
-                    end;
-                    exit;
-                  end;
-                if (Ch_NoReadIfEqualRegs in Ch) and (p.ops=2) and
-                   (p.oper[0]^.typ=top_reg) and (p.oper[1]^.typ=top_reg) and
-                   (p.oper[0]^.reg=p.oper[1]^.reg) then
-                  exit;
-                if ([CH_RWOP1,CH_ROP1,CH_MOP1]*Ch<>[]) and reginop(reg,p.oper[0]^) then
-                  begin
-                    RegReadByInstruction := true;
-                    exit
-                  end;
-                if ([Ch_RWOP2,Ch_ROP2,Ch_MOP2]*Ch<>[]) and reginop(reg,p.oper[1]^) then
-                  begin
-                    RegReadByInstruction := true;
-                    exit
-                  end;
-                if ([Ch_RWOP3,Ch_ROP3,Ch_MOP3]*Ch<>[]) and reginop(reg,p.oper[2]^) then
-                  begin
-                    RegReadByInstruction := true;
-                    exit
-                  end;
-              end;
-          end;
-      end;
-    end;
-
-
 { returns true if p contains a memory operand with a segment set }
 function InsContainsSegRef(p: taicpu): boolean;
 var

+ 218 - 0
compiler/x86/aoptx86.pas

@@ -37,6 +37,8 @@ unit aoptx86;
     type
       TX86AsmOptimizer = class(TAsmOptimizer)
         function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
+        function InstructionLoadsFromReg(const reg : TRegister; const hp : tai) : boolean; override;
+        function RegReadByInstruction(reg : TRegister; hp : tai) : boolean;
       protected
         { checks whether loading a new value in reg1 overwrites the entirety of reg2 }
         function Reg1WriteOverwritesReg2Entirely(reg1, reg2: tregister): boolean;
@@ -217,6 +219,222 @@ unit aoptx86;
       end;
 
 
+  function TX86AsmOptimizer.InstructionLoadsFromReg(const reg: TRegister;const hp: tai): boolean;
+    begin
+      Result:=RegReadByInstruction(reg,hp);
+    end;
+
+
+  function TX86AsmOptimizer.RegReadByInstruction(reg: TRegister; hp: tai): boolean;
+    var
+      p: taicpu;
+      opcount: longint;
+    begin
+      RegReadByInstruction := false;
+      if hp.typ <> ait_instruction then
+        exit;
+      p := taicpu(hp);
+      case p.opcode of
+        A_CALL:
+          regreadbyinstruction := true;
+        A_IMUL:
+          case p.ops of
+            1:
+              regReadByInstruction := RegInOp(reg,p.oper[0]^) or
+                 (
+                  ((getregtype(reg)=R_INTREGISTER) and (getsupreg(reg)=RS_EAX)) and
+                  ((getsubreg(reg)<>R_SUBH) or (p.opsize<>S_B))
+                 );
+            2,3:
+              regReadByInstruction :=
+                reginop(reg,p.oper[0]^) or
+                reginop(reg,p.oper[1]^);
+          end;
+        A_MUL:
+          begin
+            regReadByInstruction := RegInOp(reg,p.oper[0]^) or
+               (
+                ((getregtype(reg)=R_INTREGISTER) and (getsupreg(reg)=RS_EAX)) and
+                ((getsubreg(reg)<>R_SUBH) or (p.opsize<>S_B))
+               );
+          end;
+        A_IDIV,A_DIV:
+          begin
+            regReadByInstruction := RegInOp(reg,p.oper[0]^) or
+               (
+                 (getregtype(reg)=R_INTREGISTER) and
+                 (
+                   (getsupreg(reg)=RS_EAX) or ((getsupreg(reg)=RS_EDX) and (p.opsize<>S_B))
+                 )
+               );
+          end;
+        else
+          begin
+            if (p.opcode=A_LEA) and is_segment_reg(reg) then
+              begin
+                RegReadByInstruction := false;
+                exit;
+              end;
+            for opcount := 0 to p.ops-1 do
+              if (p.oper[opCount]^.typ = top_ref) and
+                 RegInRef(reg,p.oper[opcount]^.ref^) then
+                begin
+                  RegReadByInstruction := true;
+                  exit
+                end;
+            { special handling for SSE MOVSD }
+            if (p.opcode=A_MOVSD) and (p.ops>0) then
+              begin
+                if p.ops<>2 then
+                  internalerror(2017042702);
+                regReadByInstruction := reginop(reg,p.oper[0]^) or
+                  (
+                   (p.oper[1]^.typ=top_reg) and (p.oper[0]^.typ=top_reg) and reginop(reg, p.oper[1]^)
+                  );
+                exit;
+              end;
+            with insprop[p.opcode] do
+              begin
+                if getregtype(reg)=R_INTREGISTER then
+                  begin
+                    case getsupreg(reg) of
+                      RS_EAX:
+                        if [Ch_REAX,Ch_RWEAX,Ch_MEAX]*Ch<>[] then
+                          begin
+                            RegReadByInstruction := true;
+                            exit
+                          end;
+                      RS_ECX:
+                        if [Ch_RECX,Ch_RWECX,Ch_MECX]*Ch<>[] then
+                          begin
+                            RegReadByInstruction := true;
+                            exit
+                          end;
+                      RS_EDX:
+                        if [Ch_REDX,Ch_RWEDX,Ch_MEDX]*Ch<>[] then
+                          begin
+                            RegReadByInstruction := true;
+                            exit
+                          end;
+                      RS_EBX:
+                        if [Ch_REBX,Ch_RWEBX,Ch_MEBX]*Ch<>[] then
+                          begin
+                            RegReadByInstruction := true;
+                            exit
+                          end;
+                      RS_ESP:
+                        if [Ch_RESP,Ch_RWESP,Ch_MESP]*Ch<>[] then
+                          begin
+                            RegReadByInstruction := true;
+                            exit
+                          end;
+                      RS_EBP:
+                        if [Ch_REBP,Ch_RWEBP,Ch_MEBP]*Ch<>[] then
+                          begin
+                            RegReadByInstruction := true;
+                            exit
+                          end;
+                      RS_ESI:
+                        if [Ch_RESI,Ch_RWESI,Ch_MESI]*Ch<>[] then
+                          begin
+                            RegReadByInstruction := true;
+                            exit
+                          end;
+                      RS_EDI:
+                        if [Ch_REDI,Ch_RWEDI,Ch_MEDI]*Ch<>[] then
+                          begin
+                            RegReadByInstruction := true;
+                            exit
+                          end;
+                    end;
+                  end;
+                if SuperRegistersEqual(reg,NR_DEFAULTFLAGS) then
+                  begin
+                    if (Ch_RFLAGScc in Ch) and not(getsubreg(reg) in [R_SUBW,R_SUBD,R_SUBQ]) then
+                      begin
+                        case p.condition of
+                          C_A,C_NBE,       { CF=0 and ZF=0  }
+                          C_BE,C_NA:       { CF=1 or ZF=1   }
+                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGCARRY,R_SUBFLAGZERO];
+                          C_AE,C_NB,C_NC,  { CF=0           }
+                          C_B,C_NAE,C_C:   { CF=1           }
+                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGCARRY];
+                          C_NE,C_NZ,       { ZF=0           }
+                          C_E,C_Z:         { ZF=1           }
+                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGZERO];
+                          C_G,C_NLE,       { ZF=0 and SF=OF }
+                          C_LE,C_NG:       { ZF=1 or SF<>OF }
+                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGZERO,R_SUBFLAGSIGN,R_SUBFLAGOVERFLOW];
+                          C_GE,C_NL,       { SF=OF          }
+                          C_L,C_NGE:       { SF<>OF         }
+                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGSIGN,R_SUBFLAGOVERFLOW];
+                          C_NO,            { OF=0           }
+                          C_O:             { OF=1           }
+                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGOVERFLOW];
+                          C_NP,C_PO,       { PF=0           }
+                          C_P,C_PE:        { PF=1           }
+                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGPARITY];
+                          C_NS,            { SF=0           }
+                          C_S:             { SF=1           }
+                            RegReadByInstruction:=getsubreg(reg) in [R_SUBFLAGSIGN];
+                          else
+                            internalerror(2017042701);
+                        end;
+                        if RegReadByInstruction then
+                          exit;
+                      end;
+                    case getsubreg(reg) of
+                      R_SUBW,R_SUBD,R_SUBQ:
+                        RegReadByInstruction :=
+                          [Ch_RCarryFlag,Ch_RParityFlag,Ch_RAuxiliaryFlag,Ch_RZeroFlag,Ch_RSignFlag,Ch_ROverflowFlag,
+                           Ch_RWCarryFlag,Ch_RWParityFlag,Ch_RWAuxiliaryFlag,Ch_RWZeroFlag,Ch_RWSignFlag,Ch_RWOverflowFlag,
+                           Ch_RDirFlag,Ch_RFlags,Ch_RWFlags,Ch_RFLAGScc]*Ch<>[];
+                      R_SUBFLAGCARRY:
+                        RegReadByInstruction:=[Ch_RCarryFlag,Ch_RWCarryFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
+                      R_SUBFLAGPARITY:
+                        RegReadByInstruction:=[Ch_RParityFlag,Ch_RWParityFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
+                      R_SUBFLAGAUXILIARY:
+                        RegReadByInstruction:=[Ch_RAuxiliaryFlag,Ch_RWAuxiliaryFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
+                      R_SUBFLAGZERO:
+                        RegReadByInstruction:=[Ch_RZeroFlag,Ch_RWZeroFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
+                      R_SUBFLAGSIGN:
+                        RegReadByInstruction:=[Ch_RSignFlag,Ch_RWSignFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
+                      R_SUBFLAGOVERFLOW:
+                        RegReadByInstruction:=[Ch_ROverflowFlag,Ch_RWOverflowFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
+                      R_SUBFLAGINTERRUPT:
+                        RegReadByInstruction:=[Ch_RFlags,Ch_RWFlags]*Ch<>[];
+                      R_SUBFLAGDIRECTION:
+                        RegReadByInstruction:=[Ch_RDirFlag,Ch_RFlags,Ch_RWFlags]*Ch<>[];
+                      else
+                        internalerror(2017042601);
+                    end;
+                    exit;
+                  end;
+                if (Ch_NoReadIfEqualRegs in Ch) and (p.ops=2) and
+                   (p.oper[0]^.typ=top_reg) and (p.oper[1]^.typ=top_reg) and
+                   (p.oper[0]^.reg=p.oper[1]^.reg) then
+                  exit;
+                if ([CH_RWOP1,CH_ROP1,CH_MOP1]*Ch<>[]) and reginop(reg,p.oper[0]^) then
+                  begin
+                    RegReadByInstruction := true;
+                    exit
+                  end;
+                if ([Ch_RWOP2,Ch_ROP2,Ch_MOP2]*Ch<>[]) and reginop(reg,p.oper[1]^) then
+                  begin
+                    RegReadByInstruction := true;
+                    exit
+                  end;
+                if ([Ch_RWOP3,Ch_ROP3,Ch_MOP3]*Ch<>[]) and reginop(reg,p.oper[2]^) then
+                  begin
+                    RegReadByInstruction := true;
+                    exit
+                  end;
+              end;
+          end;
+      end;
+    end;
+
+
 {$ifdef DEBUG_AOPTCPU}
     procedure TX86AsmOptimizer.DebugMsg(const s: string;p : tai);
       begin