Sfoglia il codice sorgente

* AVR: second part of assembler optimizer rework

git-svn-id: trunk@49378 -
florian 4 anni fa
parent
commit
430b2fd791
1 ha cambiato i file con 709 aggiunte e 633 eliminazioni
  1. 709 633
      compiler/avr/aoptcpu.pas

+ 709 - 633
compiler/avr/aoptcpu.pas

@@ -48,11 +48,20 @@ Type
     function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
     procedure PeepHoleOptPass2;override;
   private
+   function OptPass1ADD(var p : tai) : boolean;
+   function OptPass1ANDI(var p : tai) : boolean;
+   function OptPass1CALL(var p : tai) : boolean;
+   function OptPass1CLR(var p : tai) : boolean;
    function OptPass1IN(var p : tai) : boolean;
     function OptPass1LDI(var p : tai) : boolean;
     function OptPass1LDS(var p : tai) : boolean;
+    function OptPass1MOV(var p : tai) : boolean;
+    function OptPass1PUSH(var p : tai) : boolean;
+    function OptPass1RCALL(var p : tai) : boolean;
+    function OptPass1SBI(var p : tai) : boolean;
     function OptPass1SBR(var p : tai) : boolean;
     function OptPass1STS(var p : tai) : boolean;
+    function OptPass1SUB(var p : tai) : boolean;
   End;
 
 Implementation
@@ -566,12 +575,699 @@ Implementation
     end;
 
 
