Look ahead more than one instruction in FoldShiftProcess for ARM

Up until now we only checked the next instruction, with the new load
scheduler this is insufficient as shift-instructions and next usage
might farther apart.

The new version uses GetNextInstructionUsingReg, this also comes with a
price as we very carefully have to check if one of the used registers is
changed and that the usage of RRX will not break when we fold and flags
get changed in between.

git-svn-id: trunk@22876 -
This commit is contained in:
masta 2012-10-29 17:57:11 +00:00
parent 7106b4dd54
commit 3a017f76d0

View File

@ -956,72 +956,89 @@ Implementation
(taicpu(p).oper[1]^.typ = top_reg) and (taicpu(p).oper[1]^.typ = top_reg) and
(taicpu(p).oper[2]^.typ = top_shifterop) and (taicpu(p).oper[2]^.typ = top_shifterop) and
(taicpu(p).oppostfix = PF_NONE) and (taicpu(p).oppostfix = PF_NONE) and
GetNextInstruction(p, hp1) and GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
MatchInstruction(hp1, [A_ADD, A_ADC, A_RSB, A_RSC, A_SUB, A_SBC, MatchInstruction(hp1, [A_ADD, A_ADC, A_RSB, A_RSC, A_SUB, A_SBC,
A_AND, A_BIC, A_EOR, A_ORR, A_TEQ, A_TST, A_AND, A_BIC, A_EOR, A_ORR, A_TEQ, A_TST,
A_CMP, A_CMN], A_CMP, A_CMN],
[taicpu(p).condition], [PF_None]) and [taicpu(p).condition], [PF_None]) and
(taicpu(hp1).ops >= 2) and {Currently we can't fold into another shifterop} (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
regLoadedWithNewValue(taicpu(p).oper[0]^.reg, hp1)) and
(taicpu(hp1).ops >= 2) and
{Currently we can't fold into another shifterop}
(taicpu(hp1).oper[taicpu(hp1).ops-1]^.typ = top_reg) and (taicpu(hp1).oper[taicpu(hp1).ops-1]^.typ = top_reg) and
{Folding rrx is problematic because of the C-Flag, as we currently can't check
NR_DEFAULTFLAGS for modification}
(
{Everything is fine if we don't use RRX}
(taicpu(p).oper[2]^.shifterop^.shiftmode <> SM_RRX) or
(
{If it is RRX, then check if we're just accessing the next instruction}
GetNextInstruction(p, hp2) and
(hp1 = hp2)
)
) and
{ reg1 might not be modified inbetween }
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) and
{ The shifterop can contain a register, might not be modified}
(
(taicpu(p).oper[2]^.shifterop^.rs = NR_NO) or
not(RegModifiedBetween(taicpu(p).oper[2]^.shifterop^.rs, p, hp1))
) and
( (
{Only ONE of the two src operands is allowed to match} {Only ONE of the two src operands is allowed to match}
MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[taicpu(hp1).ops-2]^) xor MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[taicpu(hp1).ops-2]^) xor
MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[taicpu(hp1).ops-1]^) MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[taicpu(hp1).ops-1]^)
) then ) then
begin begin
CopyUsedRegs(TmpUsedRegs);
UpdateUsedRegs(TmpUsedRegs, tai(p.next));
if taicpu(hp1).opcode in [A_TST, A_TEQ, A_CMN] then if taicpu(hp1).opcode in [A_TST, A_TEQ, A_CMN] then
I2:=0 I2:=0
else else
I2:=1; I2:=1;
if not(RegUsedAfterInstruction(taicpu(p).oper[0]^.reg,hp1,TmpUsedRegs)) then for I:=I2 to taicpu(hp1).ops-1 do
for I:=I2 to taicpu(hp1).ops-1 do if MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[I]^.reg) then
if MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[I]^.reg) then begin
begin { If the parameter matched on the second op from the RIGHT
{ If the parameter matched on the second op from the RIGHT we have to switch the parameters, this will not happen for CMP
we have to switch the parameters, this will not happen for CMP were we're only evaluating the most right parameter
were we're only evaluating the most right parameter }
} if I <> taicpu(hp1).ops-1 then
if I <> taicpu(hp1).ops-1 then begin
begin {The SUB operators need to be changed when we swap parameters}
{The SUB operators need to be changed when we swap parameters} case taicpu(hp1).opcode of
case taicpu(hp1).opcode of A_SUB: tempop:=A_RSB;
A_SUB: tempop:=A_RSB; A_SBC: tempop:=A_RSC;
A_SBC: tempop:=A_RSC; A_RSB: tempop:=A_SUB;
A_RSB: tempop:=A_SUB; A_RSC: tempop:=A_SBC;
A_RSC: tempop:=A_SBC; else tempop:=taicpu(hp1).opcode;
else tempop:=taicpu(hp1).opcode; end;
end;
if taicpu(hp1).ops = 3 then
hp2:=taicpu.op_reg_reg_reg_shifterop(tempop,
taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[2]^.reg,
taicpu(p).oper[1]^.reg, taicpu(p).oper[2]^.shifterop^)
else
hp2:=taicpu.op_reg_reg_shifterop(tempop,
taicpu(hp1).oper[0]^.reg, taicpu(p).oper[1]^.reg,
taicpu(p).oper[2]^.shifterop^);
end
else
if taicpu(hp1).ops = 3 then if taicpu(hp1).ops = 3 then
hp2:=taicpu.op_reg_reg_reg_shifterop(taicpu(hp1).opcode, hp2:=taicpu.op_reg_reg_reg_shifterop(tempop,
taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[1]^.reg, taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[2]^.reg,
taicpu(p).oper[1]^.reg, taicpu(p).oper[2]^.shifterop^) taicpu(p).oper[1]^.reg, taicpu(p).oper[2]^.shifterop^)
else else
hp2:=taicpu.op_reg_reg_shifterop(taicpu(hp1).opcode, hp2:=taicpu.op_reg_reg_shifterop(tempop,
taicpu(hp1).oper[0]^.reg, taicpu(p).oper[1]^.reg, taicpu(hp1).oper[0]^.reg, taicpu(p).oper[1]^.reg,
taicpu(p).oper[2]^.shifterop^); taicpu(p).oper[2]^.shifterop^);
asml.insertbefore(hp2, p); end
asml.remove(p); else
asml.remove(hp1); if taicpu(hp1).ops = 3 then
p.free; hp2:=taicpu.op_reg_reg_reg_shifterop(taicpu(hp1).opcode,
hp1.free; taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[1]^.reg,
p:=hp2; taicpu(p).oper[1]^.reg, taicpu(p).oper[2]^.shifterop^)
GetNextInstruction(p,hp1); else
DebugMsg('Peephole FoldShiftProcess done', p); hp2:=taicpu.op_reg_reg_shifterop(taicpu(hp1).opcode,
break; taicpu(hp1).oper[0]^.reg, taicpu(p).oper[1]^.reg,
end; taicpu(p).oper[2]^.shifterop^);
ReleaseUsedRegs(TmpUsedRegs); asml.insertbefore(hp2, hp1);
asml.remove(p);
asml.remove(hp1);
p.free;
hp1.free;
p:=hp2;
GetNextInstruction(p,hp1);
DebugMsg('Peephole FoldShiftProcess done', p);
break;
end;
end; end;
{ {