mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-08 21:57:38 +01:00
+ added and implemented function TX86AsmOptimizer.Reg1WriteOverwritesReg2Entirely,
which takes into account how 16-bit and 8-bit subregisters work on the x86 (the new function is not used for now, but is probably going to replace SuperRegistersEqual in a few specific places (in RegLoadedWithNewValue), so that our register tracking becomes more accurate for 8-bit and 16-bit subregisters) git-svn-id: trunk@35990 -
This commit is contained in:
parent
aee000a773
commit
33f9b36a54
@ -38,6 +38,9 @@ unit aoptx86;
|
|||||||
TX86AsmOptimizer = class(TAsmOptimizer)
|
TX86AsmOptimizer = class(TAsmOptimizer)
|
||||||
function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
|
function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
|
||||||
protected
|
protected
|
||||||
|
{ checks whether loading a new value in reg1 overwrites the entirety of reg2 }
|
||||||
|
function Reg1WriteOverwritesReg2Entirely(reg1, reg2: tregister): boolean;
|
||||||
|
|
||||||
procedure PostPeepholeOptMov(const p : tai);
|
procedure PostPeepholeOptMov(const p : tai);
|
||||||
|
|
||||||
function OptPass1AND(var p : tai) : boolean;
|
function OptPass1AND(var p : tai) : boolean;
|
||||||
@ -223,6 +226,43 @@ unit aoptx86;
|
|||||||
{$endif DEBUG_AOPTCPU}
|
{$endif DEBUG_AOPTCPU}
|
||||||
|
|
||||||
|
|
||||||
|
function TX86AsmOptimizer.Reg1WriteOverwritesReg2Entirely(reg1, reg2: tregister): boolean;
|
||||||
|
begin
|
||||||
|
if not SuperRegistersEqual(reg1,reg2) then
|
||||||
|
exit(false);
|
||||||
|
if getregtype(reg1)<>R_INTREGISTER then
|
||||||
|
exit(true); {because SuperRegisterEqual is true}
|
||||||
|
case getsubreg(reg1) of
|
||||||
|
{ A write to R_SUBL doesn't change R_SUBH and if reg2 is R_SUBW or
|
||||||
|
higher, it preserves the high bits, so the new value depends on
|
||||||
|
reg2's previous value. In other words, it is equivalent to doing:
|
||||||
|
|
||||||
|
reg2 := (reg2 and $ffffff00) or byte(reg1); }
|
||||||
|
R_SUBL:
|
||||||
|
exit(getsubreg(reg2)=R_SUBL);
|
||||||
|
{ A write to R_SUBH doesn't change R_SUBL and if reg2 is R_SUBW or
|
||||||
|
higher, it actually does a:
|
||||||
|
|
||||||
|
reg2 := (reg2 and $ffff00ff) or (reg1 and $ff00); }
|
||||||
|
R_SUBH:
|
||||||
|
exit(getsubreg(reg2)=R_SUBH);
|
||||||
|
{ If reg2 is R_SUBD or larger, a write to R_SUBW preserves the high 16
|
||||||
|
bits of reg2:
|
||||||
|
|
||||||
|
reg2 := (reg2 and $ffff0000) or word(reg1); }
|
||||||
|
R_SUBW:
|
||||||
|
exit(getsubreg(reg2) in [R_SUBL,R_SUBH,R_SUBW]);
|
||||||
|
{ a write to R_SUBD always overwrites every other subregister,
|
||||||
|
because it clears the high 32 bits of R_SUBQ on x86_64 }
|
||||||
|
R_SUBD,
|
||||||
|
R_SUBQ:
|
||||||
|
exit(true);
|
||||||
|
else
|
||||||
|
internalerror(2017042801);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ allocates register reg between (and including) instructions p1 and p2
|
{ allocates register reg between (and including) instructions p1 and p2
|
||||||
the type of p1 and p2 must not be in SkipInstr
|
the type of p1 and p2 must not be in SkipInstr
|
||||||
note that this routine is both called from the peephole optimizer
|
note that this routine is both called from the peephole optimizer
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user