-  function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+  function TCpuAsmOptimizer.OptPass1SBI(var p : tai) : boolean;
+    var
+      hp1, hp2, hp3, hp4, hp5: tai;
+    begin
+      Result:=false;
+      {
+        Turn
+            sbic/sbis X, y
+            jmp .L1
+            op
+          .L1:
+
+        into
+            sbis/sbic X,y
+            op
+          .L1:
+      }
+      if InvertSkipInstruction(p) then
+        result:=true
+      {
+        Turn
+            sbiX X, y
+            jmp .L1
+            jmp .L2
+          .L1:
+            op
+          .L2:
+
+        into
+            sbiX X,y
+          .L1:
+            op
+          .L2:
+      }
+      else if GetNextInstruction(p, hp1) and
+         (hp1.typ=ait_instruction) and
+         (taicpu(hp1).opcode in [A_JMP,A_RJMP]) and
+         (taicpu(hp1).ops>0) and
+         (taicpu(hp1).oper[0]^.typ = top_ref) and
+         (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) and
+
+         GetNextInstruction(hp1, hp2) and
+         (hp2.typ=ait_instruction) and
+         (taicpu(hp2).opcode in [A_JMP,A_RJMP]) and
+         (taicpu(hp2).ops>0) and
+         (taicpu(hp2).oper[0]^.typ = top_ref) and
+         (taicpu(hp2).oper[0]^.ref^.symbol is TAsmLabel) and
+
+         GetNextInstruction(hp2, hp3) and
+         (hp3.typ=ait_label) and
+         (taicpu(hp1).oper[0]^.ref^.symbol=tai_label(hp3).labsym) and
+
+         GetNextInstruction(hp3, hp4) and
+         (hp4.typ=ait_instruction) and
+
+         GetNextInstruction(hp4, hp5) and
+         (hp3.typ=ait_label) and
+         (taicpu(hp2).oper[0]^.ref^.symbol=tai_label(hp5).labsym) then
+        begin
+          DebugMsg('Peephole SbiJmpJmp2Sbi performed',p);
+
+          tai_label(hp3).labsym.decrefs;
+          tai_label(hp5).labsym.decrefs;
+
+          AsmL.remove(hp1);
+          taicpu(hp1).Free;
+
+          AsmL.remove(hp2);
+          taicpu(hp2).Free;
+
+          result:=true;
+        end;
+    end;
+
+
+  function TCpuAsmOptimizer.OptPass1ANDI(var p : tai) : boolean;
+    var
+      hp1, hp2, hp3: tai;
+      i : longint;
+    begin
+      Result:=false;
+      {
+        Turn
+            andi rx, #pow2
+            brne l
+            <op>
+          l:
+        Into
+            sbrs rx, #(1 shl imm)
+            <op>
+          l:
+      }
+      if (taicpu(p).ops=2) and
+         (taicpu(p).oper[1]^.typ=top_const) and
+         ispowerof2(taicpu(p).oper[1]^.val,i) and
+         assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(p.next))) and
+         GetNextInstruction(p,hp1) and
+         (hp1.typ=ait_instruction) and
+         (taicpu(hp1).opcode=A_BRxx) and
+         (taicpu(hp1).condition in [C_EQ,C_NE]) and
+         (taicpu(hp1).ops>0) and
+         (taicpu(hp1).oper[0]^.typ = top_ref) and
+         (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) and
+         GetNextInstruction(hp1,hp2) and
+         (hp2.typ=ait_instruction) and
+         GetNextInstruction(hp2,hp3) and
+         (hp3.typ=ait_label) and
+         (taicpu(hp1).oper[0]^.ref^.symbol=tai_label(hp3).labsym) then
+        begin
+          DebugMsg('Peephole AndiBr2Sbr performed', p);
+
+          taicpu(p).oper[1]^.val:=i;
+
+          if taicpu(hp1).condition=C_NE then
+            taicpu(p).opcode:=A_SBRS
+          else
+            taicpu(p).opcode:=A_SBRC;
+
+          asml.Remove(hp1);
+          hp1.free;
+
+          result:=true;
+        end
+      {
+        Remove
+          andi rx, #y
+          dealloc rx
+      }
+      else if (taicpu(p).ops=2) and
+         (taicpu(p).oper[0]^.typ=top_reg) and
+         assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(p.next))) and
+         (assigned(FindRegDeAlloc(NR_DEFAULTFLAGS,tai(p.Next))) or
+          (not RegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs))) then
+        begin
+          DebugMsg('Redundant Andi removed', p);
+
+          result:=RemoveCurrentP(p);
+        end;
+    end;
+
+
+  function TCpuAsmOptimizer.OptPass1ADD(var p : tai) : boolean;
+    var
+      hp1: tai;
+    begin
+      Result:=false;
+      if (taicpu(p).oper[1]^.reg=GetDefaultZeroReg) and
+      GetNextInstruction(p, hp1) and
+      MatchInstruction(hp1,A_ADC) then
+      begin
+        DebugMsg('Peephole AddAdc2Add performed', p);
+
+        RemoveCurrentP(p, hp1);
+        Result := True;
+      end;
+    end;
+
+
+  function TCpuAsmOptimizer.OptPass1SUB(var p : tai) : boolean;
+    var
+      hp1: tai;
+    begin
+      Result:=false;
+      if (taicpu(p).oper[1]^.reg=GetDefaultZeroReg) and
+      GetNextInstruction(p, hp1) and
+      MatchInstruction(hp1,A_SBC) then
+      begin
+        DebugMsg('Peephole SubSbc2Sub performed', p);
+
+        taicpu(hp1).opcode:=A_SUB;
+
+        RemoveCurrentP(p, hp1);
+        Result := True;
+      end;
+    end;
+
+
+  function TCpuAsmOptimizer.OptPass1CLR(var p : tai) : boolean;
+    var
+      hp1: tai;
+      alloc, dealloc: tai_regalloc;
+    begin
+      Result:=false;
+      { turn the common
+        clr rX
+        mov/ld rX, rY
+        into
+        mov/ld rX, rY
+      }
+      if (taicpu(p).ops=1) and
+         (taicpu(p).oper[0]^.typ=top_reg) and
+         GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+         (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
+         (hp1.typ=ait_instruction) and
+         (taicpu(hp1).opcode in [A_MOV,A_LD]) and
+         (taicpu(hp1).ops>0) and
+         (taicpu(hp1).oper[0]^.typ=top_reg) and
+         (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
+        begin
+          DebugMsg('Peephole ClrMov2Mov performed', p);
+
+          result:=RemoveCurrentP(p);
+        end
+      { turn
+        clr rX
+        ...
+        adc rY, rX
+        into
+        ...
+        adc rY, r1
+      }
+      else if (taicpu(p).ops=1) and
+         (taicpu(p).oper[0]^.typ=top_reg) and
+         GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+         (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
+         (hp1.typ=ait_instruction) and
+         (taicpu(hp1).opcode in [A_ADC,A_SBC]) and
+         (taicpu(hp1).ops=2) and
+         (taicpu(hp1).oper[1]^.typ=top_reg) and
+         (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
+         (taicpu(hp1).oper[0]^.reg<>taicpu(p).oper[0]^.reg) and
+         assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
+        begin
+          DebugMsg('Peephole ClrAdc2Adc performed', p);
+
+          taicpu(hp1).oper[1]^.reg:=GetDefaultZeroReg;
+
+          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;
+
+          result:=RemoveCurrentP(p);
+        end;
+    end;
+
+
+  function TCpuAsmOptimizer.OptPass1PUSH(var p : tai) : boolean;
+    var
+      hp1, hp2, hp3: tai;
+    begin
+      Result:=false;
+      { turn
+        push reg0
+        push reg1
+        pop reg3
+        pop reg2
+
+        into
+
+        movw reg2,reg0
+
+        or
+
+        mov  reg3,reg1
+        mov  reg2,reg0
+
+      }
+      if GetNextInstruction(p,hp1) and
+         MatchInstruction(hp1,A_PUSH) and
+
+         GetNextInstruction(hp1,hp2) and
+         MatchInstruction(hp2,A_POP) and
+
+         GetNextInstruction(hp2,hp3) and
+         MatchInstruction(hp3,A_POP) then
+        begin
+         if (CPUAVR_HAS_MOVW in cpu_capabilities[current_settings.cputype]) and
+           (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
+           ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
+           (getsupreg(taicpu(hp2).oper[0]^.reg)=getsupreg(taicpu(hp3).oper[0]^.reg)+1) and
+           ((getsupreg(taicpu(hp3).oper[0]^.reg) mod 2)=0) then
+           begin
+             DebugMsg('Peephole PushPushPopPop2Movw performed', p);
+
+             taicpu(hp3).ops:=2;
+             taicpu(hp3).opcode:=A_MOVW;
+
+             taicpu(hp3).loadreg(1, taicpu(p).oper[0]^.reg);
+
+             { We're removing 3 concurrent instructions.  Remove hp1
+               and hp2 manually instead of calling RemoveCurrentP
+               as this means we won't be calling UpdateUsedRegs 3 times }
+             asml.Remove(hp1);
+             hp1.Free;
+
+             asml.Remove(hp2);
+             hp2.Free;
+
+             { By removing p last, we've guaranteed that p.Next is
+               valid (storing it prior to removing the instructions
+               may result in a dangling pointer if hp1 immediately
+               follows p), and because hp1, hp2 and hp3 came from
+               sequential calls to GetNextInstruction, it is
+               guaranteed that UpdateUsedRegs will stop at hp3. [Kit] }
+             RemoveCurrentP(p, hp3);
+             Result := True;
+           end
+         else
+           begin
+             DebugMsg('Peephole PushPushPopPop2MovMov performed', p);
+
+             taicpu(p).ops:=2;
+             taicpu(p).opcode:=A_MOV;
+
+             taicpu(hp1).ops:=2;
+             taicpu(hp1).opcode:=A_MOV;
+
+             taicpu(p).loadreg(1, taicpu(p).oper[0]^.reg);
+             taicpu(p).loadreg(0, taicpu(hp3).oper[0]^.reg);
+
+             taicpu(hp1).loadreg(1, taicpu(hp1).oper[0]^.reg);
+             taicpu(hp1).loadreg(0, taicpu(hp2).oper[0]^.reg);
+
+             { life range of reg2 and reg3 is increased, fix register allocation entries }
+             TransferUsedRegs(TmpUsedRegs);
+             UpdateUsedRegs(TmpUsedRegs,tai(p.Next));
+             AllocRegBetween(taicpu(hp2).oper[0]^.reg,hp1,hp2,TmpUsedRegs);
+
+             TransferUsedRegs(TmpUsedRegs);
+             AllocRegBetween(taicpu(hp3).oper[0]^.reg,p,hp3,TmpUsedRegs);
+
+             IncludeRegInUsedRegs(taicpu(hp3).oper[0]^.reg,UsedRegs);
+             UpdateUsedRegs(tai(p.Next));
+
+             asml.Remove(hp2);
+             hp2.Free;
+             asml.Remove(hp3);
+             hp3.Free;
+
+             result:=true;
+           end
+
+        end;
+    end;
+
+
+  function TCpuAsmOptimizer.OptPass1CALL(var p : tai) : boolean;
+    var
+      hp1: tai;
+    begin
+      Result:=false;
+      if (cs_opt_level4 in current_settings.optimizerswitches) and
+        GetNextInstruction(p,hp1) and
+        MatchInstruction(hp1,A_RET) then
+        begin
+           DebugMsg('Peephole CallReg2Jmp performed', p);
+
+           taicpu(p).opcode:=A_JMP;
+
+           asml.Remove(hp1);
+           hp1.Free;
+
+           result:=true;
+        end;
+    end;
+
+
+  function TCpuAsmOptimizer.OptPass1RCALL(var p : tai) : boolean;
     var
-      hp1,hp2,hp3,hp4,hp5: tai;
+      hp1: tai;
+    begin
+      Result:=false;
+      if (cs_opt_level4 in current_settings.optimizerswitches) and
+        GetNextInstruction(p,hp1) and
+        MatchInstruction(hp1,A_RET) then
+        begin
+           DebugMsg('Peephole RCallReg2RJmp performed', p);
+
+           taicpu(p).opcode:=A_RJMP;
+
+           asml.Remove(hp1);
+           hp1.Free;
+
+           result:=true;
+        end;
+    end;
+
+
+  function TCpuAsmOptimizer.OptPass1MOV(var p : tai) : boolean;
+    var
+      hp1, hp2: tai;
+      i : Integer;
       alloc, dealloc: tai_regalloc;
-      i: integer;
-      l: TAsmLabel;
+    begin
+      Result:=false;
+      { change
+        mov reg0, reg1
+        dealloc reg0
+        into
+        dealloc reg0
+      }
+      if MatchOpType(taicpu(p),top_reg,top_reg) then
+        begin
+          TransferUsedRegs(TmpUsedRegs);
+          UpdateUsedRegs(TmpUsedRegs,tai(p.Next));
+          if not(RegInUsedRegs(taicpu(p).oper[0]^.reg,TmpUsedRegs)) and
+            { reg. allocation information before calls is not perfect, so don't do this before
+              calls/icalls }
+            GetNextInstruction(p,hp1) and
+            not(MatchInstruction(hp1,[A_CALL,A_RCALL])) then
+            begin
+              DebugMsg('Peephole Mov2Nop performed', p);
+              RemoveCurrentP(p, hp1);
+              Result := True;
+              exit;
+            end;
+        end;
+
+      { turn
+        mov reg0, reg1
+        <op> reg2,reg0
+        dealloc reg0
+        into
+        <op> reg2,reg1
+      }
+      if MatchOpType(taicpu(p),top_reg,top_reg) and
+         GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+         (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p, hp1)) and
+         (MatchInstruction(hp1,[A_PUSH,A_MOV,A_CP,A_CPC,A_ADD,A_SUB,A_ADC,A_SBC,A_EOR,A_AND,A_OR,
+                                 A_OUT,A_IN]) or
+         { the reference register of ST/STD cannot be replaced }
+         (MatchInstruction(hp1,[A_STD,A_ST,A_STS]) and (MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^)))) and
+         (not RegModifiedByInstruction(taicpu(p).oper[0]^.reg, hp1)) and
+         {(taicpu(hp1).ops=1) and
+         (taicpu(hp1).oper[0]^.typ = top_reg) and
+         (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and  }
+         assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
+        begin
+          DebugMsg('Peephole MovOp2Op 1 performed', p);
+
+          for i := 0 to taicpu(hp1).ops-1 do
+            if taicpu(hp1).oper[i]^.typ=top_reg then
+              if taicpu(hp1).oper[i]^.reg=taicpu(p).oper[0]^.reg then
+                taicpu(hp1).oper[i]^.reg:=taicpu(p).oper[1]^.reg;
+
+          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;
+
+          { life range of reg1 is increased }
+          AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,usedregs);
+          { p will be removed, update used register as we continue
+            with the next instruction after p }
+
+          result:=RemoveCurrentP(p);
+        end
+      { turn
+        mov reg1, reg0
+        <op> reg1,xxxx
+        dealloc reg1
+        into
+        <op> reg1,xxx
+      }
+      else if MatchOpType(taicpu(p),top_reg,top_reg) and
+         GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+         not(RegModifiedBetween(taicpu(p).oper[1]^.reg, p, hp1)) and
+         MatchInstruction(hp1,[A_CP,A_CPC,A_CPI,A_SBRS,A_SBRC]) and
+         assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
+        begin
+          DebugMsg('Peephole MovOp2Op 2 performed', p);
+
+          for i := 0 to taicpu(hp1).ops-1 do
+            if taicpu(hp1).oper[i]^.typ=top_reg then
+              if taicpu(hp1).oper[i]^.reg=taicpu(p).oper[0]^.reg then
+                taicpu(hp1).oper[i]^.reg:=taicpu(p).oper[1]^.reg;
+
+          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;
+
+          { life range of reg1 is increased }
+          AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,usedregs);
+          { p will be removed, update used register as we continue
+            with the next instruction after p }
+
+          result:=RemoveCurrentP(p);
+        end
+      { remove
+        mov reg0,reg0
+      }
+      else if (taicpu(p).ops=2) and
+         (taicpu(p).oper[0]^.typ = top_reg) and
+         (taicpu(p).oper[1]^.typ = top_reg) and
+         (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+        begin
+          DebugMsg('Peephole RedundantMov performed', p);
+
+          result:=RemoveCurrentP(p);
+        end
+      {
+        Turn
+          mov rx,ry
+          op rx,rz
+          mov ry, rx
+        Into
+          op ry,rz
+      }
+      else if (taicpu(p).ops=2) and
+         MatchOpType(taicpu(p),top_reg,top_reg) and
+         GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+         (hp1.typ=ait_instruction) and
+         (taicpu(hp1).ops >= 1) and
+         (taicpu(hp1).oper[0]^.typ = top_reg) and
+         GetNextInstructionUsingReg(hp1,hp2,taicpu(hp1).oper[0]^.reg) and
+         MatchInstruction(hp2,A_MOV) and
+         MatchOpType(taicpu(hp2),top_reg,top_reg) and
+         (taicpu(hp2).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
+         (taicpu(hp2).oper[1]^.reg = taicpu(hp1).oper[0]^.reg) and
+         (taicpu(hp2).oper[1]^.reg = taicpu(p).oper[0]^.reg) and
+         (not RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp2)) and
+         (taicpu(hp1).opcode in [A_ADD,A_ADC,A_SUB,A_SBC,A_AND,A_OR,A_EOR,
+                                 A_INC,A_DEC,
+                                 A_LSL,A_LSR,A_ASR,A_ROR,A_ROL]) and
+         assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg, tai(hp2.Next))) then
+        begin
+          DebugMsg('Peephole MovOpMov2Op performed', p);
+
+          if (taicpu(hp1).ops=2) and
+             (taicpu(hp1).oper[1]^.typ=top_reg) and
+             (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+            taicpu(hp1).oper[1]^.reg:=taicpu(p).oper[1]^.reg;
+
+          taicpu(hp1).oper[0]^.reg:=taicpu(p).oper[1]^.reg;
+
+          alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
+          dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp2.Next));
+
+          if assigned(alloc) and assigned(dealloc) then
+            begin
+              asml.Remove(alloc);
+              alloc.Free;
+              asml.Remove(dealloc);
+              dealloc.Free;
+            end;
+
+          asml.remove(hp2);
+          hp2.free;
+
+          result:=RemoveCurrentP(p);
+        end
+      {
+        Turn
+          mov rx,ry
+          op  rx,rw
+          mov rw,rx
+        Into
+          op rw,ry
+      }
+      else if (taicpu(p).ops=2) and
+         MatchOpType(taicpu(p),top_reg,top_reg) and
+         GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+         (hp1.typ=ait_instruction) and
+         (taicpu(hp1).ops = 2) and
+         MatchOpType(taicpu(hp1),top_reg,top_reg) and
+         GetNextInstructionUsingReg(hp1,hp2,taicpu(hp1).oper[0]^.reg) and
+         (hp2.typ=ait_instruction) and
+         (taicpu(hp2).opcode=A_MOV) and
+         MatchOpType(taicpu(hp2),top_reg,top_reg) and
+         (taicpu(hp2).oper[0]^.reg = taicpu(hp1).oper[1]^.reg) and
+         (taicpu(hp2).oper[1]^.reg = taicpu(hp1).oper[0]^.reg) and
+         (taicpu(hp2).oper[1]^.reg = taicpu(p).oper[0]^.reg) and
+         (not RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) and
+         (taicpu(hp1).opcode in [A_ADD,A_ADC,A_AND,A_OR,A_EOR]) and
+         assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg, tai(hp2.Next))) then
+        begin
+          DebugMsg('Peephole MovOpMov2Op2 performed', p);
+
+          taicpu(hp1).oper[0]^.reg:=taicpu(hp2).oper[0]^.reg;
+          taicpu(hp1).oper[1]^.reg:=taicpu(p).oper[1]^.reg;
+
+          alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
+          dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp2.Next));
+
+          if assigned(alloc) and assigned(dealloc) then
+            begin
+              asml.Remove(alloc);
+              alloc.Free;
+              asml.Remove(dealloc);
+              dealloc.Free;
+            end;
+
+          result:=RemoveCurrentP(p);
+
+          asml.remove(hp2);
+          hp2.free;
+        end
+      { fold
+        mov reg2,reg0
+        mov reg3,reg1
+        to
+        movw reg2,reg0
+      }
+      else if (CPUAVR_HAS_MOVW in cpu_capabilities[current_settings.cputype]) and
+         (taicpu(p).ops=2) and
+         (taicpu(p).oper[0]^.typ = top_reg) and
+         (taicpu(p).oper[1]^.typ = top_reg) and
+         getnextinstruction(p,hp1) and
+         (hp1.typ = ait_instruction) and
+         (taicpu(hp1).opcode = A_MOV) and
+         (taicpu(hp1).ops=2) and
+         (taicpu(hp1).oper[0]^.typ = top_reg) and
+         (taicpu(hp1).oper[1]^.typ = top_reg) and
+         (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
+         ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
+         ((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and
+         (getsupreg(taicpu(hp1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
+        begin
+          DebugMsg('Peephole MovMov2Movw performed', p);
+
+          alloc:=FindRegAllocBackward(taicpu(hp1).oper[0]^.reg,tai(hp1.Previous));
+          if assigned(alloc) then
+            begin
+              asml.Remove(alloc);
+              asml.InsertBefore(alloc,p);
+              { proper book keeping of currently used registers }
+              IncludeRegInUsedRegs(taicpu(hp1).oper[0]^.reg,UsedRegs);
+            end;
+
+          taicpu(p).opcode:=A_MOVW;
+          asml.remove(hp1);
+          hp1.free;
+          result:=true;
+        end
+      {
+        This removes the first mov from
+        mov rX,...
+        mov rX,...
+      }
+      else if GetNextInstruction(p,hp1) and MatchInstruction(hp1,A_MOV) and
+        { test condition here already instead in the while loop only, else MovMov2Mov 2 might be oversight }
+        MatchInstruction(hp1,A_MOV) and
+        MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^) then
+        while MatchInstruction(hp1,A_MOV) and
+              MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^) and
+              { don't remove the first mov if the second is a mov rX,rX }
+              not(MatchOperand(taicpu(hp1).oper[0]^,taicpu(hp1).oper[1]^)) do
+          begin
+            DebugMsg('Peephole MovMov2Mov 1 performed', p);
+
+            RemoveCurrentP(p,hp1);
+            Result := True;
+
+            GetNextInstruction(hp1,hp1);
+            if not assigned(hp1) then
+              break;
+          end
+      {
+        This removes the second mov from
+        mov rX,rY
+
+        ...
+
+        mov rX,rY
+
+        if rX and rY are not modified in-between
+      }
+      else if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[1]^.reg) and
+        MatchInstruction(hp1,A_MOV) and
+        MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^) and
+        MatchOperand(taicpu(p).oper[1]^, taicpu(hp1).oper[1]^) and
+        not(RegModifiedBetween(taicpu(p).oper[0]^.reg,p,hp1)) then
+        begin
+          DebugMsg('Peephole MovMov2Mov 2 performed', p);
+          AllocRegBetween(taicpu(p).oper[0]^.reg,p,hp1,UsedRegs);
+          RemoveInstruction(hp1);
+          Result := True;
+        end;
+    end;
+
+  function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+    var
+      hp1,hp2: tai;
     begin
       result := false;
       case p.typ of
@@ -659,644 +1355,24 @@ Implementation
                 A_SBRC:
                   Result:=OptPass1SBR(p);
                 A_ANDI:
-                  begin
-                    {
-                      Turn
-                          andi rx, #pow2
-                          brne l
-                          <op>
-                        l:
-                      Into
-                          sbrs rx, #(1 shl imm)
-                          <op>
-                        l:
-                    }
-                    if (taicpu(p).ops=2) and
-                       (taicpu(p).oper[1]^.typ=top_const) and
-                       ispowerof2(taicpu(p).oper[1]^.val,i) and
-                       assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(p.next))) and
-                       GetNextInstruction(p,hp1) and
-                       (hp1.typ=ait_instruction) and
-                       (taicpu(hp1).opcode=A_BRxx) and
-                       (taicpu(hp1).condition in [C_EQ,C_NE]) and
-                       (taicpu(hp1).ops>0) and
-                       (taicpu(hp1).oper[0]^.typ = top_ref) and
-                       (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) and
-                       GetNextInstruction(hp1,hp2) and
-                       (hp2.typ=ait_instruction) and
-                       GetNextInstruction(hp2,hp3) and
-                       (hp3.typ=ait_label) and
-                       (taicpu(hp1).oper[0]^.ref^.symbol=tai_label(hp3).labsym) then
-                      begin
-                        DebugMsg('Peephole AndiBr2Sbr performed', p);
-
-                        taicpu(p).oper[1]^.val:=i;
-
-                        if taicpu(hp1).condition=C_NE then
-                          taicpu(p).opcode:=A_SBRS
-                        else
-                          taicpu(p).opcode:=A_SBRC;
-
-                        asml.Remove(hp1);
-                        hp1.free;
-
-                        result:=true;
-                      end
-                    {
-                      Remove
-                        andi rx, #y
-                        dealloc rx
-                    }
-                    else if (taicpu(p).ops=2) and
-                       (taicpu(p).oper[0]^.typ=top_reg) and
-                       assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(p.next))) and
-                       (assigned(FindRegDeAlloc(NR_DEFAULTFLAGS,tai(p.Next))) or
-                        (not RegInUsedRegs(NR_DEFAULTFLAGS,UsedRegs))) then
-                      begin
-                        DebugMsg('Redundant Andi removed', p);
-
-                        result:=RemoveCurrentP(p);
-                      end;
-                  end;
+                  Result:=OptPass1ANDI(p);
                 A_ADD:
