|
@@ -21,26 +21,44 @@
|
|
|
****************************************************************************
|
|
|
}
|
|
|
|
|
|
-
|
|
|
Unit aoptcpu;
|
|
|
|
|
|
{$i fpcdefs.inc}
|
|
|
|
|
|
-Interface
|
|
|
+{ $define DEBUG_AOPTCPU}
|
|
|
|
|
|
-uses cpubase, aasmtai, aopt, aoptcpub;
|
|
|
+Interface
|
|
|
|
|
|
-Type
|
|
|
- TCpuAsmOptimizer = class(TAsmOptimizer)
|
|
|
- { uses the same constructor as TAopObj }
|
|
|
- function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
|
|
- procedure PeepHoleOptPass2;override;
|
|
|
- End;
|
|
|
+ uses
|
|
|
+ globtype, globals,
|
|
|
+ cutils,
|
|
|
+ cgbase, cpubase, aasmtai, aasmcpu, aopt, aoptcpub;
|
|
|
+
|
|
|
+ Type
|
|
|
+ TCpuAsmOptimizer = class(TAsmOptimizer)
|
|
|
+ { uses the same constructor as TAopObj }
|
|
|
+ function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
|
|
+ procedure PeepHoleOptPass2;override;
|
|
|
+ function GetNextInstructionUsingReg(Current : tai; out Next : tai; reg : TRegister) : Boolean;
|
|
|
+ function LookForPostindexedPattern(p : taicpu) : boolean;
|
|
|
+ procedure DebugMsg(const s : string; p : tai);
|
|
|
+ End;
|
|
|
|
|
|
Implementation
|
|
|
|
|
|
uses
|
|
|
- aasmbase,aasmcpu,cgbase;
|
|
|
+ aasmbase;
|
|
|
+
|
|
|
+{$ifdef DEBUG_AOPTCPU}
|
|
|
+ procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
|
|
|
+ begin
|
|
|
+ asml.insertbefore(tai_comment.Create(strpnew(s)), p);
|
|
|
+ end;
|
|
|
+{$else DEBUG_AOPTCPU}
|
|
|
+ procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);inline;
|
|
|
+ begin
|
|
|
+ end;
|
|
|
+{$endif DEBUG_AOPTCPU}
|
|
|
|
|
|
function CanBeCond(p : tai) : boolean;
|
|
|
begin
|
|
@@ -48,11 +66,105 @@ Implementation
|
|
|
end;
|
|
|
|
|
|
|
|
|
+ function MatchInstruction(const instr: tai; const op: TAsmOps; const postfix: TOpPostfixes): boolean;
|
|
|
+ begin
|
|
|
+ result :=
|
|
|
+ (instr.typ = ait_instruction) and
|
|
|
+ ((op = []) or (taicpu(instr).opcode in op)) and
|
|
|
+ ((postfix = []) or (taicpu(instr).oppostfix in postfix));
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ function MatchInstruction(const instr: tai; const op: TAsmOp; const postfix: TOpPostfixes): boolean;
|
|
|
+ begin
|
|
|
+ result :=
|
|
|
+ (instr.typ = ait_instruction) and
|
|
|
+ (taicpu(instr).opcode = op) and
|
|
|
+ ((postfix = []) or (taicpu(instr).oppostfix in postfix));
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
|
|
|
+ Out Next: tai; reg: TRegister): Boolean;
|
|
|
+ begin
|
|
|
+ Next:=Current;
|
|
|
+ repeat
|
|
|
+ Result:=GetNextInstruction(Next,Next);
|
|
|
+ until not (Result) or
|
|
|
+ not(cs_opt_level3 in current_settings.optimizerswitches) or
|
|
|
+ (Next.typ<>ait_instruction) or
|
|
|
+ RegInInstruction(reg,Next) or
|
|
|
+ is_calljmp(taicpu(Next).opcode);
|
|
|
+ end;
|
|
|
+
|
|
|
+ {
|
|
|
+ optimize
|
|
|
+ ldr/str regX,[reg1]
|
|
|
+ ...
|
|
|
+ add/sub reg1,reg1,regY/const
|
|
|
+
|
|
|
+ into
|
|
|
+
|
|
|
+ ldr/str regX,[reg1], regY/const
|
|
|
+ }
|
|
|
+ function TCpuAsmOptimizer.LookForPostindexedPattern(p: taicpu) : boolean;
|
|
|
+ var
|
|
|
+ hp1 : tai;
|
|
|
+ begin
|
|
|
+ Result:=false;
|
|
|
+ if (p.oper[1]^.typ = top_ref) and
|
|
|
+ (p.oper[1]^.ref^.addressmode=AM_OFFSET) and
|
|
|
+ (p.oper[1]^.ref^.index=NR_NO) and
|
|
|
+ (p.oper[1]^.ref^.offset=0) and
|
|
|
+ GetNextInstructionUsingReg(p, hp1, p.oper[1]^.ref^.base) and
|
|
|
+ { we cannot check NR_DEFAULTFLAGS for modification yet so don't allow a condition }
|
|
|
+ MatchInstruction(hp1, [A_ADD, A_SUB], [PF_None]) and
|
|
|
+ (taicpu(hp1).oper[0]^.reg=p.oper[1]^.ref^.base) and
|
|
|
+ (taicpu(hp1).oper[1]^.reg=p.oper[1]^.ref^.base) and
|
|
|
+ (
|
|
|
+ { valid offset? }
|
|
|
+ (taicpu(hp1).oper[2]^.typ=top_const) and
|
|
|
+ (taicpu(hp1).oper[2]^.val>=-256) and
|
|
|
+ (abs(taicpu(hp1).oper[2]^.val)<256)
|
|
|
+ ) and
|
|
|
+ { don't apply the optimization if the base register is loaded }
|
|
|
+ (p.oper[0]^.reg<>p.oper[1]^.ref^.base) and
|
|
|
+ not(RegModifiedBetween(taicpu(hp1).oper[0]^.reg,p,hp1)) and
|
|
|
+ { don't apply the optimization if the (new) index register is loaded }
|
|
|
+ (p.oper[0]^.reg<>taicpu(hp1).oper[2]^.reg) and
|
|
|
+ not(RegModifiedBetween(taicpu(hp1).oper[2]^.reg,p,hp1)) then
|
|
|
+ begin
|
|
|
+ DebugMsg('Peephole Str/LdrAdd/Sub2Str/Ldr Postindex done', p);
|
|
|
+ p.oper[1]^.ref^.addressmode:=AM_POSTINDEXED;
|
|
|
+ if taicpu(hp1).opcode=A_ADD then
|
|
|
+ p.oper[1]^.ref^.offset:=taicpu(hp1).oper[2]^.val
|
|
|
+ else
|
|
|
+ p.oper[1]^.ref^.offset:=-taicpu(hp1).oper[2]^.val;
|
|
|
+ asml.Remove(hp1);
|
|
|
+ hp1.Free;
|
|
|
+ Result:=true;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
|
|
|
var
|
|
|
next1: tai;
|
|
|
begin
|
|
|
result := false;
|
|
|
+ if p.typ=ait_instruction then
|
|
|
+ begin
|
|
|
+ case taicpu(p).opcode of
|
|
|
+ A_LDR:
|
|
|
+ begin
|
|
|
+ Result:=LookForPostindexedPattern(taicpu(p));
|
|
|
+ end;
|
|
|
+ A_STR:
|
|
|
+ begin
|
|
|
+ Result:=LookForPostindexedPattern(taicpu(p));
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
|