|
@@ -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
|
|
|
|
- if MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[I]^.reg) then
|
|
|
|
- begin
|
|
|
|
- { If the parameter matched on the second op from the RIGHT
|
|
|
|
- we have to switch the parameters, this will not happen for CMP
|
|
|
|
- were we're only evaluating the most right parameter
|
|
|
|
- }
|
|
|
|
- if I <> taicpu(hp1).ops-1 then
|
|
|
|
- begin
|
|
|
|
- {The SUB operators need to be changed when we swap parameters}
|
|
|
|
- case taicpu(hp1).opcode of
|
|
|
|
- A_SUB: tempop:=A_RSB;
|
|
|
|
- A_SBC: tempop:=A_RSC;
|
|
|
|
- A_RSB: tempop:=A_SUB;
|
|
|
|
- A_RSC: tempop:=A_SBC;
|
|
|
|
- else tempop:=taicpu(hp1).opcode;
|
|
|
|
- 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
|
|
|
|
|
|
+ for I:=I2 to taicpu(hp1).ops-1 do
|
|
|
|
+ if MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[I]^.reg) then
|
|
|
|
+ begin
|
|
|
|
+ { If the parameter matched on the second op from the RIGHT
|
|
|
|
+ we have to switch the parameters, this will not happen for CMP
|
|
|
|
+ were we're only evaluating the most right parameter
|
|
|
|
+ }
|
|
|
|
+ if I <> taicpu(hp1).ops-1 then
|
|
|
|
+ begin
|
|
|
|
+ {The SUB operators need to be changed when we swap parameters}
|
|
|
|
+ case taicpu(hp1).opcode of
|
|
|
|
+ A_SUB: tempop:=A_RSB;
|
|
|
|
+ A_SBC: tempop:=A_RSC;
|
|
|
|
+ A_RSB: tempop:=A_SUB;
|
|
|
|
+ A_RSC: tempop:=A_SBC;
|
|
|
|
+ else tempop:=taicpu(hp1).opcode;
|
|
|
|
+ end;
|
|
if taicpu(hp1).ops = 3 then
|
|
if taicpu(hp1).ops = 3 then
|
|
- hp2:=taicpu.op_reg_reg_reg_shifterop(taicpu(hp1).opcode,
|
|
|
|
- taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[1]^.reg,
|
|
|
|
|
|
+ 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^)
|
|
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);
|
|
|
|
- asml.remove(p);
|
|
|
|
- asml.remove(hp1);
|
|
|
|
- p.free;
|
|
|
|
- hp1.free;
|
|
|
|
- p:=hp2;
|
|
|
|
- GetNextInstruction(p,hp1);
|
|
|
|
- DebugMsg('Peephole FoldShiftProcess done', p);
|
|
|
|
- break;
|
|
|
|
- end;
|
|
|
|
- ReleaseUsedRegs(TmpUsedRegs);
|
|
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ if taicpu(hp1).ops = 3 then
|
|
|
|
+ hp2:=taicpu.op_reg_reg_reg_shifterop(taicpu(hp1).opcode,
|
|
|
|
+ taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[1]^.reg,
|
|
|
|
+ taicpu(p).oper[1]^.reg, taicpu(p).oper[2]^.shifterop^)
|
|
|
|
+ else
|
|
|
|
+ hp2:=taicpu.op_reg_reg_shifterop(taicpu(hp1).opcode,
|
|
|
|
+ taicpu(hp1).oper[0]^.reg, taicpu(p).oper[1]^.reg,
|
|
|
|
+ taicpu(p).oper[2]^.shifterop^);
|
|
|
|
+ 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;
|
|
|
|
|
|
{
|
|
{
|