* arm / a64: Factored out common conditional checks in "OptPass1UXTB",

"OptPass1SXTB", "OptPass1UXTH" and "OptPass1SXTH" to
               improve performance.
This commit is contained in:
J. Gareth "Curious Kit" Moreton 2024-05-13 22:09:22 +01:00 committed by FPK
parent 6de766e40a
commit b1a9150160

View File

@ -211,8 +211,7 @@ Implementation
opoffset: Integer; opoffset: Integer;
begin begin
Result:=false; Result:=false;
if (taicpu(p).ops=2) and if ((MatchInstruction(hp1, [A_ADD,A_SUB], [C_None], [PF_None,PF_S]) and
((MatchInstruction(hp1, [A_ADD,A_SUB], [C_None], [PF_None,PF_S]) and
(taicpu(hp1).ops=3) and (taicpu(hp1).ops=3) and
MatchOperand(taicpu(hp1).oper[2]^, taicpu(p).oper[0]^.reg) and MatchOperand(taicpu(hp1).oper[2]^, taicpu(p).oper[0]^.reg) and
not(MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg))) or not(MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg))) or
@ -682,107 +681,107 @@ Implementation
so: tshifterop; so: tshifterop;
begin begin
Result:=false; Result:=false;
if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) then if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
(taicpu(p).oppostfix = PF_None) and
(taicpu(p).ops = 2) then
begin begin
{ if (taicpu(p).condition = C_None) then
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
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 begin
DebugMsg('Peephole UxtbStrb2Strb done', p); {
taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg); change
result:=RemoveCurrentP(p); uxtb reg2,reg1
end strb reg2,[...]
{ dealloc reg2
change to
uxtb reg2,reg1 strb reg1,[...]
uxth reg3,reg2 }
dealloc reg2 if MatchInstruction(hp1, A_STR, [C_None], [PF_B]) and
to assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) and
uxtb reg3,reg1 { the reference in strb might not use reg2 }
} not(RegInRef(taicpu(p).oper[0]^.reg,taicpu(hp1).oper[1]^.ref^)) and
else if MatchInstruction(p, A_UXTB, [C_None], [PF_None]) and { reg1 might not be modified inbetween }
(taicpu(p).ops=2) and not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
MatchInstruction(hp1, A_UXTH, [C_None], [PF_None]) and begin
(taicpu(hp1).ops = 2) and DebugMsg('Peephole UxtbStrb2Strb done', p);
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and result:=RemoveCurrentP(p);
{ reg1 might not be modified inbetween } end
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then {
begin change
DebugMsg('Peephole UxtbUxth2Uxtb done', p); uxtb reg2,reg1
AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs); uxth reg3,reg2
taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg); dealloc reg2
asml.remove(hp1); to
hp1.free; uxtb reg3,reg1
result:=true; }
end else if MatchInstruction(hp1, A_UXTH, [C_None], [PF_None]) and
{ (taicpu(hp1).ops = 2) and
change MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
uxtb reg2,reg1 RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
uxtb reg3,reg2 { reg1 might not be modified inbetween }
dealloc reg2 not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
to begin
uxtb reg3,reg1 DebugMsg('Peephole UxtbUxth2Uxtb done', p);
} AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs);
else if MatchInstruction(p, A_UXTB, [C_None], [PF_None]) and taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg);
(taicpu(p).ops=2) and asml.remove(hp1);
MatchInstruction(hp1, A_UXTB, [C_None], [PF_None]) and hp1.free;
(taicpu(hp1).ops = 2) and result:=true;
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and end
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and {
{ reg1 might not be modified inbetween } change
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then uxtb reg2,reg1
begin uxtb reg3,reg2
DebugMsg('Peephole UxtbUxtb2Uxtb done', p); dealloc reg2
AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs); to
taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg); uxtb reg3,reg1
asml.remove(hp1); }
hp1.free; else if MatchInstruction(hp1, A_UXTB, [C_None], [PF_None]) and
result:=true; (taicpu(hp1).ops = 2) and
end MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
{ RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
change { reg1 might not be modified inbetween }
uxtb reg2,reg1 not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
and reg3,reg2,#0x*FF begin
dealloc reg2 DebugMsg('Peephole UxtbUxtb2Uxtb done', p);
to AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs);
uxtb reg3,reg1 taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg);
} asml.remove(hp1);
else if MatchInstruction(p, A_UXTB, [C_None], [PF_None]) and hp1.free;
(taicpu(p).ops=2) and result:=true;
MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and end
(taicpu(hp1).ops=3) and {
(taicpu(hp1).oper[2]^.typ=top_const) and change
((taicpu(hp1).oper[2]^.val and $FF)=$FF) and uxtb reg2,reg1
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and and reg3,reg2,#0x*FF
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and dealloc reg2
{ reg1 might not be modified inbetween } to
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then uxtb reg3,reg1
begin }
DebugMsg('Peephole UxtbAndImm2Uxtb done', p); else if MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and
taicpu(hp1).opcode:=A_UXTB; (taicpu(hp1).ops=3) and
taicpu(hp1).ops:=2; (taicpu(hp1).oper[2]^.typ=top_const) and
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg); ((taicpu(hp1).oper[2]^.val and $FF)=$FF) and
result:=RemoveCurrentP(p); MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
end 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);
result:=RemoveCurrentP(p);
end
{$ifdef AARCH64} {$ifdef AARCH64}
else if USxtOp2Op(p,hp1,SM_UXTB) then else if USxtOp2Op(p,hp1,SM_UXTB) then
Result:=true Result:=true
{$endif AARCH64} {$endif AARCH64}
else if RemoveSuperfluousMove(p, hp1, 'UxtbMov2Uxtb') then end;
{ Condition doesn't have to be C_None }
if not Result and
RemoveSuperfluousMove(p, hp1, 'UxtbMov2Uxtb') then
Result:=true; Result:=true;
end; end;
end; end;
@ -794,82 +793,84 @@ Implementation
so: tshifterop; so: tshifterop;
begin begin
Result:=false; Result:=false;
if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) then if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
(taicpu(p).oppostfix = PF_None) and
(taicpu(p).ops = 2) then
begin begin
{ if (taicpu(p).condition = C_None) then
change
uxth reg2,reg1
strh reg2,[...]
dealloc reg2
to
strh reg1,[...]
}
if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
(taicpu(p).ops=2) and
MatchInstruction(hp1, A_STR, [C_None], [PF_H]) and
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) 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 begin
DebugMsg('Peephole UXTHStrh2Strh done', p); {
taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg); change
result:=RemoveCurrentP(p); uxth reg2,reg1
end strh reg2,[...]
{ dealloc reg2
change to
uxth reg2,reg1 strh reg1,[...]
uxth reg3,reg2 }
dealloc reg2 if MatchInstruction(hp1, A_STR, [C_None], [PF_H]) and
to RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
uxth reg3,reg1 { the reference in strb might not use reg2 }
} not(RegInRef(taicpu(p).oper[0]^.reg,taicpu(hp1).oper[1]^.ref^)) and
else if MatchInstruction(p, A_UXTH, [C_None], [PF_None]) and { reg1 might not be modified inbetween }
(taicpu(p).ops=2) and not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
MatchInstruction(hp1, A_UXTH, [C_None], [PF_None]) and begin
(taicpu(hp1).ops=2) and DebugMsg('Peephole UXTHStrh2Strh done', p);
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and result:=RemoveCurrentP(p);
{ reg1 might not be modified inbetween } end
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then {
begin change
DebugMsg('Peephole UxthUxth2Uxth done', p); uxth reg2,reg1
AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,UsedRegs); uxth reg3,reg2
taicpu(hp1).opcode:=A_UXTH; dealloc reg2
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg); to
result:=RemoveCurrentP(p); uxth reg3,reg1
end }
{ else if MatchInstruction(hp1, A_UXTH, [C_None], [PF_None]) and
change (taicpu(hp1).ops=2) and
uxth reg2,reg1 MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
and reg3,reg2,#65535 RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
dealloc reg2 { reg1 might not be modified inbetween }
to not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
uxth reg3,reg1 begin
} DebugMsg('Peephole UxthUxth2Uxth done', p);
else if MatchInstruction(p, A_UXTH, [C_None], [PF_None]) and AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,UsedRegs);
(taicpu(p).ops=2) and taicpu(hp1).opcode:=A_UXTH;
MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
(taicpu(hp1).ops=3) and result:=RemoveCurrentP(p);
(taicpu(hp1).oper[2]^.typ=top_const) and end
((taicpu(hp1).oper[2]^.val and $FFFF)=$FFFF) and {
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and change
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and uxth reg2,reg1
{ reg1 might not be modified inbetween } and reg3,reg2,#65535
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then dealloc reg2
begin to
DebugMsg('Peephole UxthAndImm2Uxth done', p); uxth reg3,reg1
taicpu(hp1).opcode:=A_UXTH; }
taicpu(hp1).ops:=2; else if MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg); (taicpu(hp1).ops=3) and
result:=RemoveCurrentP(p); (taicpu(hp1).oper[2]^.typ=top_const) and
end ((taicpu(hp1).oper[2]^.val and $FFFF)=$FFFF) 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 UxthAndImm2Uxth done', p);
taicpu(hp1).opcode:=A_UXTH;
taicpu(hp1).ops:=2;
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
result:=RemoveCurrentP(p);
end
{$ifdef AARCH64} {$ifdef AARCH64}
else if USxtOp2Op(p,hp1,SM_UXTH) then else if USxtOp2Op(p,hp1,SM_UXTH) then
Result:=true Result:=true
{$endif AARCH64} {$endif AARCH64}
else if RemoveSuperfluousMove(p, hp1, 'UxthMov2Data') then end;
{ Condition doesn't have to be C_None }
if not Result and
RemoveSuperfluousMove(p, hp1, 'UxthMov2Data') then
Result:=true; Result:=true;
end; end;
end; end;
@ -881,107 +882,106 @@ Implementation
so: tshifterop; so: tshifterop;
begin begin
Result:=false; Result:=false;
if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) then if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
(taicpu(p).oppostfix = PF_None) and
(taicpu(p).ops = 2) then
begin begin
{ if (taicpu(p).condition = C_None) then
change
sxtb 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
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 begin
DebugMsg('Peephole SxtbStrb2Strb done', p); {
taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg); change
result:=RemoveCurrentP(p); sxtb reg2,reg1
end strb reg2,[...]
{ dealloc reg2
change to
sxtb reg2,reg1 strb reg1,[...]
sxth reg3,reg2 }
dealloc reg2 if MatchInstruction(hp1, A_STR, [C_None], [PF_B]) and
to assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) and
sxtb reg3,reg1 { the reference in strb might not use reg2 }
} not(RegInRef(taicpu(p).oper[0]^.reg,taicpu(hp1).oper[1]^.ref^)) and
else if MatchInstruction(p, A_SXTB, [C_None], [PF_None]) and { reg1 might not be modified inbetween }
(taicpu(p).ops=2) and not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
MatchInstruction(hp1, A_SXTH, [C_None], [PF_None]) and begin
(taicpu(hp1).ops = 2) and DebugMsg('Peephole SxtbStrb2Strb done', p);
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and result:=RemoveCurrentP(p);
{ reg1 might not be modified inbetween } end
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then {
begin change
DebugMsg('Peephole SxtbSxth2Sxtb done', p); sxtb reg2,reg1
AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs); sxth reg3,reg2
taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg); dealloc reg2
asml.remove(hp1); to
hp1.free; sxtb reg3,reg1
result:=true; }
end else if MatchInstruction(hp1, A_SXTH, [C_None], [PF_None]) and
{ (taicpu(hp1).ops = 2) and
change MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
sxtb reg2,reg1 RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
sxtb reg3,reg2 { reg1 might not be modified inbetween }
dealloc reg2 not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
to begin
uxtb reg3,reg1 DebugMsg('Peephole SxtbSxth2Sxtb done', p);
} AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs);
else if MatchInstruction(p, A_SXTB, [C_None], [PF_None]) and taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg);
(taicpu(p).ops=2) and asml.remove(hp1);
MatchInstruction(hp1, A_SXTB, [C_None], [PF_None]) and hp1.free;
(taicpu(hp1).ops = 2) and result:=true;
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and end
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and {
{ reg1 might not be modified inbetween } change
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then sxtb reg2,reg1
begin sxtb reg3,reg2
DebugMsg('Peephole SxtbSxtb2Sxtb done', p); dealloc reg2
AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs); to
taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg); uxtb reg3,reg1
asml.remove(hp1); }
hp1.free; else if MatchInstruction(hp1, A_SXTB, [C_None], [PF_None]) and
result:=true; (taicpu(hp1).ops = 2) and
end MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
{ RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
change { reg1 might not be modified inbetween }
sxtb reg2,reg1 not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
and reg3,reg2,#0x*FF begin
dealloc reg2 DebugMsg('Peephole SxtbSxtb2Sxtb done', p);
to AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs);
uxtb reg3,reg1 taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg);
} asml.remove(hp1);
else if MatchInstruction(p, A_SXTB, [C_None], [PF_None]) and hp1.free;
(taicpu(p).ops=2) and result:=true;
MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and end
(taicpu(hp1).ops=3) and {
(taicpu(hp1).oper[2]^.typ=top_const) and change
((taicpu(hp1).oper[2]^.val and $FF)=$FF) and sxtb reg2,reg1
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and and reg3,reg2,#0x*FF
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and dealloc reg2
{ reg1 might not be modified inbetween } to
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then uxtb reg3,reg1
begin }
DebugMsg('Peephole SxtbAndImm2Uxtb done', p); else if MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and
taicpu(hp1).opcode:=A_UXTB; (taicpu(hp1).ops=3) and
taicpu(hp1).ops:=2; (taicpu(hp1).oper[2]^.typ=top_const) and
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg); ((taicpu(hp1).oper[2]^.val and $FF)=$FF) and
result:=RemoveCurrentP(p); MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
end 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 SxtbAndImm2Uxtb done', p);
taicpu(hp1).opcode:=A_UXTB;
taicpu(hp1).ops:=2;
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
result:=RemoveCurrentP(p);
end
{$ifdef AARCH64} {$ifdef AARCH64}
else if USxtOp2Op(p,hp1,SM_SXTB) then else if USxtOp2Op(p,hp1,SM_SXTB) then
Result:=true Result:=true
{$endif AARCH64} {$endif AARCH64}
else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and end;
{ Condition doesn't have to be C_None }
if not Result and
RemoveSuperfluousMove(p, hp1, 'SxtbMov2Sxtb') then RemoveSuperfluousMove(p, hp1, 'SxtbMov2Sxtb') then
Result:=true; Result:=true;
end; end;
@ -994,107 +994,114 @@ Implementation
so: tshifterop; so: tshifterop;
begin begin
Result:=false; Result:=false;
if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) then if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
(taicpu(p).oppostfix = PF_None) and
(taicpu(p).ops = 2) then
begin begin
{ if (taicpu(p).condition = C_None) then
change
sxth reg2,reg1
strh reg2,[...]
dealloc reg2
to
strh reg1,[...]
}
if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
(taicpu(p).ops=2) and
MatchInstruction(hp1, A_STR, [C_None], [PF_H]) and
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) 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 begin
DebugMsg('Peephole SxthStrh2Strh done', p); {
taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg); change
result:=RemoveCurrentP(p); sxth reg2,reg1
end strh reg2,[...]
{ dealloc reg2
change to
sxth reg2,reg1 strh reg1,[...]
sxth reg3,reg2 }
dealloc reg2 if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
to (taicpu(p).ops=2) and
sxth reg3,reg1 MatchInstruction(hp1, A_STR, [C_None], [PF_H]) and
} RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
else if MatchInstruction(p, A_SXTH, [C_None], [PF_None]) and { the reference in strb might not use reg2 }
(taicpu(p).ops=2) and not(RegInRef(taicpu(p).oper[0]^.reg,taicpu(hp1).oper[1]^.ref^)) and
MatchInstruction(hp1, A_SXTH, [C_None], [PF_None]) and { reg1 might not be modified inbetween }
(taicpu(hp1).ops=2) and not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and begin
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and DebugMsg('Peephole SxthStrh2Strh done', p);
{ reg1 might not be modified inbetween } taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then result:=RemoveCurrentP(p);
begin end
DebugMsg('Peephole SxthSxth2Sxth done', p); {
AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,UsedRegs); change
taicpu(hp1).opcode:=A_SXTH; sxth reg2,reg1
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg); sxth reg3,reg2
result:=RemoveCurrentP(p); dealloc reg2
end to
sxth reg3,reg1
}
else if MatchInstruction(p, A_SXTH, [C_None], [PF_None]) and
(taicpu(p).ops=2) and
MatchInstruction(hp1, A_SXTH, [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 SxthSxth2Sxth done', p);
AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,UsedRegs);
taicpu(hp1).opcode:=A_SXTH;
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
result:=RemoveCurrentP(p);
end
{$ifdef AARCH64} {$ifdef AARCH64}
{ {
change change
sxth reg2,reg1 sxth reg2,reg1
sxtw reg3,reg2 sxtw reg3,reg2
dealloc reg2 dealloc reg2
to to
sxth reg3,reg1 sxth reg3,reg1
} }
else if MatchInstruction(p, A_SXTH, [C_None], [PF_None]) and else if MatchInstruction(p, A_SXTH, [C_None], [PF_None]) and
(taicpu(p).ops=2) and (taicpu(p).ops=2) and
MatchInstruction(hp1, A_SXTW, [C_None], [PF_None]) and MatchInstruction(hp1, A_SXTW, [C_None], [PF_None]) and
(taicpu(hp1).ops=2) and (taicpu(hp1).ops=2) and
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
{ 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 SxthSxtw2Sxth done', p); DebugMsg('Peephole SxthSxtw2Sxth done', p);
AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,UsedRegs); AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,UsedRegs);
taicpu(hp1).opcode:=A_SXTH; taicpu(hp1).opcode:=A_SXTH;
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg); taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
result:=RemoveCurrentP(p); result:=RemoveCurrentP(p);
end end
{$endif AARCH64} {$endif AARCH64}
{ {
change change
sxth reg2,reg1 sxth reg2,reg1
and reg3,reg2,#65535 and reg3,reg2,#65535
dealloc reg2 dealloc reg2
to to
uxth reg3,reg1 uxth reg3,reg1
} }
else if MatchInstruction(p, A_SXTH, [C_None], [PF_None]) and else if MatchInstruction(p, A_SXTH, [C_None], [PF_None]) and
(taicpu(p).ops=2) and (taicpu(p).ops=2) and
MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and
(taicpu(hp1).ops=3) and (taicpu(hp1).ops=3) and
(taicpu(hp1).oper[2]^.typ=top_const) and (taicpu(hp1).oper[2]^.typ=top_const) and
((taicpu(hp1).oper[2]^.val and $FFFF)=$FFFF) and ((taicpu(hp1).oper[2]^.val and $FFFF)=$FFFF) and
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
{ 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 SxthAndImm2Uxth done', p); DebugMsg('Peephole SxthAndImm2Uxth done', p);
taicpu(hp1).opcode:=A_UXTH; taicpu(hp1).opcode:=A_UXTH;
taicpu(hp1).ops:=2; taicpu(hp1).ops:=2;
taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg); taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
result:=RemoveCurrentP(p); result:=RemoveCurrentP(p);
end end
{$ifdef AARCH64} {$ifdef AARCH64}
else if USxtOp2Op(p,hp1,SM_SXTH) then else if USxtOp2Op(p,hp1,SM_SXTH) then
Result:=true Result:=true
{$endif AARCH64} {$endif AARCH64}
else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and end;
{ Condition doesn't have to be C_None }
if not Result and
RemoveSuperfluousMove(p, hp1, 'SxthMov2Sxth') then RemoveSuperfluousMove(p, hp1, 'SxthMov2Sxth') then
Result:=true; Result:=true;
end; end;