diff options
author | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2020-04-15 20:21:29 +0000 |
---|---|---|
committer | florian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2020-04-15 20:21:29 +0000 |
commit | bb4c6b5122193996239fff8c103c282f8d56f3ed (patch) | |
tree | 0a9dd0113f41d3b78ecbb1a3351f1fe776f38f9a /compiler/arm | |
parent | 3352e591982823a0c4a004dd05d5bf659c25a58d (diff) | |
download | fpc-bb4c6b5122193996239fff8c103c282f8d56f3ed.tar.gz |
* factored out TARMAsmOptimizer.OptPass1UXTB
* several other routines being very similar for ARM and AAarch64 moved to aoptarm
git-svn-id: https://svn.freepascal.org/svn/fpc/trunk@44725 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler/arm')
-rw-r--r-- | compiler/arm/aoptcpu.pas | 271 |
1 files changed, 1 insertions, 270 deletions
diff --git a/compiler/arm/aoptcpu.pas b/compiler/arm/aoptcpu.pas index 07d17045e3..bf3b565e0b 100644 --- a/compiler/arm/aoptcpu.pas +++ b/compiler/arm/aoptcpu.pas @@ -44,7 +44,6 @@ Type function PeepHoleOptPass1Cpu(var p: tai): boolean; override; procedure PeepHoleOptPass2;override; Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;override; - function RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string): boolean; function RemoveSuperfluousVMov(const p : tai; movp : tai; const optimizer : string) : boolean; { gets the next tai object after current that contains info relevant @@ -52,7 +51,6 @@ Type change in program flow. If there is none, it returns false and sets p1 to nil } - Function GetNextInstructionUsingReg(Current: tai; Out Next: tai; reg: TRegister): Boolean; Function GetNextInstructionUsingRef(Current: tai; Out Next: tai; const ref: TReference; StopOnStore: Boolean = true): Boolean; { outputs a debug message into the assembler file } @@ -112,63 +110,6 @@ Implementation end; - function RefsEqual(const r1, r2: treference): boolean; - begin - refsequal := - (r1.offset = r2.offset) and - (r1.base = r2.base) and - (r1.index = r2.index) and (r1.scalefactor = r2.scalefactor) and - (r1.symbol=r2.symbol) and (r1.refaddr = r2.refaddr) and - (r1.relsymbol = r2.relsymbol) and - (r1.signindex = r2.signindex) and - (r1.shiftimm = r2.shiftimm) and - (r1.addressmode = r2.addressmode) and - (r1.shiftmode = r2.shiftmode) and - (r1.volatility=[]) and - (r2.volatility=[]); - end; - - function MatchInstruction(const instr: tai; const op: TCommonAsmOps; const cond: TAsmConds; const postfix: TOpPostfixes): boolean; - begin - result := - (instr.typ = ait_instruction) and - ((op = []) or ((ord(taicpu(instr).opcode)<256) and (taicpu(instr).opcode in op))) and - ((cond = []) or (taicpu(instr).condition in cond)) and - ((postfix = []) or (taicpu(instr).oppostfix in postfix)); - end; - - function MatchInstruction(const instr: tai; const op: TAsmOp; const cond: TAsmConds; const postfix: TOpPostfixes): boolean; - begin - result := - (instr.typ = ait_instruction) and - (taicpu(instr).opcode = op) and - ((cond = []) or (taicpu(instr).condition in cond)) and - ((postfix = []) or (taicpu(instr).oppostfix in postfix)); - end; - - function MatchOperand(const oper1: TOper; const oper2: TOper): boolean; inline; - begin - result := oper1.typ = oper2.typ; - - if result then - case oper1.typ of - top_const: - Result:=oper1.val = oper2.val; - top_reg: - Result:=oper1.reg = oper2.reg; - top_conditioncode: - Result:=oper1.cc = oper2.cc; - top_ref: - Result:=RefsEqual(oper1.ref^, oper2.ref^); - else Result:=false; - end - end; - - function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline; - begin - result := (oper.typ = top_reg) and (oper.reg = reg); - end; - function RemoveRedundantMove(const cmpp: tai; movp: tai; asml: TAsmList):Boolean; begin Result:=false; @@ -332,20 +273,6 @@ Implementation 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) or - RegModifiedByInstruction(NR_PC,Next); - end; - function TCpuAsmOptimizer.GetNextInstructionUsingRef(Current: tai; Out Next: tai; const ref: TReference; StopOnStore: Boolean = true): Boolean; begin @@ -395,92 +322,6 @@ Implementation end; - function TCpuAsmOptimizer.RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string):boolean; - var - alloc, - dealloc : tai_regalloc; - hp1 : tai; - begin - Result:=false; - if MatchInstruction(movp, A_MOV, [taicpu(p).condition], [PF_None]) and - (taicpu(movp).ops=2) and {We can't optimize if there is a shiftop} - MatchOperand(taicpu(movp).oper[1]^, taicpu(p).oper[0]^.reg) and - { don't mess with moves to pc } - (taicpu(movp).oper[0]^.reg<>NR_PC) and - { don't mess with moves to lr } - (taicpu(movp).oper[0]^.reg<>NR_R14) and - { the destination register of the mov might not be used beween p and movp } - not(RegUsedBetween(taicpu(movp).oper[0]^.reg,p,movp)) and - { cb[n]z are thumb instructions which require specific registers, with no wide forms } - (taicpu(p).opcode<>A_CBZ) and - (taicpu(p).opcode<>A_CBNZ) and - {There is a special requirement for MUL and MLA, oper[0] and oper[1] are not allowed to be the same} - not ( - (taicpu(p).opcode in [A_MLA, A_MUL]) and - (taicpu(p).oper[1]^.reg = taicpu(movp).oper[0]^.reg) and - (current_settings.cputype < cpu_armv6) - ) and - { Take care to only do this for instructions which REALLY load to the first register. - Otherwise - str reg0, [reg1] - mov reg2, reg0 - will be optimized to - str reg2, [reg1] - } - regLoadedWithNewValue(taicpu(p).oper[0]^.reg, p) then - begin - dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(movp.Next)); - if assigned(dealloc) then - begin - DebugMsg('Peephole '+optimizer+' removed superfluous mov', movp); - result:=true; - - { taicpu(p).oper[0]^.reg is not used anymore, try to find its allocation - and remove it if possible } - asml.Remove(dealloc); - alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.previous)); - if assigned(alloc) then - begin - asml.Remove(alloc); - alloc.free; - dealloc.free; - end - else - asml.InsertAfter(dealloc,p); - - { try to move the allocation of the target register } - GetLastInstruction(movp,hp1); - alloc:=FindRegAlloc(taicpu(movp).oper[0]^.reg,tai(hp1.Next)); - if assigned(alloc) then - begin - asml.Remove(alloc); - asml.InsertBefore(alloc,p); - { adjust used regs } - IncludeRegInUsedRegs(taicpu(movp).oper[0]^.reg,UsedRegs); - end; - - { finally get rid of the mov } - taicpu(p).loadreg(0,taicpu(movp).oper[0]^.reg); - { Remove preindexing and postindexing for LDR in some cases. - For example: - ldr reg2,[reg1, xxx]! - mov reg1,reg2 - must be translated to: - ldr reg1,[reg1, xxx] - - Preindexing must be removed there, since the same register is used as the base and as the target. - Such case is not allowed for ARM CPU and produces crash. } - if (taicpu(p).opcode = A_LDR) and (taicpu(p).oper[1]^.typ = top_ref) - and (taicpu(movp).oper[0]^.reg = taicpu(p).oper[1]^.ref^.base) - then - taicpu(p).oper[1]^.ref^.addressmode:=AM_OFFSET; - asml.remove(movp); - movp.free; - end; - end; - end; - - function TCpuAsmOptimizer.RemoveSuperfluousVMov(const p: tai; movp: tai; const optimizer: string):boolean; var alloc, @@ -2049,117 +1890,7 @@ Implementation end; {$endif dummy} A_UXTB: - begin - { - change - uxtb reg2,reg1 - strb reg2,[...] - dealloc reg2 - to - strb reg1,[...] - } - if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and - (taicpu(p).ops=2) and - GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and - MatchInstruction(hp1, A_STR, [C_None], [PF_B]) and - assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) and - { the reference in strb might not use reg2 } - not(RegInRef(taicpu(p).oper[0]^.reg,taicpu(hp1).oper[1]^.ref^)) and - { reg1 might not be modified inbetween } - not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then - begin - DebugMsg('Peephole UxtbStrb2Strb done', p); - taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg); - GetNextInstruction(p,hp2); - asml.remove(p); - p.free; - p:=hp2; - result:=true; - end - { - change - uxtb reg2,reg1 - uxth reg3,reg2 - dealloc reg2 - to - uxtb reg3,reg1 - } - else if MatchInstruction(p, A_UXTB, [C_None], [PF_None]) and - (taicpu(p).ops=2) and - GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and - MatchInstruction(hp1, A_UXTH, [C_None], [PF_None]) and - (taicpu(hp1).ops = 2) and - MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and - RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and - { reg1 might not be modified inbetween } - not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then - begin - DebugMsg('Peephole UxtbUxth2Uxtb done', p); - AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs); - taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg); - asml.remove(hp1); - hp1.free; - result:=true; - end - { - change - uxtb reg2,reg1 - uxtb reg3,reg2 - dealloc reg2 - to - uxtb reg3,reg1 - } - else if MatchInstruction(p, A_UXTB, [C_None], [PF_None]) and - (taicpu(p).ops=2) and - GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and - MatchInstruction(hp1, A_UXTB, [C_None], [PF_None]) and - (taicpu(hp1).ops = 2) and - MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and - RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and - { reg1 might not be modified inbetween } - not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then - begin - DebugMsg('Peephole UxtbUxtb2Uxtb done', p); - AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs); - taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg); - asml.remove(hp1); - hp1.free; - result:=true; - end - { - change - uxtb reg2,reg1 - and reg3,reg2,#0x*FF - dealloc reg2 - to - uxtb reg3,reg1 - } - else if MatchInstruction(p, A_UXTB, [C_None], [PF_None]) and - (taicpu(p).ops=2) and - GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and - MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and - (taicpu(hp1).ops=3) and - (taicpu(hp1).oper[2]^.typ=top_const) and - ((taicpu(hp1).oper[2]^.val and $FF)=$FF) and - MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and - RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and - { reg1 might not be modified inbetween } - not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then - begin - DebugMsg('Peephole UxtbAndImm2Uxtb done', p); - taicpu(hp1).opcode:=A_UXTB; - taicpu(hp1).ops:=2; - taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg); - GetNextInstruction(p,hp2); - asml.remove(p); - p.free; - p:=hp2; - result:=true; - end - else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and - RemoveSuperfluousMove(p, hp1, 'UxtbMov2Data') then - Result:=true; - end; + Result:=OptPass1UXTB(p); A_UXTH: begin { |