mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-25 10:29:42 +02:00
Added support for IT block merging
Added a peephole pattern check for UXTB->UXTH chains git-svn-id: branches/laksen/arm-embedded@22592 -
This commit is contained in:
parent
9ec9b44784
commit
3e963a49e2
@ -270,7 +270,7 @@ uses
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
cutils,rgobj,itcpugas;
|
cutils,rgobj,itcpugas,aoptcpu;
|
||||||
|
|
||||||
|
|
||||||
procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
|
procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
|
||||||
@ -1098,13 +1098,110 @@ implementation
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function getMergedInstruction(FirstOp,LastOp:TAsmOp;InvertLast:boolean) : TAsmOp;
|
||||||
|
const
|
||||||
|
opTable: array[A_IT..A_ITTTT] of string =
|
||||||
|
('T','TE','TT','TEE','TTE','TET','TTT',
|
||||||
|
'TEEE','TTEE','TETE','TTTE',
|
||||||
|
'TEET','TTET','TETT','TTTT');
|
||||||
|
invertedOpTable: array[A_IT..A_ITTTT] of string =
|
||||||
|
('E','ET','EE','ETT','EET','ETE','EEE',
|
||||||
|
'ETTT','EETT','ETET','EEET',
|
||||||
|
'ETTE','EETE','ETEE','EEEE');
|
||||||
|
var
|
||||||
|
resStr : string;
|
||||||
|
i : TAsmOp;
|
||||||
|
begin
|
||||||
|
if InvertLast then
|
||||||
|
resStr := opTable[FirstOp]+invertedOpTable[LastOp]
|
||||||
|
else
|
||||||
|
resStr := opTable[FirstOp]+opTable[LastOp];
|
||||||
|
if length(resStr) > 4 then
|
||||||
|
internalerror(2012100805);
|
||||||
|
|
||||||
|
for i := low(opTable) to high(opTable) do
|
||||||
|
if opTable[i] = resStr then
|
||||||
|
exit(i);
|
||||||
|
|
||||||
|
internalerror(2012100806);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure foldITInstructions(list: TAsmList);
|
||||||
|
var
|
||||||
|
curtai,hp1 : tai;
|
||||||
|
levels,i : LongInt;
|
||||||
|
begin
|
||||||
|
curtai:=tai(list.First);
|
||||||
|
while assigned(curtai) do
|
||||||
|
begin
|
||||||
|
case curtai.typ of
|
||||||
|
ait_instruction:
|
||||||
|
if IsIT(taicpu(curtai).opcode) then
|
||||||
|
begin
|
||||||
|
levels := GetITLevels(taicpu(curtai).opcode);
|
||||||
|
if levels < 4 then
|
||||||
|
begin
|
||||||
|
i:=levels;
|
||||||
|
hp1:=tai(curtai.Next);
|
||||||
|
while assigned(hp1) and
|
||||||
|
(i > 0) do
|
||||||
|
begin
|
||||||
|
if hp1.typ=ait_instruction then
|
||||||
|
begin
|
||||||
|
dec(i);
|
||||||
|
if (i = 0) and
|
||||||
|
mustbelast(hp1) then
|
||||||
|
begin
|
||||||
|
hp1:=nil;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
hp1:=tai(hp1.Next);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if assigned(hp1) then
|
||||||
|
begin
|
||||||
|
// We are pointing at the first instruction after the IT block
|
||||||
|
while assigned(hp1) and
|
||||||
|
(hp1.typ<>ait_instruction) do
|
||||||
|
hp1:=tai(hp1.Next);
|
||||||
|
|
||||||
|
if assigned(hp1) and
|
||||||
|
(hp1.typ=ait_instruction) and
|
||||||
|
IsIT(taicpu(hp1).opcode) then
|
||||||
|
begin
|
||||||
|
if (levels+GetITLevels(taicpu(hp1).opcode) <= 4) and
|
||||||
|
((taicpu(curtai).oper[0]^.cc=taicpu(hp1).oper[0]^.cc) or
|
||||||
|
(taicpu(curtai).oper[0]^.cc=inverse_cond(taicpu(hp1).oper[0]^.cc))) then
|
||||||
|
begin
|
||||||
|
taicpu(curtai).opcode:=getMergedInstruction(taicpu(curtai).opcode,
|
||||||
|
taicpu(hp1).opcode,
|
||||||
|
taicpu(curtai).oper[0]^.cc=inverse_cond(taicpu(hp1).oper[0]^.cc));
|
||||||
|
|
||||||
|
list.Remove(hp1);
|
||||||
|
hp1.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
curtai:=tai(curtai.Next);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure finalizearmcode(list, listtoinsert: TAsmList);
|
procedure finalizearmcode(list, listtoinsert: TAsmList);
|
||||||
begin
|
begin
|
||||||
insertpcrelativedata(list, listtoinsert);
|
|
||||||
|
|
||||||
{ Do Thumb-2 16bit -> 32bit transformations }
|
{ Do Thumb-2 16bit -> 32bit transformations }
|
||||||
if current_settings.cputype in cpu_thumb2 then
|
if current_settings.cputype in cpu_thumb2 then
|
||||||
ensurethumb2encodings(list);
|
begin
|
||||||
|
ensurethumb2encodings(list);
|
||||||
|
foldITInstructions(list);
|
||||||
|
end;
|
||||||
|
|
||||||
|
insertpcrelativedata(list, listtoinsert);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure InsertPData;
|
procedure InsertPData;
|
||||||
|
@ -66,6 +66,8 @@ Type
|
|||||||
procedure PeepHoleOptPass2;override;
|
procedure PeepHoleOptPass2;override;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
function MustBeLast(p : tai) : boolean;
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -1199,9 +1201,16 @@ Implementation
|
|||||||
p:=hp1;
|
p:=hp1;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
A_UXTB,
|
A_UXTB:
|
||||||
A_SXTB:
|
|
||||||
begin
|
begin
|
||||||
|
{
|
||||||
|
change
|
||||||
|
uxtb reg2,reg1
|
||||||
|
strb reg2,[...]
|
||||||
|
dealloc reg2
|
||||||
|
to
|
||||||
|
strb reg1,[...]
|
||||||
|
}
|
||||||
if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
|
if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
|
||||||
GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
|
GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
|
||||||
MatchInstruction(hp1, A_STR, [C_None], [PF_B]) and
|
MatchInstruction(hp1, A_STR, [C_None], [PF_B]) and
|
||||||
@ -1211,15 +1220,37 @@ Implementation
|
|||||||
{ reg1 might not be modified inbetween }
|
{ reg1 might not be modified inbetween }
|
||||||
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
|
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
|
||||||
begin
|
begin
|
||||||
DebugMsg('Peephole xXTBStrb2Strb done', p);
|
DebugMsg('Peephole UxtbStrb2Strb done', p);
|
||||||
taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
|
taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
|
||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=hp1;
|
p:=hp1;
|
||||||
|
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
|
||||||
|
GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
|
||||||
|
MatchInstruction(hp1, A_UXTH, [C_None], [PF_None]) and
|
||||||
|
(assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
|
||||||
|
(taicpu(p).oper[0]^.reg = taicpu(hp1).oper[0]^.reg)) and
|
||||||
|
{ reg1 might not be modified inbetween }
|
||||||
|
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
|
||||||
|
begin
|
||||||
|
DebugMsg('Peephole UxtbUxth2Uxtb done', p);
|
||||||
|
taicpu(hp1).opcode:=A_UXTB;
|
||||||
|
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
|
||||||
|
asml.remove(p);
|
||||||
|
p.free;
|
||||||
|
p:=hp1;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
A_UXTH,
|
A_UXTH:
|
||||||
A_SXTH:
|
|
||||||
begin
|
begin
|
||||||
if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
|
if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
|
||||||
GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
|
GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
|
||||||
@ -1230,7 +1261,7 @@ Implementation
|
|||||||
{ reg1 might not be modified inbetween }
|
{ reg1 might not be modified inbetween }
|
||||||
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
|
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
|
||||||
begin
|
begin
|
||||||
DebugMsg('Peephole xXTBStrh2Strh done', p);
|
DebugMsg('Peephole UXTHStrh2Strh done', p);
|
||||||
taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
|
taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
|
||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
|
@ -361,6 +361,9 @@ unit cpubase;
|
|||||||
function split_into_shifter_const(value : aint;var imm1: dword; var imm2: dword):boolean;
|
function split_into_shifter_const(value : aint;var imm1: dword; var imm2: dword):boolean;
|
||||||
function dwarf_reg(r:tregister):shortint;
|
function dwarf_reg(r:tregister):shortint;
|
||||||
|
|
||||||
|
function IsIT(op: TAsmOp) : boolean;
|
||||||
|
function GetITLevels(op: TAsmOp) : longint;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -606,4 +609,35 @@ unit cpubase;
|
|||||||
result:=RS_R0;
|
result:=RS_R0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function IsIT(op: TAsmOp) : boolean;
|
||||||
|
begin
|
||||||
|
case op of
|
||||||
|
A_IT,
|
||||||
|
A_ITE, A_ITT,
|
||||||
|
A_ITEE, A_ITTE, A_ITET, A_ITTT,
|
||||||
|
A_ITEEE, A_ITTEE, A_ITETE, A_ITTTE,
|
||||||
|
A_ITEET, A_ITTET, A_ITETT, A_ITTTT:
|
||||||
|
result:=true;
|
||||||
|
else
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetITLevels(op: TAsmOp) : longint;
|
||||||
|
begin
|
||||||
|
case op of
|
||||||
|
A_IT:
|
||||||
|
result:=1;
|
||||||
|
A_ITE, A_ITT:
|
||||||
|
result:=2;
|
||||||
|
A_ITEE, A_ITTE, A_ITET, A_ITTT:
|
||||||
|
result:=3;
|
||||||
|
A_ITEEE, A_ITTEE, A_ITETE, A_ITTTE,
|
||||||
|
A_ITEET, A_ITTET, A_ITETT, A_ITTTT:
|
||||||
|
result:=4;
|
||||||
|
else
|
||||||
|
result:=0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -255,37 +255,6 @@ unit rgcpu;
|
|||||||
result:=getsubreg(r);
|
result:=getsubreg(r);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function IsIT(op: TAsmOp) : boolean;
|
|
||||||
begin
|
|
||||||
case op of
|
|
||||||
A_IT,
|
|
||||||
A_ITE, A_ITT,
|
|
||||||
A_ITEE, A_ITTE, A_ITET, A_ITTT,
|
|
||||||
A_ITEEE, A_ITTEE, A_ITETE, A_ITTTE,
|
|
||||||
A_ITEET, A_ITTET, A_ITETT, A_ITTTT:
|
|
||||||
result:=true;
|
|
||||||
else
|
|
||||||
result:=false;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetITLevels(op: TAsmOp) : longint;
|
|
||||||
begin
|
|
||||||
case op of
|
|
||||||
A_IT:
|
|
||||||
result:=1;
|
|
||||||
A_ITE, A_ITT:
|
|
||||||
result:=2;
|
|
||||||
A_ITEE, A_ITTE, A_ITET, A_ITTT:
|
|
||||||
result:=3;
|
|
||||||
A_ITEEE, A_ITTEE, A_ITETE, A_ITTTE,
|
|
||||||
A_ITEET, A_ITTET, A_ITETT, A_ITTTT:
|
|
||||||
result:=4;
|
|
||||||
else
|
|
||||||
result:=0;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetITRemainderOp(originalOp:TAsmOp;remLevels:longint;var newOp: TAsmOp;var NeedsCondSwap:boolean) : TAsmOp;
|
function GetITRemainderOp(originalOp:TAsmOp;remLevels:longint;var newOp: TAsmOp;var NeedsCondSwap:boolean) : TAsmOp;
|
||||||
const
|
const
|
||||||
remOps : array[1..3] of array[A_ITE..A_ITTTT] of TAsmOp = (
|
remOps : array[1..3] of array[A_ITE..A_ITTTT] of TAsmOp = (
|
||||||
|
Loading…
Reference in New Issue
Block a user