-                  begin
-                    if (taicpu(p).oper[1]^.reg=GetDefaultZeroReg) and
-                    GetNextInstruction(p, hp1) and
-                    MatchInstruction(hp1,A_ADC) then
-                    begin
-                      DebugMsg('Peephole AddAdc2Add performed', p);
-
-                      RemoveCurrentP(p, hp1);
-                      Result := True;
-                    end;
-                  end;
+                  Result:=OptPass1ADD(p);
                 A_SUB:
-                  begin
-                    if (taicpu(p).oper[1]^.reg=GetDefaultZeroReg) and
-                    GetNextInstruction(p, hp1) and
-                    MatchInstruction(hp1,A_SBC) then
-                    begin
-                      DebugMsg('Peephole SubSbc2Sub performed', p);
-
-                      taicpu(hp1).opcode:=A_SUB;
-
-                      RemoveCurrentP(p, hp1);
-                      Result := True;
-                    end;
-                  end;
+                  Result:=OptPass1SUB(p);
                 A_CLR:
-                  begin
-                    { turn the common
-                      clr rX
-                      mov/ld rX, rY
-                      into
-                      mov/ld rX, rY
-                    }
-                    if (taicpu(p).ops=1) and
-                       (taicpu(p).oper[0]^.typ=top_reg) and
-                       GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
-                       (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
-                       (hp1.typ=ait_instruction) and
-                       (taicpu(hp1).opcode in [A_MOV,A_LD]) and
-                       (taicpu(hp1).ops>0) and
-                       (taicpu(hp1).oper[0]^.typ=top_reg) and
-                       (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
-                      begin
-                        DebugMsg('Peephole ClrMov2Mov performed', p);
-
-                        result:=RemoveCurrentP(p);
-                      end
-                    { turn
-                      clr rX
-                      ...
-                      adc rY, rX
-                      into
-                      ...
-                      adc rY, r1
-                    }
-                    else if (taicpu(p).ops=1) and
-                       (taicpu(p).oper[0]^.typ=top_reg) and
-                       GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
-                       (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
-                       (hp1.typ=ait_instruction) and
-                       (taicpu(hp1).opcode in [A_ADC,A_SBC]) and
-                       (taicpu(hp1).ops=2) and
-                       (taicpu(hp1).oper[1]^.typ=top_reg) and
-                       (taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
-                       (taicpu(hp1).oper[0]^.reg<>taicpu(p).oper[0]^.reg) and
-                       assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
-                      begin
-                        DebugMsg('Peephole ClrAdc2Adc performed', p);
-
-                        taicpu(hp1).oper[1]^.reg:=GetDefaultZeroReg;
-
-                        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;
-
-                        result:=RemoveCurrentP(p);
-                      end;
-                  end;
+                  Result:=OptPass1CLR(p);
                 A_PUSH:
-                  begin
-                    { turn
-                      push reg0
-                      push reg1
-                      pop reg3
-                      pop reg2
-
-                      into
-
-                      movw reg2,reg0
-
-                      or
-
-                      mov  reg3,reg1
-                      mov  reg2,reg0
-
-                    }
-                    if GetNextInstruction(p,hp1) and
-                       MatchInstruction(hp1,A_PUSH) and
-
-                       GetNextInstruction(hp1,hp2) and
-                       MatchInstruction(hp2,A_POP) and
-
-                       GetNextInstruction(hp2,hp3) and
-                       MatchInstruction(hp3,A_POP) then
-                      begin
-                       if (CPUAVR_HAS_MOVW in cpu_capabilities[current_settings.cputype]) and
-                         (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
-                         ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
-                         (getsupreg(taicpu(hp2).oper[0]^.reg)=getsupreg(taicpu(hp3).oper[0]^.reg)+1) and
-                         ((getsupreg(taicpu(hp3).oper[0]^.reg) mod 2)=0) then
-                         begin
-                           DebugMsg('Peephole PushPushPopPop2Movw performed', p);
-
-                           taicpu(hp3).ops:=2;
-                           taicpu(hp3).opcode:=A_MOVW;
-
-                           taicpu(hp3).loadreg(1, taicpu(p).oper[0]^.reg);
-
-                           { We're removing 3 concurrent instructions.  Remove hp1
-                             and hp2 manually instead of calling RemoveCurrentP
-                             as this means we won't be calling UpdateUsedRegs 3 times }
-                           asml.Remove(hp1);
-                           hp1.Free;
-
-                           asml.Remove(hp2);
-                           hp2.Free;
-
-                           { By removing p last, we've guaranteed that p.Next is
-                             valid (storing it prior to removing the instructions
-                             may result in a dangling pointer if hp1 immediately
-                             follows p), and because hp1, hp2 and hp3 came from
-                             sequential calls to GetNextInstruction, it is
-                             guaranteed that UpdateUsedRegs will stop at hp3. [Kit] }
-                           RemoveCurrentP(p, hp3);
-                           Result := True;
-                         end
-                       else
-                         begin
-                           DebugMsg('Peephole PushPushPopPop2MovMov performed', p);
-
-                           taicpu(p).ops:=2;
-                           taicpu(p).opcode:=A_MOV;
-
-                           taicpu(hp1).ops:=2;
-                           taicpu(hp1).opcode:=A_MOV;
-
-                           taicpu(p).loadreg(1, taicpu(p).oper[0]^.reg);
-                           taicpu(p).loadreg(0, taicpu(hp3).oper[0]^.reg);
-
-                           taicpu(hp1).loadreg(1, taicpu(hp1).oper[0]^.reg);
-                           taicpu(hp1).loadreg(0, taicpu(hp2).oper[0]^.reg);
-
-                           { life range of reg2 and reg3 is increased, fix register allocation entries }
-                           TransferUsedRegs(TmpUsedRegs);
-                           UpdateUsedRegs(TmpUsedRegs,tai(p.Next));
-                           AllocRegBetween(taicpu(hp2).oper[0]^.reg,hp1,hp2,TmpUsedRegs);
-
-                           TransferUsedRegs(TmpUsedRegs);
-                           AllocRegBetween(taicpu(hp3).oper[0]^.reg,p,hp3,TmpUsedRegs);
-
-                           IncludeRegInUsedRegs(taicpu(hp3).oper[0]^.reg,UsedRegs);
-                           UpdateUsedRegs(tai(p.Next));
-
-                           asml.Remove(hp2);
-                           hp2.Free;
-                           asml.Remove(hp3);
-                           hp3.Free;
-
-                           result:=true;
-                         end
-
-                      end;
-                  end;
+                  Result:=OptPass1PUSH(p);
                 A_CALL:
-                  if (cs_opt_level4 in current_settings.optimizerswitches) and
-                    GetNextInstruction(p,hp1) and
-                    MatchInstruction(hp1,A_RET) then
-                    begin
-                       DebugMsg('Peephole CallReg2Jmp performed', p);
-
-                       taicpu(p).opcode:=A_JMP;
-
-                       asml.Remove(hp1);
-                       hp1.Free;
-
-                       result:=true;
-                    end;
+                  Result:=OptPass1CALL(p);
                 A_RCALL:
-                  if (cs_opt_level4 in current_settings.optimizerswitches) and
-                    GetNextInstruction(p,hp1) and
-                    MatchInstruction(hp1,A_RET) then
-                    begin
-                       DebugMsg('Peephole RCallReg2RJmp performed', p);
-
-                       taicpu(p).opcode:=A_RJMP;
-
-                       asml.Remove(hp1);
-                       hp1.Free;
-
-                       result:=true;
-                    end;
+                  Result:=OptPass1RCALL(p);
                 A_MOV:
-                  begin
-                    { change
-                      mov reg0, reg1
-                      dealloc reg0
-                      into
-                      dealloc reg0
-                    }
-                    if MatchOpType(taicpu(p),top_reg,top_reg) then
-                      begin
-                        TransferUsedRegs(TmpUsedRegs);
-                        UpdateUsedRegs(TmpUsedRegs,tai(p.Next));
-                        if not(RegInUsedRegs(taicpu(p).oper[0]^.reg,TmpUsedRegs)) and
-                          { reg. allocation information before calls is not perfect, so don't do this before
-                            calls/icalls }
-                          GetNextInstruction(p,hp1) and
-                          not(MatchInstruction(hp1,[A_CALL,A_RCALL])) then
-                          begin
-                            DebugMsg('Peephole Mov2Nop performed', p);
-                            RemoveCurrentP(p, hp1);
-                            Result := True;
-                            exit;
-                          end;
-                      end;
-
-                    { turn
-                      mov reg0, reg1
-                      <op> reg2,reg0
-                      dealloc reg0
-                      into
-                      <op> reg2,reg1
-                    }
-                    if MatchOpType(taicpu(p),top_reg,top_reg) and
-                       GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
-                       (not RegModifiedBetween(taicpu(p).oper[1]^.reg, p, hp1)) and
-                       (MatchInstruction(hp1,[A_PUSH,A_MOV,A_CP,A_CPC,A_ADD,A_SUB,A_ADC,A_SBC,A_EOR,A_AND,A_OR,
-                                               A_OUT,A_IN]) or
-                       { the reference register of ST/STD cannot be replaced }
-                       (MatchInstruction(hp1,[A_STD,A_ST,A_STS]) and (MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^)))) and
-                       (not RegModifiedByInstruction(taicpu(p).oper[0]^.reg, hp1)) and
-                       {(taicpu(hp1).ops=1) and
-                       (taicpu(hp1).oper[0]^.typ = top_reg) and
-                       (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and  }
-                       assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
-                      begin
-                        DebugMsg('Peephole MovOp2Op 1 performed', p);
-
-                        for i := 0 to taicpu(hp1).ops-1 do
-                          if taicpu(hp1).oper[i]^.typ=top_reg then
-                            if taicpu(hp1).oper[i]^.reg=taicpu(p).oper[0]^.reg then
-                              taicpu(hp1).oper[i]^.reg:=taicpu(p).oper[1]^.reg;
-
-                        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;
-
-                        { life range of reg1 is increased }
-                        AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,usedregs);
-                        { p will be removed, update used register as we continue
-                          with the next instruction after p }
-
-                        result:=RemoveCurrentP(p);
-                      end
-                    { turn
-                      mov reg1, reg0
-                      <op> reg1,xxxx
-                      dealloc reg1
-                      into
-                      <op> reg1,xxx
-                    }
-                    else if MatchOpType(taicpu(p),top_reg,top_reg) and
-                       GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
-                       not(RegModifiedBetween(taicpu(p).oper[1]^.reg, p, hp1)) and
-                       MatchInstruction(hp1,[A_CP,A_CPC,A_CPI,A_SBRS,A_SBRC]) and
-                       assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
-                      begin
-                        DebugMsg('Peephole MovOp2Op 2 performed', p);
-
-                        for i := 0 to taicpu(hp1).ops-1 do
-                          if taicpu(hp1).oper[i]^.typ=top_reg then
-                            if taicpu(hp1).oper[i]^.reg=taicpu(p).oper[0]^.reg then
-                              taicpu(hp1).oper[i]^.reg:=taicpu(p).oper[1]^.reg;
-
-                        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;
-
-                        { life range of reg1 is increased }
-                        AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,usedregs);
-                        { p will be removed, update used register as we continue
-                          with the next instruction after p }
-
-                        result:=RemoveCurrentP(p);
-                      end
-                    { remove
-                      mov reg0,reg0
-                    }
-                    else if (taicpu(p).ops=2) and
-                       (taicpu(p).oper[0]^.typ = top_reg) and
-                       (taicpu(p).oper[1]^.typ = top_reg) and
-                       (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
-                      begin
-                        DebugMsg('Peephole RedundantMov performed', p);
-
-                        result:=RemoveCurrentP(p);
-                      end
-                    {
-                      Turn
-                        mov rx,ry
-                        op rx,rz
-                        mov ry, rx
-                      Into
-                        op ry,rz
-                    }
-                    else if (taicpu(p).ops=2) and
-                       MatchOpType(taicpu(p),top_reg,top_reg) and
-                       GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
-                       (hp1.typ=ait_instruction) and
-                       (taicpu(hp1).ops >= 1) and
-                       (taicpu(hp1).oper[0]^.typ = top_reg) and
-                       GetNextInstructionUsingReg(hp1,hp2,taicpu(hp1).oper[0]^.reg) and
-                       MatchInstruction(hp2,A_MOV) and
-                       MatchOpType(taicpu(hp2),top_reg,top_reg) and
-                       (taicpu(hp2).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
-                       (taicpu(hp2).oper[1]^.reg = taicpu(hp1).oper[0]^.reg) and
-                       (taicpu(hp2).oper[1]^.reg = taicpu(p).oper[0]^.reg) and
-                       (not RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp2)) and
-                       (taicpu(hp1).opcode in [A_ADD,A_ADC,A_SUB,A_SBC,A_AND,A_OR,A_EOR,
-                                               A_INC,A_DEC,
-                                               A_LSL,A_LSR,A_ASR,A_ROR,A_ROL]) and
-                       assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg, tai(hp2.Next))) then
-                      begin
-                        DebugMsg('Peephole MovOpMov2Op performed', p);
-
-                        if (taicpu(hp1).ops=2) and
-                           (taicpu(hp1).oper[1]^.typ=top_reg) and
-                           (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
-                          taicpu(hp1).oper[1]^.reg:=taicpu(p).oper[1]^.reg;
-
-                        taicpu(hp1).oper[0]^.reg:=taicpu(p).oper[1]^.reg;
-
-                        alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
-                        dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp2.Next));
-
-                        if assigned(alloc) and assigned(dealloc) then
-                          begin
-                            asml.Remove(alloc);
-                            alloc.Free;
-                            asml.Remove(dealloc);
-                            dealloc.Free;
-                          end;
-
-                        asml.remove(hp2);
-                        hp2.free;
-
-                        result:=RemoveCurrentP(p);
-                      end
-                    {
-                      Turn
-                        mov rx,ry
-                        op  rx,rw
-                        mov rw,rx
-                      Into
-                        op rw,ry
-                    }
-                    else if (taicpu(p).ops=2) and
-                       MatchOpType(taicpu(p),top_reg,top_reg) and
-                       GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
-                       (hp1.typ=ait_instruction) and
-                       (taicpu(hp1).ops = 2) and
-                       MatchOpType(taicpu(hp1),top_reg,top_reg) and
-                       GetNextInstructionUsingReg(hp1,hp2,taicpu(hp1).oper[0]^.reg) and
-                       (hp2.typ=ait_instruction) and
-                       (taicpu(hp2).opcode=A_MOV) and
-                       MatchOpType(taicpu(hp2),top_reg,top_reg) and
-                       (taicpu(hp2).oper[0]^.reg = taicpu(hp1).oper[1]^.reg) and
-                       (taicpu(hp2).oper[1]^.reg = taicpu(hp1).oper[0]^.reg) and
-                       (taicpu(hp2).oper[1]^.reg = taicpu(p).oper[0]^.reg) and
-                       (not RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) and
-                       (taicpu(hp1).opcode in [A_ADD,A_ADC,A_AND,A_OR,A_EOR]) and
-                       assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg, tai(hp2.Next))) then
-                      begin
-                        DebugMsg('Peephole MovOpMov2Op2 performed', p);
-
-                        taicpu(hp1).oper[0]^.reg:=taicpu(hp2).oper[0]^.reg;
-                        taicpu(hp1).oper[1]^.reg:=taicpu(p).oper[1]^.reg;
-
-                        alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
-                        dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp2.Next));
-
-                        if assigned(alloc) and assigned(dealloc) then
-                          begin
-                            asml.Remove(alloc);
-                            alloc.Free;
-                            asml.Remove(dealloc);
-                            dealloc.Free;
-                          end;
-
-                        result:=RemoveCurrentP(p);
-
-                        asml.remove(hp2);
-                        hp2.free;
-                      end
-                    { fold
-                      mov reg2,reg0
-                      mov reg3,reg1
-                      to
-                      movw reg2,reg0
-                    }
-                    else if (CPUAVR_HAS_MOVW in cpu_capabilities[current_settings.cputype]) and
-                       (taicpu(p).ops=2) and
-                       (taicpu(p).oper[0]^.typ = top_reg) and
-                       (taicpu(p).oper[1]^.typ = top_reg) and
-                       getnextinstruction(p,hp1) and
-                       (hp1.typ = ait_instruction) and
-                       (taicpu(hp1).opcode = A_MOV) and
-                       (taicpu(hp1).ops=2) and
-                       (taicpu(hp1).oper[0]^.typ = top_reg) and
-                       (taicpu(hp1).oper[1]^.typ = top_reg) and
-                       (getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
-                       ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
-                       ((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and
-                       (getsupreg(taicpu(hp1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
-                      begin
-                        DebugMsg('Peephole MovMov2Movw performed', p);
-
-                        alloc:=FindRegAllocBackward(taicpu(hp1).oper[0]^.reg,tai(hp1.Previous));
-                        if assigned(alloc) then
-                          begin
-                            asml.Remove(alloc);
-                            asml.InsertBefore(alloc,p);
-                            { proper book keeping of currently used registers }
-                            IncludeRegInUsedRegs(taicpu(hp1).oper[0]^.reg,UsedRegs);
-                          end;
-
-                        taicpu(p).opcode:=A_MOVW;
-                        asml.remove(hp1);
-                        hp1.free;
-                        result:=true;
-                      end
-                    {
-                      This removes the first mov from
-                      mov rX,...
-                      mov rX,...
-                    }
-                    else if GetNextInstruction(p,hp1) and MatchInstruction(hp1,A_MOV) and
-                      { test condition here already instead in the while loop only, else MovMov2Mov 2 might be oversight }
-                      MatchInstruction(hp1,A_MOV) and
-                      MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^) then
-                      while MatchInstruction(hp1,A_MOV) and
-                            MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^) and
-                            { don't remove the first mov if the second is a mov rX,rX }
-                            not(MatchOperand(taicpu(hp1).oper[0]^,taicpu(hp1).oper[1]^)) do
-                        begin
-                          DebugMsg('Peephole MovMov2Mov 1 performed', p);
-
-                          RemoveCurrentP(p,hp1);
-                          Result := True;
-
-                          GetNextInstruction(hp1,hp1);
-                          if not assigned(hp1) then
-                            break;
-                        end
-                    {
-                      This removes the second mov from
-                      mov rX,rY
-
-                      ...
-
-                      mov rX,rY
-
-                      if rX and rY are not modified in-between
-                    }
-                    else if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[1]^.reg) and
-                      MatchInstruction(hp1,A_MOV) and
-                      MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^) and
-                      MatchOperand(taicpu(p).oper[1]^, taicpu(hp1).oper[1]^) and
-                      not(RegModifiedBetween(taicpu(p).oper[0]^.reg,p,hp1)) then
-                      begin
-                        DebugMsg('Peephole MovMov2Mov 2 performed', p);
-                        AllocRegBetween(taicpu(p).oper[0]^.reg,p,hp1,UsedRegs);
-                        RemoveInstruction(hp1);
-                        Result := True;
-                      end;
-                  end;
+                  Result:=OptPass1MOV(p);
                 A_SBIC,
                 A_SBIS:
-                  begin
-                    {
-                      Turn
-                          sbic/sbis X, y
-                          jmp .L1
-                          op
-                        .L1:
-
-                      into
-                          sbis/sbic X,y
-                          op
-                        .L1:
-                    }
-                    if InvertSkipInstruction(p) then
-                      result:=true
-                    {
-                      Turn
-                          sbiX X, y
-                          jmp .L1
-                          jmp .L2
-                        .L1:
-                          op
-                        .L2:
-
-                      into
-                          sbiX X,y
-                        .L1:
-                          op
-                        .L2:
-                    }
-                    else if GetNextInstruction(p, hp1) and
-                       (hp1.typ=ait_instruction) and
-                       (taicpu(hp1).opcode in [A_JMP,A_RJMP]) and
-                       (taicpu(hp1).ops>0) and
-                       (taicpu(hp1).oper[0]^.typ = top_ref) and
-                       (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) and
-
-                       GetNextInstruction(hp1, hp2) and
-                       (hp2.typ=ait_instruction) and
-                       (taicpu(hp2).opcode in [A_JMP,A_RJMP]) and
-                       (taicpu(hp2).ops>0) and
-                       (taicpu(hp2).oper[0]^.typ = top_ref) and
-                       (taicpu(hp2).oper[0]^.ref^.symbol is TAsmLabel) and
-
-                       GetNextInstruction(hp2, hp3) and
-                       (hp3.typ=ait_label) and
-                       (taicpu(hp1).oper[0]^.ref^.symbol=tai_label(hp3).labsym) and
-
-                       GetNextInstruction(hp3, hp4) and
-                       (hp4.typ=ait_instruction) and
-
-                       GetNextInstruction(hp4, hp5) and
-                       (hp3.typ=ait_label) and
-                       (taicpu(hp2).oper[0]^.ref^.symbol=tai_label(hp5).labsym) then
-                      begin
-                        DebugMsg('Peephole SbiJmpJmp2Sbi performed',p);
-
-                        tai_label(hp3).labsym.decrefs;
-                        tai_label(hp5).labsym.decrefs;
-
-                        AsmL.remove(hp1);
-                        taicpu(hp1).Free;
-
-                        AsmL.remove(hp2);
-                        taicpu(hp2).Free;
-
-                        result:=true;
-                      end;
-                  end;
+                  Result:=OptPass1SBI(p);
               end;
           end;
       end;