Explorar el Código

* changed LdiCp2Cpi into LdiMov/Cp2Ldi/Cpi and improved it

git-svn-id: trunk@34920 -
florian hace 8 años
padre
commit
0520d246d0
Se han modificado 1 ficheros con 118 adiciones y 32 borrados
  1. 118 32
      compiler/avr/aoptcpu.pas

+ 118 - 32
compiler/avr/aoptcpu.pas

@@ -30,7 +30,7 @@ Unit aoptcpu;
 
 Interface
 
-uses cpubase, cgbase, aasmtai, aopt, aoptcpub;
+uses cpubase, cgbase, aasmtai, aopt,AoptObj, aoptcpub;
 
 Type
   TCpuAsmOptimizer = class(TAsmOptimizer)
@@ -39,6 +39,8 @@ Type
 
     Function GetNextInstructionUsingReg(Current: tai; Var Next: tai;reg : TRegister): Boolean;
     function RegInInstruction(Reg: TRegister; p1: tai): Boolean; override;
+    function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
+    function InstructionLoadsFromReg(const reg : TRegister; const hp : tai) : boolean; override;
 
     { uses the same constructor as TAopObj }
     function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
@@ -49,6 +51,7 @@ Implementation
 
   uses
     cutils,
+    verbose,
     cpuinfo,
     aasmbase,aasmcpu,aasmdata,
     globals,globtype,
@@ -114,6 +117,22 @@ Implementation
     end;
 
 
+  function MatchInstruction(const instr: tai; const ops: TAsmOpSet;opcount : byte): boolean;
+    begin
+      result :=
+        (instr.typ = ait_instruction) and
+        (taicpu(instr).opcode in ops) and
+        (taicpu(instr).ops=opcount);
+    end;
+
+
+  function MatchOpType(const instr : tai;ot0,ot1 : toptype) : Boolean;
+    begin
+      Result:=(taicpu(instr).ops=2) and
+        (taicpu(instr).oper[0]^.typ=ot0) and
+        (taicpu(instr).oper[1]^.typ=ot1);
+    end;
+
 {$ifdef DEBUG_AOPTCPU}
   procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
     begin
@@ -147,12 +166,72 @@ Implementation
     end;
 
 
+  function TCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
+    var
+      p: taicpu;
+    begin
+      if not assigned(hp) or
+         (hp.typ <> ait_instruction) then
+       begin
+         Result := false;
+         exit;
+       end;
+      p := taicpu(hp);
+      Result := ((p.opcode in [A_LDI,A_MOV,A_LDS]) and (reg=p.oper[0]^.reg) and ((p.oper[1]^.typ<>top_reg) or (reg<>p.oper[0]^.reg))) or
+        ((p.opcode in [A_LD,A_LDD,A_LPM]) and (reg=p.oper[0]^.reg) and not(RegInRef(reg,p.oper[1]^.ref^))) or
+        ((p.opcode in [A_MOVW]) and ((reg=p.oper[0]^.reg) or (TRegister(ord(reg)+1)=p.oper[0]^.reg)) and not(reg=p.oper[1]^.reg) and not(TRegister(ord(reg)+1)=p.oper[1]^.reg)) or
+        ((p.opcode in [A_POP]) and (reg=p.oper[0]^.reg));
+    end;
+
+
+  function TCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
+    var
+      p: taicpu;
+      i: longint;
+    begin
+      Result := false;
+
+      if not (assigned(hp) and (hp.typ = ait_instruction)) then
+        exit;
+      p:=taicpu(hp);
+
+      i:=0;
+
+      { we do not care about the stack pointer }
+      if p.opcode in [A_POP] then
+        exit;
+
+      { first operand only written?
+        then skip it }
+      if p.opcode in [A_MOV,A_LD,A_LDD,A_LDS,A_LPM,A_LDI,A_MOVW] then
+        i:=1;
+
+      while(i<p.ops) do
+        begin
+          case p.oper[I]^.typ of
+            top_reg:
+              Result := (p.oper[I]^.reg = reg) or
+                { MOVW }
+                ((i=1) and (p.opcode=A_MOVW) and (getsupreg(p.oper[0]^.reg)+1=getsupreg(reg)));
+            top_ref:
+              Result :=
+                (p.oper[I]^.ref^.base = reg) or
+                (p.oper[I]^.ref^.index = reg);
+          end;
+          { Bailout if we found something }
+          if Result then
+            exit;
+          Inc(I);
+        end;
+    end;
+
   function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
     var
       hp1,hp2,hp3,hp4,hp5: tai;
       alloc, dealloc: tai_regalloc;
       i: integer;
       l: TAsmLabel;
