IR: add coalescing heuristics for pair replacements

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig 2024-08-10 17:22:38 -04:00
parent f4b5c4e69a
commit a9c26cbf71
4 changed files with 34 additions and 6 deletions

View File

@ -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>();

View File

@ -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();

View File

@ -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": {

View File

@ -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;