|
@@ -47,6 +47,21 @@ Type
|
|
{ uses the same constructor as TAopObj }
|
|
{ uses the same constructor as TAopObj }
|
|
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
|
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
|
procedure PeepHoleOptPass2;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;
|
|
End;
|
|
|
|
|
|
Implementation
|
|
Implementation
|
|
@@ -291,12 +306,968 @@ Implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
- function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
|
|
|
|
|
|
+ function TCpuAsmOptimizer.OptPass1LDI(var p : tai) : boolean;
|
|
|
|
+ var
|
|
|
|
+ hp1 : tai;
|
|
|
|
+ alloc ,dealloc: tai_regalloc;
|
|
|
|
+ begin
|
|
|
|
+ Result:=false;
|
|
|
|
+ { turn
|
|
|
|
+ ldi reg0, imm
|
|
|
|
+ <op> reg1, reg0
|
|
|
|
+ dealloc reg0
|
|
|
|
+ into
|
|
|
|
+ <op>i reg1, imm
|
|
|
|
+ }
|
|
|
|
+ if MatchOpType(taicpu(p),top_reg,top_const) and
|
|
|
|
+ GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
|
|
|
+ MatchInstruction(hp1,[A_CP,A_MOV,A_AND,A_SUB],2) and
|
|
|
|
+ (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
|
|
|
|
+ MatchOpType(taicpu(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
|
|
|
|
+ not(MatchOperand(taicpu(hp1).oper[0]^,taicpu(hp1).oper[1]^)) then
|
|
|
|
+ begin
|
|
|
|
+ TransferUsedRegs(TmpUsedRegs);
|
|
|
|
+ UpdateUsedRegs(TmpUsedRegs,tai(p.next));
|
|
|
|
+ UpdateUsedRegs(TmpUsedRegs,tai(hp1.next));
|
|
|
|
+ if not(RegUsedAfterInstruction(taicpu(hp1).oper[1]^.reg, hp1, TmpUsedRegs)) then
|
|
|
|
+ begin
|
|
|
|
+ case taicpu(hp1).opcode of
|
|
|
|
+ A_CP:
|
|
|
|
+ taicpu(hp1).opcode:=A_CPI;
|
|
|
|
+ A_MOV:
|
|
|
|
+ taicpu(hp1).opcode:=A_LDI;
|
|
|
|
+ A_AND:
|
|
|
|
+ taicpu(hp1).opcode:=A_ANDI;
|
|
|
|
+ A_SUB:
|
|
|
|
+ taicpu(hp1).opcode:=A_SUBI;
|
|
|
|
+ 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 LdiOp2Opi performed', p);
|
|
|
|
+
|
|
|
|
+ result:=RemoveCurrentP(p);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ function TCpuAsmOptimizer.OptPass1STS(var p : tai) : boolean;
|
|
|
|
+ begin
|
|
|
|
+ Result:=false;
|
|
|
|
+ if (taicpu(p).oper[0]^.ref^.symbol=nil) and
|
|
|
|
+ (taicpu(p).oper[0]^.ref^.relsymbol=nil) and
|
|
|
|
+ (getsupreg(taicpu(p).oper[0]^.ref^.base)=RS_NO) and
|
|
|
|
+ (getsupreg(taicpu(p).oper[0]^.ref^.index)=RS_NO) and
|
|
|
|
+ (taicpu(p).oper[0]^.ref^.addressmode=AM_UNCHANGED) and
|
|
|
|
+ (((CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
|
+ (taicpu(p).oper[0]^.ref^.offset>=0) and
|
|
|
|
+ (taicpu(p).oper[0]^.ref^.offset<=63)) or
|
|
|
|
+ (not(CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
|
+ (taicpu(p).oper[0]^.ref^.offset>=32) and
|
|
|
|
+ (taicpu(p).oper[0]^.ref^.offset<=95))) then
|
|
|
|
+ begin
|
|
|
|
+ DebugMsg('Peephole Sts2Out performed', p);
|
|
|
|
+
|
|
|
|
+ taicpu(p).opcode:=A_OUT;
|
|
|
|
+ if CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype] then
|
|
|
|
+ taicpu(p).loadconst(0,taicpu(p).oper[0]^.ref^.offset)
|
|
|
|
+ else
|
|
|
|
+ taicpu(p).loadconst(0,taicpu(p).oper[0]^.ref^.offset-32);
|
|
|
|
+ result:=true;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ function TCpuAsmOptimizer.OptPass1LDS(var p : tai) : boolean;
|
|
|
|
+ begin
|
|
|
|
+ Result:=false;
|
|
|
|
+ if (taicpu(p).oper[1]^.ref^.symbol=nil) and
|
|
|
|
+ (taicpu(p).oper[1]^.ref^.relsymbol=nil) and
|
|
|
|
+ (getsupreg(taicpu(p).oper[1]^.ref^.base)=RS_NO) and
|
|
|
|
+ (getsupreg(taicpu(p).oper[1]^.ref^.index)=RS_NO) and
|
|
|
|
+ (taicpu(p).oper[1]^.ref^.addressmode=AM_UNCHANGED) and
|
|
|
|
+ (((CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
|
+ (taicpu(p).oper[1]^.ref^.offset>=0) and
|
|
|
|
+ (taicpu(p).oper[1]^.ref^.offset<=63)) or
|
|
|
|
+ (not(CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
|
+ (taicpu(p).oper[1]^.ref^.offset>=32) and
|
|
|
|
+ (taicpu(p).oper[1]^.ref^.offset<=95))) then
|
|
|
|
+ begin
|
|
|
|
+ DebugMsg('Peephole Lds2In performed', p);
|
|
|
|
+
|
|
|
|
+ taicpu(p).opcode:=A_IN;
|
|
|
|
+ if CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype] then
|
|
|
|
+ taicpu(p).loadconst(1,taicpu(p).oper[1]^.ref^.offset)
|
|
|
|
+ else
|
|
|
|
+ taicpu(p).loadconst(1,taicpu(p).oper[1]^.ref^.offset-32);
|
|
|
|
+
|
|
|
|
+ result:=true;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ function TCpuAsmOptimizer.OptPass1IN(var p : tai) : boolean;
|
|
|
|
+ var
|
|
|
|
+ hp1, hp2: tai;
|
|
|
|
+ l : TAsmLabel;
|
|
|
|
+ begin
|
|
|
|
+ Result:=false;
|
|
|
|
+ if GetNextInstruction(p,hp1) then
|
|
|
|
+ begin
|
|
|
|
+ {
|
|
|
|
+ in rX,Y
|
|
|
|
+ ori rX,n
|
|
|
|
+ out Y,rX
|
|
|
|
+
|
|
|
|
+ into
|
|
|
|
+ sbi rX,lg(n)
|
|
|
|
+ }
|
|
|
|
+ if (taicpu(p).oper[1]^.val<=31) and
|
|
|
|
+ MatchInstruction(hp1,A_ORI) and
|
|
|
|
+ (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
|
|
|
|
+ (PopCnt(byte(taicpu(hp1).oper[1]^.val))=1) and
|
|
|
|
+ GetNextInstruction(hp1,hp2) and
|
|
|
|
+ MatchInstruction(hp2,A_OUT) and
|
|
|
|
+ MatchOperand(taicpu(hp2).oper[1]^,taicpu(p).oper[0]^) and
|
|
|
|
+ MatchOperand(taicpu(hp2).oper[0]^,taicpu(p).oper[1]^) then
|
|
|
|
+ begin
|
|
|
|
+ DebugMsg('Peephole InOriOut2Sbi performed', p);
|
|
|
|
+
|
|
|
|
+ taicpu(p).opcode:=A_SBI;
|
|
|
|
+ taicpu(p).loadconst(0,taicpu(p).oper[1]^.val);
|
|
|
|
+ taicpu(p).loadconst(1,BsrByte(taicpu(hp1).oper[1]^.val));
|
|
|
|
+ asml.Remove(hp1);
|
|
|
|
+ hp1.Free;
|
|
|
|
+ asml.Remove(hp2);
|
|
|
|
+ hp2.Free;
|
|
|
|
+ result:=true;
|
|
|
|
+ end
|
|
|
|
+ {
|
|
|
|
+ in rX,Y
|
|
|
|
+ andi rX,not(n)
|
|
|
|
+ out Y,rX
|
|
|
|
+
|
|
|
|
+ into
|
|
|
|
+ cbi rX,lg(n)
|
|
|
|
+ }
|
|
|
|
+ else if (taicpu(p).oper[1]^.val<=31) and
|
|
|
|
+ MatchInstruction(hp1,A_ANDI) and
|
|
|
|
+ (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
|
|
|
|
+ (PopCnt(byte(not(taicpu(hp1).oper[1]^.val)))=1) and
|
|
|
|
+ GetNextInstruction(hp1,hp2) and
|
|
|
|
+ MatchInstruction(hp2,A_OUT) and
|
|
|
|
+ MatchOperand(taicpu(hp2).oper[1]^,taicpu(p).oper[0]^) and
|
|
|
|
+ MatchOperand(taicpu(hp2).oper[0]^,taicpu(p).oper[1]^) then
|
|
|
|
+ begin
|
|
|
|
+ DebugMsg('Peephole InAndiOut2Cbi performed', p);
|
|
|
|
+
|
|
|
|
+ taicpu(p).opcode:=A_CBI;
|
|
|
|
+ taicpu(p).loadconst(0,taicpu(p).oper[1]^.val);
|
|
|
|
+ taicpu(p).loadconst(1,BsrByte(not(taicpu(hp1).oper[1]^.val)));
|
|
|
|
+ asml.Remove(hp1);
|
|
|
|
+ hp1.Free;
|
|
|
|
+ asml.Remove(hp2);
|
|
|
|
+ hp2.Free;
|
|
|
|
+ result:=true;
|
|
|
|
+ end
|
|
|
|
+ {
|
|
|
|
+ in rX,Y
|
|
|
|
+ andi rX,n
|
|
|
|
+ breq/brne L1
|
|
|
|
+
|
|
|
|
+ into
|
|
|
|
+ sbis/sbic Y,lg(n)
|
|
|
|
+ jmp L1
|
|
|
|
+ .Ltemp:
|
|
|
|
+ }
|
|
|
|
+ else if (taicpu(p).oper[1]^.val<=31) and
|
|
|
|
+ MatchInstruction(hp1,A_ANDI) and
|
|
|
|
+ (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
|
|
|
|
+ (PopCnt(byte(taicpu(hp1).oper[1]^.val))=1) and
|
|
|
|
+ GetNextInstruction(hp1,hp2) and
|
|
|
|
+ MatchInstruction(hp2,A_BRxx) and
|
|
|
|
+ (taicpu(hp2).condition in [C_EQ,C_NE]) then
|
|
|
|
+ begin
|
|
|
|
+ if taicpu(hp2).condition=C_EQ then
|
|
|
|
+ taicpu(p).opcode:=A_SBIS
|
|
|
|
+ else
|
|
|
|
+ taicpu(p).opcode:=A_SBIC;
|
|
|
|
+
|
|
|
|
+ DebugMsg('Peephole InAndiBrx2SbixJmp performed', p);
|
|
|
|
+
|
|
|
|
+ taicpu(p).loadconst(0,taicpu(p).oper[1]^.val);
|
|
|
|
+ taicpu(p).loadconst(1,BsrByte(taicpu(hp1).oper[1]^.val));
|
|
|
|
+ asml.Remove(hp1);
|
|
|
|
+ hp1.Free;
|
|
|
|
+
|
|
|
|
+ taicpu(hp2).condition:=C_None;
|
|
|
|
+ if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
|
|
|
|
+ taicpu(hp2).opcode:=A_JMP
|
|
|
|
+ else
|
|
|
|
+ taicpu(hp2).opcode:=A_RJMP;
|
|
|
|
+
|
|
|
|
+ current_asmdata.getjumplabel(l);
|
|
|
|
+ l.increfs;
|
|
|
|
+ asml.InsertAfter(tai_label.create(l), hp2);
|
|
|
|
+
|
|
|
|
+ result:=true;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ function TCpuAsmOptimizer.OptPass1SBR(var p : tai) : boolean;
|
|
|
|
+ var
|
|
|
|
+ hp1 : tai;
|
|
|
|
+ begin
|
|
|
|
+ Result:=false;
|
|
|
|
+ {
|
|
|
|
+ Turn
|
|
|
|
+ in rx, y
|
|
|
|
+ sbr* rx, z
|
|
|
|
+ Into
|
|
|
|
+ sbi* y, z
|
|
|
|
+ }
|
|
|
|
+ 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
|
|
|
|
+ GetLastInstruction(p,hp1) and
|
|
|
|
+ (hp1.typ=ait_instruction) and
|
|
|
|
+ (taicpu(hp1).opcode=A_IN) and
|
|
|
|
+ (taicpu(hp1).ops=2) and
|
|
|
|
+ (taicpu(hp1).oper[1]^.typ=top_const) and
|
|
|
|
+ (taicpu(hp1).oper[1]^.val in [0..31]) and
|
|
|
|
+ MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^.reg) and
|
|
|
|
+ (not RegModifiedBetween(taicpu(p).oper[0]^.reg, hp1, p)) then
|
|
|
|
+ begin
|
|
|
|
+ if taicpu(p).opcode=A_SBRS then
|
|
|
|
+ taicpu(p).opcode:=A_SBIS
|
|
|
|
+ else
|
|
|
|
+ taicpu(p).opcode:=A_SBIC;
|
|
|
|
+
|
|
|
|
+ taicpu(p).loadconst(0, taicpu(hp1).oper[1]^.val);
|
|
|
|
+
|
|
|
|
+ DebugMsg('Peephole InSbrx2Sbix performed', p);
|
|
|
|
+
|
|
|
|
+ asml.Remove(hp1);
|
|
|
|
+ hp1.free;
|
|
|
|
+
|
|
|
|
+ result:=true;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ if InvertSkipInstruction(p) then
|
|
|
|
+ result:=true;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ 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
|
|
var
|
|
- hp1,hp2,hp3,hp4,hp5: tai;
|
|
|
|
|
|
+ hp1: tai;
|
|
alloc, dealloc: tai_regalloc;
|
|
alloc, dealloc: tai_regalloc;
|
|
- i: integer;
|
|
|
|
- l: TAsmLabel;
|
|
|
|
|
|
+ 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: 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;
|
|
|
|
+ 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
|
|
begin
|
|
result := false;
|
|
result := false;
|
|
case p.typ of
|
|
case p.typ of
|
|
@@ -373,847 +1344,35 @@ Implementation
|
|
else
|
|
else
|
|
case taicpu(p).opcode of
|
|
case taicpu(p).opcode of
|
|
A_LDI:
|
|
A_LDI:
|
|
- begin
|
|
|
|
- { turn
|
|
|
|
- ldi reg0, imm
|
|
|
|
- <op> reg1, reg0
|
|
|
|
- dealloc reg0
|
|
|
|
- into
|
|
|
|
- <op>i reg1, imm
|
|
|
|
- }
|
|
|
|
- if MatchOpType(taicpu(p),top_reg,top_const) and
|
|
|
|
- GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
|
|
|
- MatchInstruction(hp1,[A_CP,A_MOV,A_AND,A_SUB],2) and
|
|
|
|
- (not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
|
|
|
|
- MatchOpType(taicpu(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
|
|
|
|
- not(MatchOperand(taicpu(hp1).oper[0]^,taicpu(hp1).oper[1]^)) then
|
|
|
|
- begin
|
|
|
|
- TransferUsedRegs(TmpUsedRegs);
|
|
|
|
- UpdateUsedRegs(TmpUsedRegs,tai(p.next));
|
|
|
|
- UpdateUsedRegs(TmpUsedRegs,tai(hp1.next));
|
|
|
|
- if not(RegUsedAfterInstruction(taicpu(hp1).oper[1]^.reg, hp1, TmpUsedRegs)) then
|
|
|
|
- begin
|
|
|
|
- case taicpu(hp1).opcode of
|
|
|
|
- A_CP:
|
|
|
|
- taicpu(hp1).opcode:=A_CPI;
|
|
|
|
- A_MOV:
|
|
|
|
- taicpu(hp1).opcode:=A_LDI;
|
|
|
|
- A_AND:
|
|
|
|
- taicpu(hp1).opcode:=A_ANDI;
|
|
|
|
- A_SUB:
|
|
|
|
- taicpu(hp1).opcode:=A_SUBI;
|
|
|
|
- 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 LdiOp2Opi performed', p);
|
|
|
|
-
|
|
|
|
- result:=RemoveCurrentP(p);
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
|
|
+ Result:=OptPass1LDI(p);
|
|
A_STS:
|
|
A_STS:
|
|
- if (taicpu(p).oper[0]^.ref^.symbol=nil) and
|
|
|
|
- (taicpu(p).oper[0]^.ref^.relsymbol=nil) and
|
|
|
|
- (getsupreg(taicpu(p).oper[0]^.ref^.base)=RS_NO) and
|
|
|
|
- (getsupreg(taicpu(p).oper[0]^.ref^.index)=RS_NO) and
|
|
|
|
- (taicpu(p).oper[0]^.ref^.addressmode=AM_UNCHANGED) and
|
|
|
|
- (((CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
|
- (taicpu(p).oper[0]^.ref^.offset>=0) and
|
|
|
|
- (taicpu(p).oper[0]^.ref^.offset<=63)) or
|
|
|
|
- (not(CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
|
- (taicpu(p).oper[0]^.ref^.offset>=32) and
|
|
|
|
- (taicpu(p).oper[0]^.ref^.offset<=95))) then
|
|
|
|
- begin
|
|
|
|
- DebugMsg('Peephole Sts2Out performed', p);
|
|
|
|
-
|
|
|
|
- taicpu(p).opcode:=A_OUT;
|
|
|
|
- if CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype] then
|
|
|
|
- taicpu(p).loadconst(0,taicpu(p).oper[0]^.ref^.offset)
|
|
|
|
- else
|
|
|
|
- taicpu(p).loadconst(0,taicpu(p).oper[0]^.ref^.offset-32);
|
|
|
|
- result:=true;
|
|
|
|
- end;
|
|
|
|
|
|
+ Result:=OptPass1STS(p);
|
|
A_LDS:
|
|
A_LDS:
|
|
- if (taicpu(p).oper[1]^.ref^.symbol=nil) and
|
|
|
|
- (taicpu(p).oper[1]^.ref^.relsymbol=nil) and
|
|
|
|
- (getsupreg(taicpu(p).oper[1]^.ref^.base)=RS_NO) and
|
|
|
|
- (getsupreg(taicpu(p).oper[1]^.ref^.index)=RS_NO) and
|
|
|
|
- (taicpu(p).oper[1]^.ref^.addressmode=AM_UNCHANGED) and
|
|
|
|
- (((CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
|
- (taicpu(p).oper[1]^.ref^.offset>=0) and
|
|
|
|
- (taicpu(p).oper[1]^.ref^.offset<=63)) or
|
|
|
|
- (not(CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
|
- (taicpu(p).oper[1]^.ref^.offset>=32) and
|
|
|
|
- (taicpu(p).oper[1]^.ref^.offset<=95))) then
|
|
|
|
- begin
|
|
|
|
- DebugMsg('Peephole Lds2In performed', p);
|
|
|
|
-
|
|
|
|
- taicpu(p).opcode:=A_IN;
|
|
|
|
- if CPUAVR_NOMEMMAPPED_REGS in cpu_capabilities[current_settings.cputype] then
|
|
|
|
- taicpu(p).loadconst(1,taicpu(p).oper[1]^.ref^.offset)
|
|
|
|
- else
|
|
|
|
- taicpu(p).loadconst(1,taicpu(p).oper[1]^.ref^.offset-32);
|
|
|
|
-
|
|
|
|
- result:=true;
|
|
|
|
- end;
|
|
|
|
|
|
+ Result:=OptPass1LDS(p);
|
|
A_IN:
|
|
A_IN:
|
|
- if GetNextInstruction(p,hp1) then
|
|
|
|
- begin
|
|
|
|
- {
|
|
|
|
- in rX,Y
|
|
|
|
- ori rX,n
|
|
|
|
- out Y,rX
|
|
|
|
-
|
|
|
|
- into
|
|
|
|
- sbi rX,lg(n)
|
|
|
|
- }
|
|
|
|
- if (taicpu(p).oper[1]^.val<=31) and
|
|
|
|
- MatchInstruction(hp1,A_ORI) and
|
|
|
|
- (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
|
|
|
|
- (PopCnt(byte(taicpu(hp1).oper[1]^.val))=1) and
|
|
|
|
- GetNextInstruction(hp1,hp2) and
|
|
|
|
- MatchInstruction(hp2,A_OUT) and
|
|
|
|
- MatchOperand(taicpu(hp2).oper[1]^,taicpu(p).oper[0]^) and
|
|
|
|
- MatchOperand(taicpu(hp2).oper[0]^,taicpu(p).oper[1]^) then
|
|
|
|
- begin
|
|
|
|
- DebugMsg('Peephole InOriOut2Sbi performed', p);
|
|
|
|
-
|
|
|
|
- taicpu(p).opcode:=A_SBI;
|
|
|
|
- taicpu(p).loadconst(0,taicpu(p).oper[1]^.val);
|
|
|
|
- taicpu(p).loadconst(1,BsrByte(taicpu(hp1).oper[1]^.val));
|
|
|
|
- asml.Remove(hp1);
|
|
|
|
- hp1.Free;
|
|
|
|
- asml.Remove(hp2);
|
|
|
|
- hp2.Free;
|
|
|
|
- result:=true;
|
|
|
|
- end
|
|
|
|
- {
|
|
|
|
- in rX,Y
|
|
|
|
- andi rX,not(n)
|
|
|
|
- out Y,rX
|
|
|
|
-
|
|
|
|
- into
|
|
|
|
- cbi rX,lg(n)
|
|
|
|
- }
|
|
|
|
- else if (taicpu(p).oper[1]^.val<=31) and
|
|
|
|
- MatchInstruction(hp1,A_ANDI) and
|
|
|
|
- (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
|
|
|
|
- (PopCnt(byte(not(taicpu(hp1).oper[1]^.val)))=1) and
|
|
|
|
- GetNextInstruction(hp1,hp2) and
|
|
|
|
- MatchInstruction(hp2,A_OUT) and
|
|
|
|
- MatchOperand(taicpu(hp2).oper[1]^,taicpu(p).oper[0]^) and
|
|
|
|
- MatchOperand(taicpu(hp2).oper[0]^,taicpu(p).oper[1]^) then
|
|
|
|
- begin
|
|
|
|
- DebugMsg('Peephole InAndiOut2Cbi performed', p);
|
|
|
|
-
|
|
|
|
- taicpu(p).opcode:=A_CBI;
|
|
|
|
- taicpu(p).loadconst(0,taicpu(p).oper[1]^.val);
|
|
|
|
- taicpu(p).loadconst(1,BsrByte(not(taicpu(hp1).oper[1]^.val)));
|
|
|
|
- asml.Remove(hp1);
|
|
|
|
- hp1.Free;
|
|
|
|
- asml.Remove(hp2);
|
|
|
|
- hp2.Free;
|
|
|
|
- result:=true;
|
|
|
|
- end
|
|
|
|
- {
|
|
|
|
- in rX,Y
|
|
|
|
- andi rX,n
|
|
|
|
- breq/brne L1
|
|
|
|
-
|
|
|
|
- into
|
|
|
|
- sbis/sbic Y,lg(n)
|
|
|
|
- jmp L1
|
|
|
|
- .Ltemp:
|
|
|
|
- }
|
|
|
|
- else if (taicpu(p).oper[1]^.val<=31) and
|
|
|
|
- MatchInstruction(hp1,A_ANDI) and
|
|
|
|
- (taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
|
|
|
|
- (PopCnt(byte(taicpu(hp1).oper[1]^.val))=1) and
|
|
|
|
- GetNextInstruction(hp1,hp2) and
|
|
|
|
- MatchInstruction(hp2,A_BRxx) and
|
|
|
|
- (taicpu(hp2).condition in [C_EQ,C_NE]) then
|
|
|
|
- begin
|
|
|
|
- if taicpu(hp2).condition=C_EQ then
|
|
|
|
- taicpu(p).opcode:=A_SBIS
|
|
|
|
- else
|
|
|
|
- taicpu(p).opcode:=A_SBIC;
|
|
|
|
-
|
|
|
|
- DebugMsg('Peephole InAndiBrx2SbixJmp performed', p);
|
|
|
|
-
|
|
|
|
- taicpu(p).loadconst(0,taicpu(p).oper[1]^.val);
|
|
|
|
- taicpu(p).loadconst(1,BsrByte(taicpu(hp1).oper[1]^.val));
|
|
|
|
- asml.Remove(hp1);
|
|
|
|
- hp1.Free;
|
|
|
|
-
|
|
|
|
- taicpu(hp2).condition:=C_None;
|
|
|
|
- if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
|
|
|
|
- taicpu(hp2).opcode:=A_JMP
|
|
|
|
- else
|
|
|
|
- taicpu(hp2).opcode:=A_RJMP;
|
|
|
|
-
|
|
|
|
- current_asmdata.getjumplabel(l);
|
|
|
|
- l.increfs;
|
|
|
|
- asml.InsertAfter(tai_label.create(l), hp2);
|
|
|
|
-
|
|
|
|
- result:=true;
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
|
|
+ Result:=OptPass1IN(p);
|
|
A_SBRS,
|
|
A_SBRS,
|
|
A_SBRC:
|
|
A_SBRC:
|
|
- begin
|
|
|
|
- {
|
|
|
|
- Turn
|
|
|
|
- in rx, y
|
|
|
|
- sbr* rx, z
|
|
|
|
- Into
|
|
|
|
- sbi* y, z
|
|
|
|
- }
|
|
|
|
- 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
|
|
|
|
- GetLastInstruction(p,hp1) and
|
|
|
|
- (hp1.typ=ait_instruction) and
|
|
|
|
- (taicpu(hp1).opcode=A_IN) and
|
|
|
|
- (taicpu(hp1).ops=2) and
|
|
|
|
- (taicpu(hp1).oper[1]^.typ=top_const) and
|
|
|
|
- (taicpu(hp1).oper[1]^.val in [0..31]) and
|
|
|
|
- MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^.reg) and
|
|
|
|
- (not RegModifiedBetween(taicpu(p).oper[0]^.reg, hp1, p)) then
|
|
|
|
- begin
|
|
|
|
- if taicpu(p).opcode=A_SBRS then
|
|
|
|
- taicpu(p).opcode:=A_SBIS
|
|
|
|
- else
|
|
|
|
- taicpu(p).opcode:=A_SBIC;
|
|
|
|
-
|
|
|
|
- taicpu(p).loadconst(0, taicpu(hp1).oper[1]^.val);
|
|
|
|
-
|
|
|
|
- DebugMsg('Peephole InSbrx2Sbix performed', p);
|
|
|
|
-
|
|
|
|
- asml.Remove(hp1);
|
|
|
|
- hp1.free;
|
|
|
|
-
|
|
|
|
- result:=true;
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- if InvertSkipInstruction(p) then
|
|
|
|
- result:=true;
|
|
|
|
- end;
|
|
|
|
|
|
+ Result:=OptPass1SBR(p);
|
|
A_ANDI:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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 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_SBIC,
|
|
A_SBIS:
|
|
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;
|
|
end;
|
|
end;
|
|
end;
|