+      TmpUsedRegs : TAllUsedRegs;
     begin
       result := false;
       case p.typ of
@@ -228,46 +307,53 @@ Implementation
                   begin
                     { turn
                       ldi reg0, imm
-                      cp reg1, reg0
+                      cp/mov reg1, reg0
                       dealloc reg0
                       into
-                      cpi reg1, imm
+                      cpi/ldi reg1, imm
                     }
-                    if (taicpu(p).ops=2) and
-                       (taicpu(p).oper[0]^.typ=top_reg) and
-                       (taicpu(p).oper[1]^.typ=top_const) and
+                    if MatchOpType(p,top_reg,top_const) and
                        GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
-                       (hp1.typ=ait_instruction) and
+                       MatchInstruction(hp1,[A_CP,A_MOV],2) and
                        (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
-                       (taicpu(hp1).opcode=A_CP) and
-                       (taicpu(hp1).ops=2) and
-                       (taicpu(hp1).oper[1]^.typ=top_reg) and
+                       MatchOpType(hp1,top_reg,top_reg) and
                        (getsupreg(taicpu(hp1).oper[0]^.reg) in [16..31]) and
-                       (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
-                       assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
+                       (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) then
                       begin
-                        taicpu(hp1).opcode:=A_CPI;
-                        taicpu(hp1).loadconst(1, taicpu(p).oper[1]^.val);
-
-                        alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
-                        dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
-
-                        if assigned(alloc) and assigned(dealloc) then
+                        CopyUsedRegs(TmpUsedRegs);
+                        if not(RegUsedAfterInstruction(taicpu(hp1).oper[1]^.reg, hp1, TmpUsedRegs)) then
                           begin
-                            asml.Remove(alloc);
-                            alloc.Free;
-                            asml.Remove(dealloc);
-                            dealloc.Free;
-                          end;
-
-                        DebugMsg('Peephole LdiCp2Cpi performed', p);
+                            case taicpu(hp1).opcode of
+                              A_CP:
+                                taicpu(hp1).opcode:=A_CPI;
+                              A_MOV:
+                                taicpu(hp1).opcode:=A_LDI;
+                              else
+                                internalerror(2016111901);
+                            end;
+                            taicpu(hp1).loadconst(1, taicpu(p).oper[1]^.val);
+
+                            alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
+                            dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
+
+                            if assigned(alloc) and assigned(dealloc) then
+                              begin
+                                asml.Remove(alloc);
+                                alloc.Free;
+                                asml.Remove(dealloc);
+                                dealloc.Free;
+                              end;
+
+                            DebugMsg('Peephole LdiMov/Cp2Ldi/Cpi performed', p);
+
+                            GetNextInstruction(p,hp1);
+                            asml.Remove(p);
+                            p.Free;
+                            p:=hp1;
 
-                        GetNextInstruction(p,hp1);
-                        asml.Remove(p);
-                        p.Free;
-                        p:=hp1;
-
-                        result:=true;
+                            result:=true;
+                          end;
+                        ReleaseUsedRegs(TmpUsedRegs);
                       end;
                   end;
                 A_STS: