mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-04-29 14:59:26 -04:00
PPCRec: Further work on support for typed registers in RA
Additionally there is no more range limit for virtual RegIDs, making the entire uint16 space available in theory
This commit is contained in:
parent
c891abcb74
commit
c786ba0ebb
4 changed files with 159 additions and 212 deletions
|
@ -586,6 +586,24 @@ struct IMLInstruction
|
||||||
operation = 0;
|
operation = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void make_r_name(IMLReg regR, IMLName name)
|
||||||
|
{
|
||||||
|
cemu_assert_debug(regR.GetBaseFormat() == regR.GetRegFormat()); // for name load/store instructions the register must match the base format
|
||||||
|
type = PPCREC_IML_TYPE_R_NAME;
|
||||||
|
operation = PPCREC_IML_OP_ASSIGN;
|
||||||
|
op_r_name.regR = regR;
|
||||||
|
op_r_name.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void make_name_r(IMLName name, IMLReg regR)
|
||||||
|
{
|
||||||
|
cemu_assert_debug(regR.GetBaseFormat() == regR.GetRegFormat()); // for name load/store instructions the register must match the base format
|
||||||
|
type = PPCREC_IML_TYPE_NAME_R;
|
||||||
|
operation = PPCREC_IML_OP_ASSIGN;
|
||||||
|
op_r_name.regR = regR;
|
||||||
|
op_r_name.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
void make_debugbreak(uint32 currentPPCAddress = 0)
|
void make_debugbreak(uint32 currentPPCAddress = 0)
|
||||||
{
|
{
|
||||||
make_macro(PPCREC_IML_MACRO_DEBUGBREAK, 0, currentPPCAddress, 0, IMLREG_INVALID);
|
make_macro(PPCREC_IML_MACRO_DEBUGBREAK, 0, currentPPCAddress, 0, IMLREG_INVALID);
|
||||||
|
|
|
@ -118,107 +118,6 @@ void PPCRecRA_identifyLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* iml
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//typedef struct
|
|
||||||
//{
|
|
||||||
// sint32 name;
|
|
||||||
// sint32 virtualRegister;
|
|
||||||
// sint32 physicalRegister;
|
|
||||||
// bool isDirty;
|
|
||||||
//}raRegisterState_t;
|
|
||||||
|
|
||||||
//const sint32 _raInfo_physicalGPRCount = PPC_X64_GPR_USABLE_REGISTERS;
|
|
||||||
//
|
|
||||||
//raRegisterState_t* PPCRecRA_getRegisterState(raRegisterState_t* regState, sint32 virtualRegister)
|
|
||||||
//{
|
|
||||||
// for (sint32 i = 0; i < _raInfo_physicalGPRCount; i++)
|
|
||||||
// {
|
|
||||||
// if (regState[i].virtualRegister == virtualRegister)
|
|
||||||
// {
|
|
||||||
//#ifdef CEMU_DEBUG_ASSERT
|
|
||||||
// if (regState[i].physicalRegister < 0)
|
|
||||||
// assert_dbg();
|
|
||||||
//#endif
|
|
||||||
// return regState + i;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return nullptr;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//raRegisterState_t* PPCRecRA_getFreePhysicalRegister(raRegisterState_t* regState)
|
|
||||||
//{
|
|
||||||
// for (sint32 i = 0; i < _raInfo_physicalGPRCount; i++)
|
|
||||||
// {
|
|
||||||
// if (regState[i].physicalRegister < 0)
|
|
||||||
// {
|
|
||||||
// regState[i].physicalRegister = i;
|
|
||||||
// return regState + i;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return nullptr;
|
|
||||||
//}
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
IMLRegID registerIndex;
|
|
||||||
uint16 registerName;
|
|
||||||
}raLoadStoreInfo_t;
|
|
||||||
|
|
||||||
IMLReg _MakeNativeGPR(IMLRegID regId)
|
|
||||||
{
|
|
||||||
return IMLReg(IMLRegFormat::I64, IMLRegFormat::I64, 0, regId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PPCRecRA_insertGPRLoadInstruction(IMLSegment* imlSegment, sint32 insertIndex, IMLRegID registerIndex, sint32 registerName)
|
|
||||||
{
|
|
||||||
PPCRecompiler_pushBackIMLInstructions(imlSegment, insertIndex, 1);
|
|
||||||
IMLInstruction* imlInstructionItr = imlSegment->imlList.data() + (insertIndex + 0);
|
|
||||||
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
|
|
||||||
imlInstructionItr->type = PPCREC_IML_TYPE_R_NAME;
|
|
||||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
|
||||||
imlInstructionItr->op_r_name.regR = _MakeNativeGPR(registerIndex);
|
|
||||||
imlInstructionItr->op_r_name.name = registerName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PPCRecRA_insertGPRLoadInstructions(IMLSegment* imlSegment, sint32 insertIndex, raLoadStoreInfo_t* loadList, sint32 loadCount)
|
|
||||||
{
|
|
||||||
PPCRecompiler_pushBackIMLInstructions(imlSegment, insertIndex, loadCount);
|
|
||||||
memset(imlSegment->imlList.data() + (insertIndex + 0), 0x00, sizeof(IMLInstruction)*loadCount);
|
|
||||||
for (sint32 i = 0; i < loadCount; i++)
|
|
||||||
{
|
|
||||||
IMLInstruction* imlInstructionItr = imlSegment->imlList.data() + (insertIndex + i);
|
|
||||||
imlInstructionItr->type = PPCREC_IML_TYPE_R_NAME;
|
|
||||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
|
||||||
imlInstructionItr->op_r_name.regR = _MakeNativeGPR(loadList[i].registerIndex);
|
|
||||||
imlInstructionItr->op_r_name.name = (uint32)loadList[i].registerName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PPCRecRA_insertGPRStoreInstruction(IMLSegment* imlSegment, sint32 insertIndex, IMLRegID registerIndex, sint32 registerName)
|
|
||||||
{
|
|
||||||
PPCRecompiler_pushBackIMLInstructions(imlSegment, insertIndex, 1);
|
|
||||||
IMLInstruction* imlInstructionItr = imlSegment->imlList.data() + (insertIndex + 0);
|
|
||||||
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
|
|
||||||
imlInstructionItr->type = PPCREC_IML_TYPE_NAME_R;
|
|
||||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
|
||||||
imlInstructionItr->op_r_name.regR = _MakeNativeGPR(registerIndex);
|
|
||||||
imlInstructionItr->op_r_name.name = registerName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PPCRecRA_insertGPRStoreInstructions(IMLSegment* imlSegment, sint32 insertIndex, raLoadStoreInfo_t* storeList, sint32 storeCount)
|
|
||||||
{
|
|
||||||
PPCRecompiler_pushBackIMLInstructions(imlSegment, insertIndex, storeCount);
|
|
||||||
memset(imlSegment->imlList.data() + (insertIndex + 0), 0x00, sizeof(IMLInstruction)*storeCount);
|
|
||||||
for (sint32 i = 0; i < storeCount; i++)
|
|
||||||
{
|
|
||||||
IMLInstruction* imlInstructionItr = imlSegment->imlList.data() + (insertIndex + i);
|
|
||||||
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
|
|
||||||
imlInstructionItr->type = PPCREC_IML_TYPE_NAME_R;
|
|
||||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
|
||||||
imlInstructionItr->op_r_name.regR = _MakeNativeGPR(storeList[i].registerIndex);
|
|
||||||
imlInstructionItr->op_r_name.name = (uint32)storeList[i].registerName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SUBRANGE_LIST_SIZE (128)
|
#define SUBRANGE_LIST_SIZE (128)
|
||||||
|
|
||||||
sint32 PPCRecRA_countInstructionsUntilNextUse(raLivenessSubrange_t* subrange, sint32 startIndex)
|
sint32 PPCRecRA_countInstructionsUntilNextUse(raLivenessSubrange_t* subrange, sint32 startIndex)
|
||||||
|
@ -407,10 +306,23 @@ void _sortSegmentAllSubrangesLinkedList(IMLSegment* imlSegment)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_map<IMLRegID, raLivenessSubrange_t*>& IMLRA_GetSubrangeMap(IMLSegment* imlSegment)
|
||||||
|
{
|
||||||
|
return imlSegment->raInfo.linkedList_perVirtualGPR2;
|
||||||
|
}
|
||||||
|
|
||||||
|
raLivenessSubrange_t* IMLRA_GetSubrange(IMLSegment* imlSegment, IMLRegID regId)
|
||||||
|
{
|
||||||
|
auto it = imlSegment->raInfo.linkedList_perVirtualGPR2.find(regId);
|
||||||
|
if (it == imlSegment->raInfo.linkedList_perVirtualGPR2.end())
|
||||||
|
return nullptr;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
raLivenessSubrange_t* _GetSubrangeByInstructionIndexAndVirtualReg(IMLSegment* imlSegment, IMLReg regToSearch, sint32 instructionIndex)
|
raLivenessSubrange_t* _GetSubrangeByInstructionIndexAndVirtualReg(IMLSegment* imlSegment, IMLReg regToSearch, sint32 instructionIndex)
|
||||||
{
|
{
|
||||||
uint32 regId = regToSearch.GetRegID();
|
uint32 regId = regToSearch.GetRegID();
|
||||||
raLivenessSubrange_t* subrangeItr = imlSegment->raInfo.linkedList_perVirtualGPR[regId];
|
raLivenessSubrange_t* subrangeItr = IMLRA_GetSubrange(imlSegment, regId);
|
||||||
while (subrangeItr)
|
while (subrangeItr)
|
||||||
{
|
{
|
||||||
if (subrangeItr->start.index <= instructionIndex && subrangeItr->end.index > instructionIndex)
|
if (subrangeItr->start.index <= instructionIndex && subrangeItr->end.index > instructionIndex)
|
||||||
|
@ -763,8 +675,10 @@ void IMLRA_AssignRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenContext_t*
|
||||||
|
|
||||||
struct subrangeEndingInfo_t
|
struct subrangeEndingInfo_t
|
||||||
{
|
{
|
||||||
|
//boost::container::small_vector<raLivenessSubrange_t*, 32> subrangeList2;
|
||||||
raLivenessSubrange_t* subrangeList[SUBRANGE_LIST_SIZE];
|
raLivenessSubrange_t* subrangeList[SUBRANGE_LIST_SIZE];
|
||||||
sint32 subrangeCount;
|
sint32 subrangeCount;
|
||||||
|
|
||||||
bool hasUndefinedEndings;
|
bool hasUndefinedEndings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -866,11 +780,35 @@ void _analyzeRangeDataFlow(raLivenessSubrange_t* subrange)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment)
|
inline IMLReg _MakeNativeReg(IMLRegFormat baseFormat, IMLRegID regId)
|
||||||
|
{
|
||||||
|
return IMLReg(baseFormat, baseFormat, 0, regId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPCRecRA_insertGPRLoadInstructions(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment, sint32 insertIndex, std::span<raLivenessSubrange_t*> loadList)
|
||||||
|
{
|
||||||
|
PPCRecompiler_pushBackIMLInstructions(imlSegment, insertIndex, loadList.size());
|
||||||
|
for (sint32 i = 0; i < loadList.size(); i++)
|
||||||
|
{
|
||||||
|
IMLRegFormat baseFormat = ctx.regIdToBaseFormat[loadList[i]->range->virtualRegister];
|
||||||
|
cemu_assert_debug(baseFormat != IMLRegFormat::INVALID_FORMAT);
|
||||||
|
imlSegment->imlList[insertIndex + i].make_r_name(_MakeNativeReg(baseFormat, loadList[i]->range->physicalRegister), loadList[i]->range->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PPCRecRA_insertGPRStoreInstructions(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment, sint32 insertIndex, std::span<raLivenessSubrange_t*> storeList)
|
||||||
|
{
|
||||||
|
PPCRecompiler_pushBackIMLInstructions(imlSegment, insertIndex, storeList.size());
|
||||||
|
for (size_t i = 0; i < storeList.size(); i++)
|
||||||
|
{
|
||||||
|
IMLRegFormat baseFormat = ctx.regIdToBaseFormat[storeList[i]->range->virtualRegister];
|
||||||
|
cemu_assert_debug(baseFormat != IMLRegFormat::INVALID_FORMAT);
|
||||||
|
imlSegment->imlList[insertIndex + i].make_name_r(storeList[i]->range->name, _MakeNativeReg(baseFormat, storeList[i]->range->physicalRegister));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMLRA_GenerateSegmentMoveInstructions(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment)
|
||||||
{
|
{
|
||||||
sint16 virtualReg2PhysReg[IML_RA_VIRT_REG_COUNT_MAX];
|
|
||||||
for (sint32 i = 0; i < IML_RA_VIRT_REG_COUNT_MAX; i++)
|
|
||||||
virtualReg2PhysReg[i] = -1;
|
|
||||||
std::unordered_map<IMLRegID, IMLRegID> virtId2PhysRegIdMap; // key = virtual register, value = physical register
|
std::unordered_map<IMLRegID, IMLRegID> virtId2PhysRegIdMap; // key = virtual register, value = physical register
|
||||||
IMLRALivenessTimeline livenessTimeline;
|
IMLRALivenessTimeline livenessTimeline;
|
||||||
sint32 index = 0;
|
sint32 index = 0;
|
||||||
|
@ -889,11 +827,9 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||||
assert_dbg();
|
assert_dbg();
|
||||||
}
|
}
|
||||||
// update translation table
|
// update translation table
|
||||||
if (virtualReg2PhysReg[subrangeItr->range->virtualRegister] != -1)
|
cemu_assert_debug(!virtId2PhysRegIdMap.contains(subrangeItr->range->virtualRegister));
|
||||||
assert_dbg();
|
|
||||||
#endif
|
#endif
|
||||||
virtualReg2PhysReg[subrangeItr->range->virtualRegister] = subrangeItr->range->physicalRegister;
|
virtId2PhysRegIdMap.try_emplace(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
||||||
virtId2PhysRegIdMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
|
||||||
}
|
}
|
||||||
// next
|
// next
|
||||||
subrangeItr = subrangeItr->link_segmentSubrangesGPR.next;
|
subrangeItr = subrangeItr->link_segmentSubrangesGPR.next;
|
||||||
|
@ -906,15 +842,12 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||||
for (auto& expiredRange : livenessTimeline.GetExpiredRanges())
|
for (auto& expiredRange : livenessTimeline.GetExpiredRanges())
|
||||||
{
|
{
|
||||||
// update translation table
|
// update translation table
|
||||||
if (virtualReg2PhysReg[expiredRange->range->virtualRegister] == -1)
|
|
||||||
assert_dbg();
|
|
||||||
virtualReg2PhysReg[expiredRange->range->virtualRegister] = -1;
|
|
||||||
virtId2PhysRegIdMap.erase(expiredRange->range->virtualRegister);
|
virtId2PhysRegIdMap.erase(expiredRange->range->virtualRegister);
|
||||||
// store GPR if required
|
// store GPR if required
|
||||||
// special care has to be taken to execute any stores before the suffix instruction since trailing instructions may not get executed
|
// special care has to be taken to execute any stores before the suffix instruction since trailing instructions may not get executed
|
||||||
if (expiredRange->hasStore)
|
if (expiredRange->hasStore)
|
||||||
{
|
{
|
||||||
PPCRecRA_insertGPRStoreInstruction(imlSegment, std::min<sint32>(index, imlSegment->imlList.size() - suffixInstructionCount), expiredRange->range->physicalRegister, expiredRange->range->name);
|
PPCRecRA_insertGPRStoreInstructions(ctx, imlSegment, std::min<sint32>(index, imlSegment->imlList.size() - suffixInstructionCount), {&expiredRange, 1});
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -936,13 +869,11 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||||
}
|
}
|
||||||
if (subrangeItr->_noLoad == false)
|
if (subrangeItr->_noLoad == false)
|
||||||
{
|
{
|
||||||
PPCRecRA_insertGPRLoadInstruction(imlSegment, std::min<sint32>(index, imlSegment->imlList.size() - suffixInstructionCount), subrangeItr->range->physicalRegister, subrangeItr->range->name);
|
PPCRecRA_insertGPRLoadInstructions(ctx, imlSegment, std::min<sint32>(index, imlSegment->imlList.size() - suffixInstructionCount), {&subrangeItr , 1});
|
||||||
index++;
|
index++;
|
||||||
subrangeItr->start.index--;
|
subrangeItr->start.index--;
|
||||||
}
|
}
|
||||||
// update translation table
|
// update translation table
|
||||||
cemu_assert_debug(virtualReg2PhysReg[subrangeItr->range->virtualRegister] == -1);
|
|
||||||
virtualReg2PhysReg[subrangeItr->range->virtualRegister] = subrangeItr->range->physicalRegister;
|
|
||||||
virtId2PhysRegIdMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
virtId2PhysRegIdMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
||||||
}
|
}
|
||||||
subrangeItr = subrangeItr->link_segmentSubrangesGPR.next;
|
subrangeItr = subrangeItr->link_segmentSubrangesGPR.next;
|
||||||
|
@ -954,31 +885,22 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
// expire infinite subranges (subranges which cross the segment border)
|
// expire infinite subranges (subranges which cross the segment border)
|
||||||
sint32 storeLoadListLength = 0;
|
std::vector<raLivenessSubrange_t*> loadStoreList;
|
||||||
raLoadStoreInfo_t loadStoreList[IML_RA_VIRT_REG_COUNT_MAX];
|
|
||||||
livenessTimeline.ExpireRanges(RA_INTER_RANGE_END);
|
livenessTimeline.ExpireRanges(RA_INTER_RANGE_END);
|
||||||
for (auto liverange : livenessTimeline.GetExpiredRanges())
|
for (auto liverange : livenessTimeline.GetExpiredRanges())
|
||||||
{
|
{
|
||||||
// update translation table
|
// update translation table
|
||||||
cemu_assert_debug(virtualReg2PhysReg[liverange->range->virtualRegister] != -1);
|
|
||||||
virtualReg2PhysReg[liverange->range->virtualRegister] = -1;
|
|
||||||
virtId2PhysRegIdMap.erase(liverange->range->virtualRegister);
|
virtId2PhysRegIdMap.erase(liverange->range->virtualRegister);
|
||||||
// store GPR
|
// store GPR
|
||||||
if (liverange->hasStore)
|
if (liverange->hasStore)
|
||||||
{
|
loadStoreList.emplace_back(liverange);
|
||||||
loadStoreList[storeLoadListLength].registerIndex = liverange->range->physicalRegister;
|
|
||||||
loadStoreList[storeLoadListLength].registerName = liverange->range->name;
|
|
||||||
storeLoadListLength++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cemu_assert_debug(livenessTimeline.activeRanges.empty());
|
cemu_assert_debug(livenessTimeline.activeRanges.empty());
|
||||||
if (storeLoadListLength > 0)
|
if (!loadStoreList.empty())
|
||||||
{
|
PPCRecRA_insertGPRStoreInstructions(ctx, imlSegment, imlSegment->imlList.size() - suffixInstructionCount, loadStoreList);
|
||||||
PPCRecRA_insertGPRStoreInstructions(imlSegment, imlSegment->imlList.size() - suffixInstructionCount, loadStoreList, storeLoadListLength);
|
|
||||||
}
|
|
||||||
// load subranges for next segments
|
// load subranges for next segments
|
||||||
subrangeItr = imlSegment->raInfo.linkedList_allSubranges;
|
subrangeItr = imlSegment->raInfo.linkedList_allSubranges;
|
||||||
storeLoadListLength = 0;
|
loadStoreList.clear();
|
||||||
while(subrangeItr)
|
while(subrangeItr)
|
||||||
{
|
{
|
||||||
if (subrangeItr->start.index == RA_INTER_RANGE_END)
|
if (subrangeItr->start.index == RA_INTER_RANGE_END)
|
||||||
|
@ -986,31 +908,23 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||||
livenessTimeline.AddActiveRange(subrangeItr);
|
livenessTimeline.AddActiveRange(subrangeItr);
|
||||||
// load GPR
|
// load GPR
|
||||||
if (subrangeItr->_noLoad == false)
|
if (subrangeItr->_noLoad == false)
|
||||||
{
|
loadStoreList.emplace_back(subrangeItr);
|
||||||
loadStoreList[storeLoadListLength].registerIndex = subrangeItr->range->physicalRegister;
|
|
||||||
loadStoreList[storeLoadListLength].registerName = subrangeItr->range->name;
|
|
||||||
storeLoadListLength++;
|
|
||||||
}
|
|
||||||
// update translation table
|
// update translation table
|
||||||
cemu_assert_debug(virtualReg2PhysReg[subrangeItr->range->virtualRegister] == -1);
|
virtId2PhysRegIdMap.try_emplace(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
||||||
virtualReg2PhysReg[subrangeItr->range->virtualRegister] = subrangeItr->range->physicalRegister;
|
|
||||||
virtId2PhysRegIdMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
|
||||||
}
|
}
|
||||||
// next
|
// next
|
||||||
subrangeItr = subrangeItr->link_segmentSubrangesGPR.next;
|
subrangeItr = subrangeItr->link_segmentSubrangesGPR.next;
|
||||||
}
|
}
|
||||||
if (storeLoadListLength > 0)
|
if (!loadStoreList.empty())
|
||||||
{
|
PPCRecRA_insertGPRLoadInstructions(ctx, imlSegment, imlSegment->imlList.size() - suffixInstructionCount, loadStoreList);
|
||||||
PPCRecRA_insertGPRLoadInstructions(imlSegment, imlSegment->imlList.size() - suffixInstructionCount, loadStoreList, storeLoadListLength);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMLRA_GenerateMoveInstructions(ppcImlGenContext_t* ppcImlGenContext)
|
void IMLRA_GenerateMoveInstructions(IMLRegisterAllocatorContext& ctx)
|
||||||
{
|
{
|
||||||
for (size_t s = 0; s < ppcImlGenContext->segmentList2.size(); s++)
|
for (size_t s = 0; s < ctx.deprGenContext->segmentList2.size(); s++)
|
||||||
{
|
{
|
||||||
IMLSegment* imlSegment = ppcImlGenContext->segmentList2[s];
|
IMLSegment* imlSegment = ctx.deprGenContext->segmentList2[s];
|
||||||
IMLRA_GenerateSegmentInstructions(ppcImlGenContext, imlSegment);
|
IMLRA_GenerateSegmentMoveInstructions(ctx, imlSegment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,11 +1034,15 @@ raLivenessSubrange_t* PPCRecRA_convertToMappedRanges(IMLRegisterAllocatorContext
|
||||||
if (abstractRange->isProcessed)
|
if (abstractRange->isProcessed)
|
||||||
{
|
{
|
||||||
// return already existing segment
|
// return already existing segment
|
||||||
return imlSegment->raInfo.linkedList_perVirtualGPR[vGPR];
|
raLivenessSubrange_t* existingRange = IMLRA_GetSubrange(imlSegment, vGPR);
|
||||||
|
cemu_assert_debug(existingRange);
|
||||||
|
return existingRange;
|
||||||
}
|
}
|
||||||
abstractRange->isProcessed = true;
|
abstractRange->isProcessed = true;
|
||||||
// create subrange
|
// create subrange
|
||||||
cemu_assert_debug(imlSegment->raInfo.linkedList_perVirtualGPR[vGPR] == nullptr);
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
|
cemu_assert_debug(IMLRA_GetSubrange(imlSegment, vGPR) == nullptr);
|
||||||
|
#endif
|
||||||
raLivenessSubrange_t* subrange = PPCRecRA_createSubrange(ctx.deprGenContext, range, imlSegment, abstractRange->usageStart, abstractRange->usageEnd);
|
raLivenessSubrange_t* subrange = PPCRecRA_createSubrange(ctx.deprGenContext, range, imlSegment, abstractRange->usageStart, abstractRange->usageEnd);
|
||||||
// traverse forward
|
// traverse forward
|
||||||
if (abstractRange->usageEnd == RA_INTER_RANGE_END)
|
if (abstractRange->usageEnd == RA_INTER_RANGE_END)
|
||||||
|
@ -1175,6 +1093,7 @@ raLivenessSubrange_t* PPCRecRA_convertToMappedRanges(IMLRegisterAllocatorContext
|
||||||
// take abstract range data and create LivenessRanges
|
// take abstract range data and create LivenessRanges
|
||||||
void IMLRA_ConvertAbstractToLivenessRanges(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment)
|
void IMLRA_ConvertAbstractToLivenessRanges(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment)
|
||||||
{
|
{
|
||||||
|
// convert abstract min-max ranges to liveness range objects
|
||||||
auto& segMap = ctx.GetSegmentAbstractRangeMap(imlSegment);
|
auto& segMap = ctx.GetSegmentAbstractRangeMap(imlSegment);
|
||||||
for (auto& it : segMap)
|
for (auto& it : segMap)
|
||||||
{
|
{
|
||||||
|
@ -1184,18 +1103,10 @@ void IMLRA_ConvertAbstractToLivenessRanges(IMLRegisterAllocatorContext& ctx, IML
|
||||||
raLivenessRange_t* range = PPCRecRA_createRangeBase(ctx.deprGenContext, regId, ctx.deprGenContext->mappedRegister[regId]);
|
raLivenessRange_t* range = PPCRecRA_createRangeBase(ctx.deprGenContext, regId, ctx.deprGenContext->mappedRegister[regId]);
|
||||||
PPCRecRA_convertToMappedRanges(ctx, imlSegment, regId, range);
|
PPCRecRA_convertToMappedRanges(ctx, imlSegment, regId, range);
|
||||||
}
|
}
|
||||||
|
// fill created ranges with read/write location indices
|
||||||
// create lookup table of ranges
|
// note that at this point there is only one range per register per segment
|
||||||
raLivenessSubrange_t* vGPR2Subrange[IML_RA_VIRT_REG_COUNT_MAX];
|
// and the algorithm below relies on this
|
||||||
for (sint32 i = 0; i < IML_RA_VIRT_REG_COUNT_MAX; i++)
|
const std::unordered_map<IMLRegID, raLivenessSubrange_t*>& regToSubrange = IMLRA_GetSubrangeMap(imlSegment);
|
||||||
{
|
|
||||||
vGPR2Subrange[i] = imlSegment->raInfo.linkedList_perVirtualGPR[i];
|
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
|
||||||
if (vGPR2Subrange[i] && vGPR2Subrange[i]->link_sameVirtualRegisterGPR.next != nullptr)
|
|
||||||
assert_dbg();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
// parse instructions and convert to locations
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
IMLUsedRegisters gprTracking;
|
IMLUsedRegisters gprTracking;
|
||||||
while (index < imlSegment->imlList.size())
|
while (index < imlSegment->imlList.size())
|
||||||
|
@ -1203,15 +1114,15 @@ void IMLRA_ConvertAbstractToLivenessRanges(IMLRegisterAllocatorContext& ctx, IML
|
||||||
imlSegment->imlList[index].CheckRegisterUsage(&gprTracking);
|
imlSegment->imlList[index].CheckRegisterUsage(&gprTracking);
|
||||||
gprTracking.ForEachAccessedGPR([&](IMLReg gprReg, bool isWritten) {
|
gprTracking.ForEachAccessedGPR([&](IMLReg gprReg, bool isWritten) {
|
||||||
IMLRegID gprId = gprReg.GetRegID();
|
IMLRegID gprId = gprReg.GetRegID();
|
||||||
// add location
|
raLivenessSubrange_t* subrange = regToSubrange.find(gprId)->second;
|
||||||
PPCRecRA_updateOrAddSubrangeLocation(vGPR2Subrange[gprId], index, !isWritten, isWritten);
|
PPCRecRA_updateOrAddSubrangeLocation(subrange, index, !isWritten, isWritten);
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
if ((sint32)index < vGPR2Subrange[gprId]->start.index)
|
if ((sint32)index < subrange->start.index)
|
||||||
{
|
{
|
||||||
IMLRARegAbstractLiveness* dbgAbstractRange = _GetAbstractRange(ctx, imlSegment, gprId);
|
IMLRARegAbstractLiveness* dbgAbstractRange = _GetAbstractRange(ctx, imlSegment, gprId);
|
||||||
assert_dbg();
|
assert_dbg();
|
||||||
}
|
}
|
||||||
if ((sint32)index + 1 > vGPR2Subrange[gprId]->end.index)
|
if ((sint32)index + 1 > subrange->end.index)
|
||||||
assert_dbg();
|
assert_dbg();
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
@ -1275,7 +1186,7 @@ void IMLRA_connectAbstractRanges(IMLRegisterAllocatorContext& ctx, IMLRegID regI
|
||||||
IMLRA_extendAbstractRangeToBeginningOfSegment(ctx, route[routeDepth - 1], regId);
|
IMLRA_extendAbstractRangeToBeginningOfSegment(ctx, route[routeDepth - 1], regId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _PPCRecRA_checkAndTryExtendRange(IMLRegisterAllocatorContext& ctx, IMLSegment* currentSegment, IMLRegID regID, sint32 distanceLeft, IMLSegment** route, sint32 routeDepth)
|
void _IMLRA_checkAndTryExtendRange(IMLRegisterAllocatorContext& ctx, IMLSegment* currentSegment, IMLRegID regID, sint32 distanceLeft, IMLSegment** route, sint32 routeDepth)
|
||||||
{
|
{
|
||||||
if (routeDepth >= 64)
|
if (routeDepth >= 64)
|
||||||
{
|
{
|
||||||
|
@ -1293,9 +1204,9 @@ void _PPCRecRA_checkAndTryExtendRange(IMLRegisterAllocatorContext& ctx, IMLSegme
|
||||||
if (distanceLeft > 0)
|
if (distanceLeft > 0)
|
||||||
{
|
{
|
||||||
if (currentSegment->nextSegmentBranchNotTaken)
|
if (currentSegment->nextSegmentBranchNotTaken)
|
||||||
_PPCRecRA_checkAndTryExtendRange(ctx, currentSegment->nextSegmentBranchNotTaken, regID, distanceLeft, route, routeDepth + 1);
|
_IMLRA_checkAndTryExtendRange(ctx, currentSegment->nextSegmentBranchNotTaken, regID, distanceLeft, route, routeDepth + 1);
|
||||||
if (currentSegment->nextSegmentBranchTaken)
|
if (currentSegment->nextSegmentBranchTaken)
|
||||||
_PPCRecRA_checkAndTryExtendRange(ctx, currentSegment->nextSegmentBranchTaken, regID, distanceLeft, route, routeDepth + 1);
|
_IMLRA_checkAndTryExtendRange(ctx, currentSegment->nextSegmentBranchTaken, regID, distanceLeft, route, routeDepth + 1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1331,9 +1242,9 @@ void PPCRecRA_checkAndTryExtendRange(IMLRegisterAllocatorContext& ctx, IMLSegmen
|
||||||
IMLSegment* route[64];
|
IMLSegment* route[64];
|
||||||
route[0] = currentSegment;
|
route[0] = currentSegment;
|
||||||
if (currentSegment->nextSegmentBranchNotTaken)
|
if (currentSegment->nextSegmentBranchNotTaken)
|
||||||
_PPCRecRA_checkAndTryExtendRange(ctx, currentSegment->nextSegmentBranchNotTaken, regID, remainingScanDist, route, 1);
|
_IMLRA_checkAndTryExtendRange(ctx, currentSegment->nextSegmentBranchNotTaken, regID, remainingScanDist, route, 1);
|
||||||
if (currentSegment->nextSegmentBranchTaken)
|
if (currentSegment->nextSegmentBranchTaken)
|
||||||
_PPCRecRA_checkAndTryExtendRange(ctx, currentSegment->nextSegmentBranchTaken, regID, remainingScanDist, route, 1);
|
_IMLRA_checkAndTryExtendRange(ctx, currentSegment->nextSegmentBranchTaken, regID, remainingScanDist, route, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCRecRA_mergeCloseRangesForSegmentV2(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment)
|
void PPCRecRA_mergeCloseRangesForSegmentV2(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment)
|
||||||
|
@ -1354,23 +1265,30 @@ void PPCRecRA_mergeCloseRangesForSegmentV2(IMLRegisterAllocatorContext& ctx, IML
|
||||||
void PPCRecRA_followFlowAndExtendRanges(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment)
|
void PPCRecRA_followFlowAndExtendRanges(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment)
|
||||||
{
|
{
|
||||||
std::vector<IMLSegment*> list_segments;
|
std::vector<IMLSegment*> list_segments;
|
||||||
list_segments.reserve(1000);
|
std::vector<bool> list_processedSegment;
|
||||||
|
size_t segmentCount = ctx.deprGenContext->segmentList2.size();
|
||||||
|
list_segments.reserve(segmentCount+1);
|
||||||
|
list_processedSegment.resize(segmentCount);
|
||||||
|
|
||||||
|
auto markSegProcessed = [&list_processedSegment](IMLSegment* seg) {list_processedSegment[seg->momentaryIndex] = true; };
|
||||||
|
auto isSegProcessed = [&list_processedSegment](IMLSegment* seg) -> bool { return list_processedSegment[seg->momentaryIndex]; };
|
||||||
|
markSegProcessed(imlSegment);
|
||||||
|
|
||||||
sint32 index = 0;
|
sint32 index = 0;
|
||||||
imlSegment->raRangeExtendProcessed = true;
|
|
||||||
list_segments.push_back(imlSegment);
|
list_segments.push_back(imlSegment);
|
||||||
while (index < list_segments.size())
|
while (index < list_segments.size())
|
||||||
{
|
{
|
||||||
IMLSegment* currentSegment = list_segments[index];
|
IMLSegment* currentSegment = list_segments[index];
|
||||||
PPCRecRA_mergeCloseRangesForSegmentV2(ctx, currentSegment);
|
PPCRecRA_mergeCloseRangesForSegmentV2(ctx, currentSegment);
|
||||||
// follow flow
|
// follow flow
|
||||||
if (currentSegment->nextSegmentBranchNotTaken && currentSegment->nextSegmentBranchNotTaken->raRangeExtendProcessed == false)
|
if (currentSegment->nextSegmentBranchNotTaken && !isSegProcessed(currentSegment->nextSegmentBranchNotTaken))
|
||||||
{
|
{
|
||||||
currentSegment->nextSegmentBranchNotTaken->raRangeExtendProcessed = true;
|
markSegProcessed(currentSegment->nextSegmentBranchNotTaken);
|
||||||
list_segments.push_back(currentSegment->nextSegmentBranchNotTaken);
|
list_segments.push_back(currentSegment->nextSegmentBranchNotTaken);
|
||||||
}
|
}
|
||||||
if (currentSegment->nextSegmentBranchTaken && currentSegment->nextSegmentBranchTaken->raRangeExtendProcessed == false)
|
if (currentSegment->nextSegmentBranchTaken && !isSegProcessed(currentSegment->nextSegmentBranchTaken))
|
||||||
{
|
{
|
||||||
currentSegment->nextSegmentBranchTaken->raRangeExtendProcessed = true;
|
markSegProcessed(currentSegment->nextSegmentBranchTaken);
|
||||||
list_segments.push_back(currentSegment->nextSegmentBranchTaken);
|
list_segments.push_back(currentSegment->nextSegmentBranchTaken);
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
|
@ -1382,11 +1300,9 @@ void IMLRA_mergeCloseAbstractRanges(IMLRegisterAllocatorContext& ctx)
|
||||||
for (size_t s = 0; s < ctx.deprGenContext->segmentList2.size(); s++)
|
for (size_t s = 0; s < ctx.deprGenContext->segmentList2.size(); s++)
|
||||||
{
|
{
|
||||||
IMLSegment* imlSegment = ctx.deprGenContext->segmentList2[s];
|
IMLSegment* imlSegment = ctx.deprGenContext->segmentList2[s];
|
||||||
if (imlSegment->list_prevSegments.empty())
|
if (!imlSegment->list_prevSegments.empty())
|
||||||
{
|
continue; // not an entry/standalone segment
|
||||||
cemu_assert_debug(!imlSegment->raRangeExtendProcessed); // should not be processed yet
|
PPCRecRA_followFlowAndExtendRanges(ctx, imlSegment);
|
||||||
PPCRecRA_followFlowAndExtendRanges(ctx, imlSegment);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1500,7 +1416,7 @@ void IMLRegisterAllocator_AllocateRegisters(ppcImlGenContext_t* ppcImlGenContext
|
||||||
IMLRA_AssignRegisters(ctx, ppcImlGenContext);
|
IMLRA_AssignRegisters(ctx, ppcImlGenContext);
|
||||||
|
|
||||||
IMLRA_AnalyzeRangeDataFlow(ppcImlGenContext);
|
IMLRA_AnalyzeRangeDataFlow(ppcImlGenContext);
|
||||||
IMLRA_GenerateMoveInstructions(ppcImlGenContext);
|
IMLRA_GenerateMoveInstructions(ctx);
|
||||||
|
|
||||||
PPCRecRA_deleteAllRanges(ppcImlGenContext);
|
PPCRecRA_deleteAllRanges(ppcImlGenContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,24 @@
|
||||||
#include "IMLRegisterAllocatorRanges.h"
|
#include "IMLRegisterAllocatorRanges.h"
|
||||||
#include "util/helpers/MemoryPool.h"
|
#include "util/helpers/MemoryPool.h"
|
||||||
|
|
||||||
void PPCRecRARange_addLink_perVirtualGPR(raLivenessSubrange_t** root, raLivenessSubrange_t* subrange)
|
void PPCRecRARange_addLink_perVirtualGPR(std::unordered_map<IMLRegID, raLivenessSubrange_t*>& root, raLivenessSubrange_t* subrange)
|
||||||
{
|
{
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
IMLRegID regId = subrange->range->virtualRegister;
|
||||||
if ((*root) && (*root)->range->virtualRegister != subrange->range->virtualRegister)
|
auto it = root.find(regId);
|
||||||
assert_dbg();
|
if (it == root.end())
|
||||||
#endif
|
{
|
||||||
subrange->link_sameVirtualRegisterGPR.next = *root;
|
// new single element
|
||||||
if (*root)
|
root.try_emplace(regId, subrange);
|
||||||
(*root)->link_sameVirtualRegisterGPR.prev = subrange;
|
subrange->link_sameVirtualRegisterGPR.prev = nullptr;
|
||||||
subrange->link_sameVirtualRegisterGPR.prev = nullptr;
|
subrange->link_sameVirtualRegisterGPR.next = nullptr;
|
||||||
*root = subrange;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// insert in first position
|
||||||
|
subrange->link_sameVirtualRegisterGPR.next = it->second;
|
||||||
|
it->second = subrange;
|
||||||
|
subrange->link_sameVirtualRegisterGPR.prev = subrange;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCRecRARange_addLink_allSubrangesGPR(raLivenessSubrange_t** root, raLivenessSubrange_t* subrange)
|
void PPCRecRARange_addLink_allSubrangesGPR(raLivenessSubrange_t** root, raLivenessSubrange_t* subrange)
|
||||||
|
@ -25,15 +32,28 @@ void PPCRecRARange_addLink_allSubrangesGPR(raLivenessSubrange_t** root, raLivene
|
||||||
*root = subrange;
|
*root = subrange;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCRecRARange_removeLink_perVirtualGPR(raLivenessSubrange_t** root, raLivenessSubrange_t* subrange)
|
void PPCRecRARange_removeLink_perVirtualGPR(std::unordered_map<IMLRegID, raLivenessSubrange_t*>& root, raLivenessSubrange_t* subrange)
|
||||||
{
|
{
|
||||||
raLivenessSubrange_t* tempPrev = subrange->link_sameVirtualRegisterGPR.prev;
|
IMLRegID regId = subrange->range->virtualRegister;
|
||||||
if (subrange->link_sameVirtualRegisterGPR.prev)
|
raLivenessSubrange_t* nextRange = subrange->link_sameVirtualRegisterGPR.next;
|
||||||
subrange->link_sameVirtualRegisterGPR.prev->link_sameVirtualRegisterGPR.next = subrange->link_sameVirtualRegisterGPR.next;
|
raLivenessSubrange_t* prevRange = subrange->link_sameVirtualRegisterGPR.prev;
|
||||||
else
|
raLivenessSubrange_t* newBase = prevRange ? prevRange : nextRange;
|
||||||
(*root) = subrange->link_sameVirtualRegisterGPR.next;
|
if (prevRange)
|
||||||
if (subrange->link_sameVirtualRegisterGPR.next)
|
prevRange->link_sameVirtualRegisterGPR.next = subrange->link_sameVirtualRegisterGPR.next;
|
||||||
subrange->link_sameVirtualRegisterGPR.next->link_sameVirtualRegisterGPR.prev = tempPrev;
|
if (nextRange)
|
||||||
|
nextRange->link_sameVirtualRegisterGPR.prev = subrange->link_sameVirtualRegisterGPR.prev;
|
||||||
|
|
||||||
|
if (!prevRange)
|
||||||
|
{
|
||||||
|
if (nextRange)
|
||||||
|
{
|
||||||
|
root.find(regId)->second = nextRange;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root.erase(regId);
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
subrange->link_sameVirtualRegisterGPR.prev = (raLivenessSubrange_t*)1;
|
subrange->link_sameVirtualRegisterGPR.prev = (raLivenessSubrange_t*)1;
|
||||||
subrange->link_sameVirtualRegisterGPR.next = (raLivenessSubrange_t*)1;
|
subrange->link_sameVirtualRegisterGPR.next = (raLivenessSubrange_t*)1;
|
||||||
|
@ -87,7 +107,7 @@ raLivenessSubrange_t* PPCRecRA_createSubrange(ppcImlGenContext_t* ppcImlGenConte
|
||||||
// add to range
|
// add to range
|
||||||
range->list_subranges.push_back(livenessSubrange);
|
range->list_subranges.push_back(livenessSubrange);
|
||||||
// add to segment
|
// add to segment
|
||||||
PPCRecRARange_addLink_perVirtualGPR(&(imlSegment->raInfo.linkedList_perVirtualGPR[range->virtualRegister]), livenessSubrange);
|
PPCRecRARange_addLink_perVirtualGPR(imlSegment->raInfo.linkedList_perVirtualGPR2, livenessSubrange);
|
||||||
PPCRecRARange_addLink_allSubrangesGPR(&imlSegment->raInfo.linkedList_allSubranges, livenessSubrange);
|
PPCRecRARange_addLink_allSubrangesGPR(&imlSegment->raInfo.linkedList_allSubranges, livenessSubrange);
|
||||||
return livenessSubrange;
|
return livenessSubrange;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +115,7 @@ raLivenessSubrange_t* PPCRecRA_createSubrange(ppcImlGenContext_t* ppcImlGenConte
|
||||||
void _unlinkSubrange(raLivenessSubrange_t* subrange)
|
void _unlinkSubrange(raLivenessSubrange_t* subrange)
|
||||||
{
|
{
|
||||||
IMLSegment* imlSegment = subrange->imlSegment;
|
IMLSegment* imlSegment = subrange->imlSegment;
|
||||||
PPCRecRARange_removeLink_perVirtualGPR(&imlSegment->raInfo.linkedList_perVirtualGPR[subrange->range->virtualRegister], subrange);
|
PPCRecRARange_removeLink_perVirtualGPR(imlSegment->raInfo.linkedList_perVirtualGPR2, subrange);
|
||||||
PPCRecRARange_removeLink_allSubrangesGPR(&imlSegment->raInfo.linkedList_allSubranges, subrange);
|
PPCRecRARange_removeLink_allSubrangesGPR(&imlSegment->raInfo.linkedList_allSubranges, subrange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "IMLInstruction.h"
|
#include "IMLInstruction.h"
|
||||||
|
|
||||||
#define IML_RA_VIRT_REG_COUNT_MAX (40 + 32) // should match PPC_REC_MAX_VIRTUAL_GPR -> todo: Make this dynamic
|
|
||||||
|
|
||||||
struct IMLSegmentPoint
|
struct IMLSegmentPoint
|
||||||
{
|
{
|
||||||
sint32 index;
|
sint32 index;
|
||||||
|
@ -62,12 +60,12 @@ struct raLivenessRange_t
|
||||||
|
|
||||||
struct PPCSegmentRegisterAllocatorInfo_t
|
struct PPCSegmentRegisterAllocatorInfo_t
|
||||||
{
|
{
|
||||||
// analyzer stage
|
// used during loop detection
|
||||||
bool isPartOfProcessedLoop{}; // used during loop detection
|
bool isPartOfProcessedLoop{};
|
||||||
sint32 lastIterationIndex{};
|
sint32 lastIterationIndex{};
|
||||||
// linked lists
|
// linked lists
|
||||||
raLivenessSubrange_t* linkedList_allSubranges{};
|
raLivenessSubrange_t* linkedList_allSubranges{};
|
||||||
raLivenessSubrange_t* linkedList_perVirtualGPR[IML_RA_VIRT_REG_COUNT_MAX]{};
|
std::unordered_map<IMLRegID, raLivenessSubrange_t*> linkedList_perVirtualGPR2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IMLSegment
|
struct IMLSegment
|
||||||
|
@ -92,9 +90,6 @@ struct IMLSegment
|
||||||
// enterable segments
|
// enterable segments
|
||||||
bool isEnterable{}; // this segment can be entered from outside the recompiler (no preloaded registers necessary)
|
bool isEnterable{}; // this segment can be entered from outside the recompiler (no preloaded registers necessary)
|
||||||
uint32 enterPPCAddress{}; // used if isEnterable is true
|
uint32 enterPPCAddress{}; // used if isEnterable is true
|
||||||
// jump destination segments
|
|
||||||
//bool isJumpDestination{}; // segment is a destination for one or more (conditional) jumps
|
|
||||||
//uint32 jumpDestinationPPCAddress{};
|
|
||||||
// PPC FPR use mask
|
// PPC FPR use mask
|
||||||
bool ppcFPRUsed[32]{}; // same as ppcGPRUsed, but for FPR
|
bool ppcFPRUsed[32]{}; // same as ppcGPRUsed, but for FPR
|
||||||
// CR use mask
|
// CR use mask
|
||||||
|
@ -103,8 +98,6 @@ struct IMLSegment
|
||||||
uint32 crBitsWritten{}; // bits that are written in this segment
|
uint32 crBitsWritten{}; // bits that are written in this segment
|
||||||
// register allocator info
|
// register allocator info
|
||||||
PPCSegmentRegisterAllocatorInfo_t raInfo{};
|
PPCSegmentRegisterAllocatorInfo_t raInfo{};
|
||||||
//PPCRecVGPRDistances_t raDistances{};
|
|
||||||
bool raRangeExtendProcessed{};
|
|
||||||
|
|
||||||
// segment state API
|
// segment state API
|
||||||
void SetEnterable(uint32 enterAddress);
|
void SetEnterable(uint32 enterAddress);
|
||||||
|
|
Loading…
Add table
Reference in a new issue