mirror of
https://github.com/FEX-Emu/FEX.git
synced 2024-12-14 01:18:46 +00:00
IR: add coalescing heuristics for pair replacements
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
parent
f4b5c4e69a
commit
a9c26cbf71
@ -19,6 +19,7 @@ namespace FEXCore::CPU {
|
||||
#define DEF_OP(x) void Arm64JITCore::Op_##x(IR::IROp_Header const* IROp, IR::NodeID Node)
|
||||
|
||||
DEF_OP(AllocateGPR) {}
|
||||
DEF_OP(AllocateGPRAfter) {}
|
||||
|
||||
DEF_OP(GuestOpcode) {
|
||||
auto Op = IROp->C<IR::IROp_GuestOpcode>();
|
||||
|
@ -3309,8 +3309,8 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) {
|
||||
SrcAddr = _Add(OpSize::i64Bit, SrcAddr, SrcSegment);
|
||||
}
|
||||
|
||||
Ref Result_Src = _AllocateGPR();
|
||||
Ref Result_Dst = _AllocateGPR();
|
||||
Ref Result_Src = _AllocateGPR(false);
|
||||
Ref Result_Dst = _AllocateGPR(false);
|
||||
_MemCpy(CTX->IsAtomicTSOEnabled(), Size, DstAddr, SrcAddr, Counter, LoadDir(1), Result_Dst, Result_Src);
|
||||
|
||||
if (DstSegment) {
|
||||
@ -3993,8 +3993,8 @@ void OpDispatchBuilder::CMPXCHGPairOp(OpcodeArgs) {
|
||||
// This will write to memory! Careful!
|
||||
// Third operand must be a calculated guest memory address
|
||||
|
||||
Ref Result_Lower = _AllocateGPR();
|
||||
Ref Result_Upper = _AllocateGPR();
|
||||
Ref Result_Lower = _AllocateGPR(true);
|
||||
Ref Result_Upper = _AllocateGPRAfter(Result_Lower);
|
||||
_CASPair(IR::SizeToOpSize(Size), Expected_Lower, Expected_Upper, Desired_Lower, Desired_Upper, Src1, Result_Lower, Result_Upper);
|
||||
|
||||
HandleNZCV_RMW();
|
||||
|
@ -252,9 +252,17 @@
|
||||
"WalkFindRegClass($Value) != GPRPairClass"
|
||||
]
|
||||
},
|
||||
"GPR = AllocateGPR": {
|
||||
"GPR = AllocateGPR i1:$ForPair": {
|
||||
"Desc": ["Silly pseudo-instruction to allocate a register for a future destination",
|
||||
"This is a kludge to deal with the IR's lack of multiple destinations"],
|
||||
"This is a kludge to deal with the IR's lack of multiple destinations",
|
||||
"If ForPair is set, RA will try to allocate the base of a register pair"],
|
||||
"DestSize": "8"
|
||||
},
|
||||
"GPR = AllocateGPRAfter GPR:$After": {
|
||||
"Desc": ["Silly pseudo-instruction to allocate a register for a future destination",
|
||||
"This is a kludge to deal with the IR's lack of multiple destinations",
|
||||
"RA will attempt to allocate to the register after $After.",
|
||||
"It may not succeed."],
|
||||
"DestSize": "8"
|
||||
},
|
||||
"GPR = RDRAND i1:$GetReseeded": {
|
||||
|
@ -411,6 +411,25 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// Try to coalesce reserved pairs. Just a heuristic to remove some moves.
|
||||
if (IROp->Op == OP_ALLOCATEGPR) {
|
||||
if (IROp->C<IROp_AllocateGPR>()->ForPair) {
|
||||
uint32_t Available = AvailableMask(&Classes[GPRClass], true);
|
||||
if (Available) {
|
||||
unsigned Reg = std::countr_zero(Available);
|
||||
SetReg(CodeNode, PhysicalRegister(GPRClass, Reg));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (IROp->Op == OP_ALLOCATEGPRAFTER) {
|
||||
uint32_t Available = AvailableMask(&Classes[GPRClass], false);
|
||||
auto After = SSAToReg[IR->GetID(IR->GetNode(IROp->Args[0])).Value];
|
||||
if ((After.Reg & 1) == 0 && Available & (1ull << (After.Reg + 1))) {
|
||||
SetReg(CodeNode, PhysicalRegister(GPRClass, After.Reg + 1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RegisterClassType OrigClassType = GetRegClassFromNode(IR, IROp);
|
||||
bool Pair = OrigClassType == GPRPairClass;
|
||||
RegisterClassType ClassType = Pair ? GPRClass : OrigClassType;
|
||||
|
Loading…
Reference in New Issue
Block a user