diff --git a/src/Cafe/HW/Espresso/Recompiler/BackendX64/BackendX64.cpp b/src/Cafe/HW/Espresso/Recompiler/BackendX64/BackendX64.cpp index cced18c4f..5ef713b9b 100644 --- a/src/Cafe/HW/Espresso/Recompiler/BackendX64/BackendX64.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/BackendX64/BackendX64.cpp @@ -172,18 +172,6 @@ void* ATTR_MS_ABI PPCRecompiler_virtualHLE(PPCInterpreter_t* hCPU, uint32 hleFun return PPCInterpreter_getCurrentInstance(); } -void ATTR_MS_ABI PPCRecompiler_getTBL(PPCInterpreter_t* hCPU, uint32 gprIndex) -{ - uint64 coreTime = coreinit::coreinit_getTimerTick(); - hCPU->gpr[gprIndex] = (uint32)(coreTime&0xFFFFFFFF); -} - -void ATTR_MS_ABI PPCRecompiler_getTBU(PPCInterpreter_t* hCPU, uint32 gprIndex) -{ - uint64 coreTime = coreinit::coreinit_getTimerTick(); - hCPU->gpr[gprIndex] = (uint32)((coreTime>>32)&0xFFFFFFFF); -} - bool PPCRecompilerX64Gen_imlInstruction_macro(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction) { if (imlInstruction->operation == PPCREC_IML_MACRO_B_TO_REG) @@ -340,43 +328,6 @@ bool PPCRecompilerX64Gen_imlInstruction_macro(PPCRecFunction_t* PPCRecFunction, x64Gen_jmp_memReg64(x64GenContext, X86_REG_RAX, (uint32)offsetof(PPCRecompilerInstanceData_t, ppcRecompilerDirectJumpTable)); return true; } - else if( imlInstruction->operation == PPCREC_IML_MACRO_MFTB ) - { - // according to MS ABI the caller needs to save: - // RAX, RCX, RDX, R8, R9, R10, R11 - - uint32 ppcAddress = imlInstruction->op_macro.param; - uint32 sprId = imlInstruction->op_macro.param2&0xFFFF; - uint32 gprIndex = (imlInstruction->op_macro.param2>>16)&0x1F; - // update instruction pointer - x64Gen_mov_mem32Reg64_imm32(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, instructionPointer), ppcAddress); - // set parameters - x64Gen_mov_reg64_reg64(x64GenContext, X86_REG_RCX, X86_REG_RSP); - x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_RDX, gprIndex); - // restore stackpointer to original RSP - x64Emit_mov_reg64_mem64(x64GenContext, X86_REG_RSP, REG_RESV_HCPU, offsetof(PPCInterpreter_t, rspTemp)); - // push hCPU on stack - x64Gen_push_reg64(x64GenContext, X86_REG_RCX); - // reserve space on stack for call parameters - x64Gen_sub_reg64_imm32(x64GenContext, X86_REG_RSP, 8*11 + 8); - x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_RBP, 0); - // call function - if( sprId == SPR_TBL ) - x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_RAX, (uint64)PPCRecompiler_getTBL); - else if( sprId == SPR_TBU ) - x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_RAX, (uint64)PPCRecompiler_getTBU); - else - assert_dbg(); - x64Gen_call_reg64(x64GenContext, X86_REG_RAX); - // restore hCPU from stack - x64Gen_add_reg64_imm32(x64GenContext, X86_REG_RSP, 8 * 11 + 8); - x64Gen_pop_reg64(x64GenContext, X86_REG_RSP); - // MOV R15, ppcRecompilerInstanceData - x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_R15, (uint64)ppcRecompilerInstanceData); - // MOV R13, memory_base - x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_R13, (uint64)memory_base); - return true; - } else { debug_printf("Unknown recompiler macro operation %d\n", imlInstruction->operation); diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLDebug.cpp b/src/Cafe/HW/Espresso/Recompiler/IML/IMLDebug.cpp index 4850ed816..1cfb470de 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLDebug.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLDebug.cpp @@ -97,23 +97,23 @@ void IMLDebug_PrintLivenessRangeInfo(StringBuf& currentLineText, IMLSegment* iml raLivenessRange* subrangeItr = imlSegment->raInfo.linkedList_allSubranges; while (subrangeItr) { - if (subrangeItr->interval2.start.GetInstructionIndexEx() == offset) + if (subrangeItr->interval.start.GetInstructionIndexEx() == offset) { - if(subrangeItr->interval2.start.IsInstructionIndex() && !subrangeItr->interval2.start.IsOnInputEdge()) + if(subrangeItr->interval.start.IsInstructionIndex() && !subrangeItr->interval.start.IsOnInputEdge()) currentLineText.add("."); else currentLineText.add("|"); currentLineText.addFmt("{:<4}", subrangeItr->GetVirtualRegister()); } - else if (subrangeItr->interval2.end.GetInstructionIndexEx() == offset) + else if (subrangeItr->interval.end.GetInstructionIndexEx() == offset) { - if(subrangeItr->interval2.end.IsInstructionIndex() && !subrangeItr->interval2.end.IsOnOutputEdge()) + if(subrangeItr->interval.end.IsInstructionIndex() && !subrangeItr->interval.end.IsOnOutputEdge()) currentLineText.add("* "); else currentLineText.add("| "); } - else if (subrangeItr->interval2.ContainsInstructionIndexEx(offset)) + else if (subrangeItr->interval.ContainsInstructionIndexEx(offset)) { currentLineText.add("| "); } @@ -374,10 +374,6 @@ void IMLDebug_DisassembleInstruction(const IMLInstruction& inst, std::string& di { strOutput.addFmt("MACRO HLE ppcAddr: 0x{:08x} funcId: 0x{:08x}", inst.op_macro.param, inst.op_macro.param2); } - else if (inst.operation == PPCREC_IML_MACRO_MFTB) - { - strOutput.addFmt("MACRO MFTB ppcAddr: 0x{:08x} sprId: 0x{:08x}", inst.op_macro.param, inst.op_macro.param2); - } else if (inst.operation == PPCREC_IML_MACRO_COUNT_CYCLES) { strOutput.addFmt("MACRO COUNT_CYCLES cycles: {}", inst.op_macro.param); diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.cpp b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.cpp index 63714cdb3..665480277 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.cpp @@ -4,6 +4,7 @@ #include "../PPCRecompiler.h" #include "../PPCRecompilerIml.h" +// return true if an instruction has side effects on top of just reading and writing registers bool IMLInstruction::HasSideEffects() const { bool hasSideEffects = true; @@ -160,7 +161,7 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const } else if (type == PPCREC_IML_TYPE_MACRO) { - if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_LEAVE || operation == PPCREC_IML_MACRO_DEBUGBREAK || operation == PPCREC_IML_MACRO_COUNT_CYCLES || operation == PPCREC_IML_MACRO_HLE || operation == PPCREC_IML_MACRO_MFTB) + if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_LEAVE || operation == PPCREC_IML_MACRO_DEBUGBREAK || operation == PPCREC_IML_MACRO_COUNT_CYCLES || operation == PPCREC_IML_MACRO_HLE) { // no effect on registers } @@ -482,15 +483,6 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const } } -//#define replaceRegister(__x,__r,__n) (((__x)==(__r))?(__n):(__x)) -IMLReg replaceRegisterId(IMLReg reg, IMLRegID oldId, IMLRegID newId) -{ - if (reg.GetRegID() != oldId) - return reg; - reg.SetRegID(newId); - return reg; -} - IMLReg replaceRegisterIdMultiple(IMLReg reg, const std::unordered_map& translationTable) { if (reg.IsInvalid()) @@ -502,26 +494,6 @@ IMLReg replaceRegisterIdMultiple(IMLReg reg, const std::unordered_map& translationTable) { if (type == PPCREC_IML_TYPE_R_NAME) @@ -594,7 +566,7 @@ void IMLInstruction::RewriteGPR(const std::unordered_map& tr } else if (type == PPCREC_IML_TYPE_MACRO) { - if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_LEAVE || operation == PPCREC_IML_MACRO_DEBUGBREAK || operation == PPCREC_IML_MACRO_HLE || operation == PPCREC_IML_MACRO_MFTB || operation == PPCREC_IML_MACRO_COUNT_CYCLES) + if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_LEAVE || operation == PPCREC_IML_MACRO_DEBUGBREAK || operation == PPCREC_IML_MACRO_HLE || operation == PPCREC_IML_MACRO_COUNT_CYCLES) { // no effect on registers } @@ -717,228 +689,3 @@ void IMLInstruction::RewriteGPR(const std::unordered_map& tr cemu_assert_unimplemented(); } } - -void IMLInstruction::ReplaceFPRs(IMLReg fprRegisterSearched[4], IMLReg fprRegisterReplaced[4]) -{ - if (type == PPCREC_IML_TYPE_R_NAME) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_NAME_R) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_R_R) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_R_S32) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_R_R_S32) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_R_R_R) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_COMPARE || type == PPCREC_IML_TYPE_COMPARE_S32 || type == PPCREC_IML_TYPE_CONDITIONAL_JUMP || type == PPCREC_IML_TYPE_JUMP) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_NO_OP) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_MACRO) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_LOAD) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_LOAD_INDEXED) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_STORE) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_STORE_INDEXED) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_ATOMIC_CMP_STORE) - { - ; - } - else if (type == PPCREC_IML_TYPE_CALL_IMM) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_FPR_LOAD) - { - op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED) - { - op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_STORE) - { - op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_STORE_INDEXED) - { - op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_R_R) - { - op_fpr_r_r.regR = replaceRegisterIdMultiple(op_fpr_r_r.regR, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r.regA = replaceRegisterIdMultiple(op_fpr_r_r.regA, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_R_R_R) - { - op_fpr_r_r_r.regR = replaceRegisterIdMultiple(op_fpr_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r.regA = replaceRegisterIdMultiple(op_fpr_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r.regB = replaceRegisterIdMultiple(op_fpr_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R) - { - op_fpr_r_r_r_r.regR = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r_r.regA = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r_r.regB = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r_r.regC = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regC, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_R) - { - op_fpr_r.regR = replaceRegisterIdMultiple(op_fpr_r.regR, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_COMPARE) - { - op_fpr_compare.regA = replaceRegisterIdMultiple(op_fpr_compare.regA, fprRegisterSearched, fprRegisterReplaced); - op_fpr_compare.regB = replaceRegisterIdMultiple(op_fpr_compare.regB, fprRegisterSearched, fprRegisterReplaced); - } - else - { - cemu_assert_unimplemented(); - } -} - -void IMLInstruction::ReplaceFPR(IMLRegID fprRegisterSearched, IMLRegID fprRegisterReplaced) -{ - if (type == PPCREC_IML_TYPE_R_NAME) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_NAME_R) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_R_R) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_R_S32) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_R_R_S32 || type == PPCREC_IML_TYPE_R_R_S32_CARRY) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_R_R_R || type == PPCREC_IML_TYPE_R_R_R_CARRY) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_COMPARE || type == PPCREC_IML_TYPE_COMPARE_S32 || type == PPCREC_IML_TYPE_CONDITIONAL_JUMP || type == PPCREC_IML_TYPE_JUMP) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_NO_OP) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_MACRO) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_LOAD) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_LOAD_INDEXED) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_STORE) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_STORE_INDEXED) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_ATOMIC_CMP_STORE) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_CALL_IMM) - { - // not affected - } - else if (type == PPCREC_IML_TYPE_FPR_LOAD) - { - op_storeLoad.registerData = replaceRegisterId(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED) - { - op_storeLoad.registerData = replaceRegisterId(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_STORE) - { - op_storeLoad.registerData = replaceRegisterId(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_STORE_INDEXED) - { - op_storeLoad.registerData = replaceRegisterId(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_R_R) - { - op_fpr_r_r.regR = replaceRegisterId(op_fpr_r_r.regR, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r.regA = replaceRegisterId(op_fpr_r_r.regA, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_R_R_R) - { - op_fpr_r_r_r.regR = replaceRegisterId(op_fpr_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r.regA = replaceRegisterId(op_fpr_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r.regB = replaceRegisterId(op_fpr_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R) - { - op_fpr_r_r_r_r.regR = replaceRegisterId(op_fpr_r_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r_r.regA = replaceRegisterId(op_fpr_r_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r_r.regB = replaceRegisterId(op_fpr_r_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced); - op_fpr_r_r_r_r.regC = replaceRegisterId(op_fpr_r_r_r_r.regC, fprRegisterSearched, fprRegisterReplaced); - } - else if (type == PPCREC_IML_TYPE_FPR_R) - { - op_fpr_r.regR = replaceRegisterId(op_fpr_r.regR, fprRegisterSearched, fprRegisterReplaced); - } - else - { - cemu_assert_unimplemented(); - } -} diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h index 28c48569c..e58511c1b 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h @@ -197,7 +197,6 @@ enum PPCREC_IML_MACRO_B_FAR, // branch to different function PPCREC_IML_MACRO_COUNT_CYCLES, // decrease current remaining thread cycles by a certain amount PPCREC_IML_MACRO_HLE, // HLE function call - PPCREC_IML_MACRO_MFTB, // get TB register value (low or high) PPCREC_IML_MACRO_LEAVE, // leaves recompiler and switches to interpeter // debugging PPCREC_IML_MACRO_DEBUGBREAK, // throws a debugbreak @@ -335,19 +334,6 @@ struct IMLUsedRegisters { IMLUsedRegisters() {}; - union - { - struct - { - IMLReg readGPR1; - IMLReg readGPR2; - IMLReg readGPR3; - IMLReg readGPR4; - IMLReg writtenGPR1; - IMLReg writtenGPR2; - }; - }; - bool IsWrittenByRegId(IMLRegID regId) const { if (writtenGPR1.IsValid() && writtenGPR1.GetRegID() == regId) @@ -404,6 +390,12 @@ struct IMLUsedRegisters F(writtenGPR2, true); } + IMLReg readGPR1; + IMLReg readGPR2; + IMLReg readGPR3; + IMLReg readGPR4; + IMLReg writtenGPR1; + IMLReg writtenGPR2; }; struct IMLInstruction @@ -575,7 +567,6 @@ struct IMLInstruction type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_B_TO_REG || type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_LEAVE || type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_HLE || - type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_MFTB || type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK || type == PPCREC_IML_TYPE_JUMP || type == PPCREC_IML_TYPE_CONDITIONAL_JUMP || @@ -788,9 +779,6 @@ struct IMLInstruction bool HasSideEffects() const; // returns true if the instruction has side effects beyond just reading and writing registers. Dead code elimination uses this to know if an instruction can be dropped when the regular register outputs are not used void RewriteGPR(const std::unordered_map& translationTable); - void ReplaceFPRs(IMLReg fprRegisterSearched[4], IMLReg fprRegisterReplaced[4]); - void ReplaceFPR(IMLRegID fprRegisterSearched, IMLRegID fprRegisterReplaced); - }; // architecture specific constants diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocator.cpp b/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocator.cpp index 910d60e77..94cf7df34 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocator.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocator.cpp @@ -192,7 +192,7 @@ static void GetInstructionFixedRegisters(IMLInstruction* instruction, IMLFixedRe } #endif -uint32 PPCRecRA_getNextIterationIndex() +uint32 IMLRA_GetNextIterationIndex() { static uint32 recRACurrentIterationIndex = 0; recRACurrentIterationIndex++; @@ -231,9 +231,9 @@ bool _detectLoop(IMLSegment* currentSegment, sint32 depth, uint32 iterationIndex return currentSegment->raInfo.isPartOfProcessedLoop; } -void PPCRecRA_detectLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegmentLoopBase) +void IMLRA_DetectLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegmentLoopBase) { - uint32 iterationIndex = PPCRecRA_getNextIterationIndex(); + uint32 iterationIndex = IMLRA_GetNextIterationIndex(); imlSegmentLoopBase->raInfo.lastIterationIndex = iterationIndex; if (_detectLoop(imlSegmentLoopBase->nextSegmentBranchTaken, 0, iterationIndex, imlSegmentLoopBase)) { @@ -241,7 +241,7 @@ void PPCRecRA_detectLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSe } } -void PPCRecRA_identifyLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment) +void IMLRA_IdentifyLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment) { if (imlSegment->nextSegmentIsUncertain) return; @@ -255,13 +255,13 @@ void PPCRecRA_identifyLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* iml // check if this segment has a branch that goes backwards (potential complex loop) if (imlSegment->nextSegmentBranchTaken && imlSegment->nextSegmentBranchTaken->momentaryIndex < imlSegment->momentaryIndex) { - PPCRecRA_detectLoop(ppcImlGenContext, imlSegment); + IMLRA_DetectLoop(ppcImlGenContext, imlSegment); } } #define SUBRANGE_LIST_SIZE (128) -sint32 PPCRecRA_countDistanceUntilNextUse2(raLivenessRange* subrange, raInstructionEdge startPosition) +sint32 IMLRA_CountDistanceUntilNextUse(raLivenessRange* subrange, raInstructionEdge startPosition) { for (sint32 i = 0; i < subrange->list_accessLocations.size(); i++) { @@ -292,8 +292,8 @@ sint32 IMLRA_CountDistanceUntilFixedRegUsageInRange(IMLSegment* imlSegment, raLi return fixedReqEntry.pos.GetRaw() - startPosition.GetRaw(); } } - cemu_assert_debug(range->interval2.end.IsInstructionIndex()); - return range->interval2.end.GetRaw() - startPosition.GetRaw(); + cemu_assert_debug(range->interval.end.IsInstructionIndex()); + return range->interval.end.GetRaw() - startPosition.GetRaw(); } sint32 IMLRA_CountDistanceUntilFixedRegUsage(IMLSegment* imlSegment, raInstructionEdge startPosition, sint32 maxDistance, IMLRegID ourRegId, sint32 physRegister) @@ -343,15 +343,15 @@ sint32 PPCRecRA_countDistanceUntilNextLocalPhysRegisterUse(IMLSegment* imlSegmen subrangeItr = subrangeItr->link_allSegmentRanges.next; continue; } - if (subrangeItr->interval2.ContainsEdge(startPosition)) + if (subrangeItr->interval.ContainsEdge(startPosition)) return 0; - if (subrangeItr->interval2.end < startPosition) + if (subrangeItr->interval.end < startPosition) { subrangeItr = subrangeItr->link_allSegmentRanges.next; continue; } - cemu_assert_debug(startPosition <= subrangeItr->interval2.start); - sint32 currentDist = subrangeItr->interval2.start.GetRaw() - startPosition.GetRaw(); + cemu_assert_debug(startPosition <= subrangeItr->interval.start); + sint32 currentDist = subrangeItr->interval.start.GetRaw() - startPosition.GetRaw(); minDistance = std::min(minDistance, currentDist); subrangeItr = subrangeItr->link_allSegmentRanges.next; } @@ -377,7 +377,7 @@ struct IMLRALivenessTimeline for (size_t f = 0; f < count; f++) { raLivenessRange* liverange = activeRanges[f]; - if (liverange->interval2.end < expireUpTo) // this was <= but since end is not inclusive we need to use < + if (liverange->interval.end < expireUpTo) // this was <= but since end is not inclusive we need to use < { #ifdef CEMU_DEBUG_ASSERT if (!expireUpTo.ConnectsToNextSegment() && (liverange->subrangeBranchTaken || liverange->subrangeBranchNotTaken)) @@ -443,7 +443,7 @@ void PPCRecRA_MaskOverlappingPhysRegForGlobalRange(raLivenessRange* range2, IMLP subrangeItr = subrangeItr->link_allSegmentRanges.next; continue; } - if (subrange->interval2.IsOverlapping(subrangeItr->interval2)) + if (subrange->interval.IsOverlapping(subrangeItr->interval)) { if (subrangeItr->GetPhysicalRegister() >= 0) physRegSet.SetReserved(subrangeItr->GetPhysicalRegister()); @@ -456,7 +456,7 @@ void PPCRecRA_MaskOverlappingPhysRegForGlobalRange(raLivenessRange* range2, IMLP bool _livenessRangeStartCompare(raLivenessRange* lhs, raLivenessRange* rhs) { - return lhs->interval2.start < rhs->interval2.start; + return lhs->interval.start < rhs->interval.start; } void _sortSegmentAllSubrangesLinkedList(IMLSegment* imlSegment) @@ -467,8 +467,7 @@ void _sortSegmentAllSubrangesLinkedList(IMLSegment* imlSegment) raLivenessRange* subrangeItr = imlSegment->raInfo.linkedList_allSubranges; while (subrangeItr) { - if (count >= 4096) - assert_dbg(); + cemu_assert(count < 4096); subrangeList[count] = subrangeItr; count++; // next @@ -560,7 +559,7 @@ boost::container::small_vector IMLRA_GetRangeWithFixedRegRe boost::container::small_vector rangeList; for (raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange; currentRange = currentRange->link_allSegmentRanges.next) { - if (!currentRange->interval2.ContainsEdge(pos)) + if (!currentRange->interval.ContainsEdge(pos)) continue; IMLPhysRegisterSet allowedRegs; if (!currentRange->GetAllowedRegistersEx(allowedRegs)) @@ -574,7 +573,7 @@ boost::container::small_vector IMLRA_GetRangeWithFixedRegRe void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment) { // first pass - iterate over all ranges with fixed register requirements and split them if they cross the segment border - // todo - this pass currently creates suboptimal results by splitting all ranges that cross the segment border if they have any fixed register requirement. This isn't always necessary + // todo - this pass currently creates suboptimal results by splitting all ranges that cross the segment border if they have any fixed register requirement. This can be avoided in some cases for (raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange;) { IMLPhysRegisterSet allowedRegs; @@ -588,10 +587,10 @@ void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment currentRange = currentRange->link_allSegmentRanges.next; continue; } - if (currentRange->interval2.ExtendsPreviousSegment() || currentRange->interval2.ExtendsIntoNextSegment()) + if (currentRange->interval.ExtendsPreviousSegment() || currentRange->interval.ExtendsIntoNextSegment()) { raLivenessRange* nextRange = currentRange->link_allSegmentRanges.next; - PPCRecRA_explodeRange(ppcImlGenContext, currentRange); + IMLRA_ExplodeRangeCluster(ppcImlGenContext, currentRange); currentRange = nextRange; continue; } @@ -638,9 +637,9 @@ void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment for (auto& range : overlappingRanges) { - if (range->interval2.start < entry.pos) + if (range->interval.start < entry.pos) { - PPCRecRA_splitLocalSubrange2(ppcImlGenContext, range, entry.pos, true); + IMLRA_SplitRange(ppcImlGenContext, range, entry.pos, true); } } } @@ -737,8 +736,8 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& allowedRegs) { - raInstructionEdge currentRangeStart = currentRange->interval2.start; - sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance(); + raInstructionEdge currentRangeStart = currentRange->interval.start; + sint32 requiredSize2 = currentRange->interval.GetPreciseDistance(); cemu_assert_debug(localRangeHoleCutting.distance == -1); cemu_assert_debug(strategyCost == INT_MAX); if (!currentRangeStart.ConnectsToPreviousSegment()) @@ -746,7 +745,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy cemu_assert_debug(currentRangeStart.GetRaw() >= 0); for (auto candidate : timeline.activeRanges) { - if (candidate->interval2.ExtendsIntoNextSegment()) + if (candidate->interval.ExtendsIntoNextSegment()) continue; // new checks (Oct 2024): if (candidate == currentRange) @@ -756,7 +755,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy if (!allowedRegs.IsAvailable(candidate->GetPhysicalRegister())) continue; - sint32 distance2 = PPCRecRA_countDistanceUntilNextUse2(candidate, currentRangeStart); + sint32 distance2 = IMLRA_CountDistanceUntilNextUse(candidate, currentRangeStart); IMLRA_MakeSafeSplitDistance(imlSegment, currentRangeStart, distance2); if (distance2 < 2) continue; @@ -785,18 +784,18 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override { cemu_assert_debug(strategyCost != INT_MAX); - sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance(); - raInstructionEdge currentRangeStart = currentRange->interval2.start; + sint32 requiredSize2 = currentRange->interval.GetPreciseDistance(); + raInstructionEdge currentRangeStart = currentRange->interval.start; raInstructionEdge holeStartPosition = currentRangeStart; raInstructionEdge holeEndPosition = currentRangeStart + localRangeHoleCutting.distance; raLivenessRange* collisionRange = localRangeHoleCutting.largestHoleSubrange; - if (collisionRange->interval2.start < holeStartPosition) + if (collisionRange->interval.start < holeStartPosition) { - collisionRange = PPCRecRA_splitLocalSubrange2(nullptr, collisionRange, holeStartPosition, true); - cemu_assert_debug(!collisionRange || collisionRange->interval2.start >= holeStartPosition); // verify if splitting worked at all, tail must be on or after the split point - cemu_assert_debug(!collisionRange || collisionRange->interval2.start >= holeEndPosition); // also verify that the trimmed hole is actually big enough + collisionRange = IMLRA_SplitRange(nullptr, collisionRange, holeStartPosition, true); + cemu_assert_debug(!collisionRange || collisionRange->interval.start >= holeStartPosition); // verify if splitting worked at all, tail must be on or after the split point + cemu_assert_debug(!collisionRange || collisionRange->interval.start >= holeEndPosition); // also verify that the trimmed hole is actually big enough } else { @@ -805,7 +804,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy // we may also have to cut the current range to fit partially into the hole if (requiredSize2 > localRangeHoleCutting.distance) { - raLivenessRange* tailRange = PPCRecRA_splitLocalSubrange2(nullptr, currentRange, currentRangeStart + localRangeHoleCutting.distance, true); + raLivenessRange* tailRange = IMLRA_SplitRange(nullptr, currentRange, currentRangeStart + localRangeHoleCutting.distance, true); if (tailRange) { cemu_assert_debug(tailRange->list_fixedRegRequirements.empty()); // we are not allowed to unassign fixed registers @@ -815,7 +814,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy // verify that the hole is large enough if (collisionRange) { - cemu_assert_debug(!collisionRange->interval2.IsOverlapping(currentRange->interval2)); + cemu_assert_debug(!collisionRange->interval.IsOverlapping(currentRange->interval)); } } @@ -840,9 +839,9 @@ class RASpillStrategy_AvailableRegisterHole : public RASpillStrategy void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& localAvailableRegsMask, const IMLPhysRegisterSet& allowedRegs) { - sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance(); + sint32 requiredSize2 = currentRange->interval.GetPreciseDistance(); - raInstructionEdge currentRangeStart = currentRange->interval2.start; + raInstructionEdge currentRangeStart = currentRange->interval.start; cemu_assert_debug(strategyCost == INT_MAX); availableRegisterHole.distance = -1; availableRegisterHole.physRegister = -1; @@ -888,9 +887,9 @@ class RASpillStrategy_AvailableRegisterHole : public RASpillStrategy void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override { cemu_assert_debug(strategyCost != INT_MAX); - raInstructionEdge currentRangeStart = currentRange->interval2.start; + raInstructionEdge currentRangeStart = currentRange->interval.start; // use available register - raLivenessRange* tailRange = PPCRecRA_splitLocalSubrange2(nullptr, currentRange, currentRangeStart + availableRegisterHole.distance, true); + raLivenessRange* tailRange = IMLRA_SplitRange(nullptr, currentRange, currentRangeStart + availableRegisterHole.distance, true); if (tailRange) { cemu_assert_debug(tailRange->list_fixedRegRequirements.empty()); // we are not allowed to unassign fixed registers @@ -918,16 +917,16 @@ class RASpillStrategy_ExplodeRange : public RASpillStrategy void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& allowedRegs) { - raInstructionEdge currentRangeStart = currentRange->interval2.start; + raInstructionEdge currentRangeStart = currentRange->interval.start; if (currentRangeStart.ConnectsToPreviousSegment()) currentRangeStart.Set(0, true); - sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance(); + sint32 requiredSize2 = currentRange->interval.GetPreciseDistance(); cemu_assert_debug(strategyCost == INT_MAX); explodeRange.range = nullptr; explodeRange.distance = -1; for (auto candidate : timeline.activeRanges) { - if (!candidate->interval2.ExtendsIntoNextSegment()) + if (!candidate->interval.ExtendsIntoNextSegment()) continue; // new checks (Oct 2024): if (candidate == currentRange) @@ -937,7 +936,7 @@ class RASpillStrategy_ExplodeRange : public RASpillStrategy if (!allowedRegs.IsAvailable(candidate->GetPhysicalRegister())) continue; - sint32 distance = PPCRecRA_countDistanceUntilNextUse2(candidate, currentRangeStart); + sint32 distance = IMLRA_CountDistanceUntilNextUse(candidate, currentRangeStart); IMLRA_MakeSafeSplitDistance(imlSegment, currentRangeStart, distance); if (distance < 2) continue; @@ -961,16 +960,16 @@ class RASpillStrategy_ExplodeRange : public RASpillStrategy void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override { - raInstructionEdge currentRangeStart = currentRange->interval2.start; + raInstructionEdge currentRangeStart = currentRange->interval.start; if (currentRangeStart.ConnectsToPreviousSegment()) currentRangeStart.Set(0, true); - sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance(); + sint32 requiredSize2 = currentRange->interval.GetPreciseDistance(); // explode range - PPCRecRA_explodeRange(nullptr, explodeRange.range); + IMLRA_ExplodeRangeCluster(nullptr, explodeRange.range); // split current subrange if necessary if (requiredSize2 > explodeRange.distance) { - raLivenessRange* tailRange = PPCRecRA_splitLocalSubrange2(nullptr, currentRange, currentRangeStart + explodeRange.distance, true); + raLivenessRange* tailRange = IMLRA_SplitRange(nullptr, currentRange, currentRangeStart + explodeRange.distance, true); if (tailRange) { cemu_assert_debug(tailRange->list_fixedRegRequirements.empty()); // we are not allowed to unassign fixed registers @@ -1005,7 +1004,7 @@ class RASpillStrategy_ExplodeRangeInter : public RASpillStrategy cemu_assert_debug(explodeRange.range == nullptr && explodeRange.distance == -1); for (auto candidate : timeline.activeRanges) { - if (!candidate->interval2.ExtendsIntoNextSegment()) + if (!candidate->interval.ExtendsIntoNextSegment()) continue; // only select candidates that clash with current subrange if (candidate->GetPhysicalRegister() < 0 && candidate != currentRange) @@ -1037,7 +1036,7 @@ class RASpillStrategy_ExplodeRangeInter : public RASpillStrategy void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override { cemu_assert_debug(strategyCost != INT_MAX); - PPCRecRA_explodeRange(ctx, explodeRange.range); + IMLRA_ExplodeRangeCluster(ctx, explodeRange.range); } private: @@ -1056,16 +1055,16 @@ void IMLRA_FilterReservedFixedRegisterRequirementsForSegment(IMLRegisterAllocato if (seg->imlList.empty()) return; // there can be no fixed register requirements if there are no instructions - raInstructionEdge firstPos = currentRange->interval2.start; - if (currentRange->interval2.start.ConnectsToPreviousSegment()) + raInstructionEdge firstPos = currentRange->interval.start; + if (currentRange->interval.start.ConnectsToPreviousSegment()) firstPos.SetRaw(0); - else if (currentRange->interval2.start.ConnectsToNextSegment()) + else if (currentRange->interval.start.ConnectsToNextSegment()) firstPos.Set(seg->imlList.size() - 1, false); - raInstructionEdge lastPos = currentRange->interval2.end; - if (currentRange->interval2.end.ConnectsToPreviousSegment()) + raInstructionEdge lastPos = currentRange->interval.end; + if (currentRange->interval.end.ConnectsToPreviousSegment()) lastPos.SetRaw(0); - else if (currentRange->interval2.end.ConnectsToNextSegment()) + else if (currentRange->interval.end.ConnectsToNextSegment()) lastPos.Set(seg->imlList.size() - 1, false); cemu_assert_debug(firstPos <= lastPos); @@ -1093,7 +1092,7 @@ void IMLRA_FilterReservedFixedRegisterRequirementsForSegment(IMLRegisterAllocato void IMLRA_FilterReservedFixedRegisterRequirementsForCluster(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment, raLivenessRange* currentRange, IMLPhysRegisterSet& candidatePhysRegSet) { cemu_assert_debug(currentRange->imlSegment == imlSegment); - if (currentRange->interval2.ExtendsPreviousSegment() || currentRange->interval2.ExtendsIntoNextSegment()) + if (currentRange->interval.ExtendsPreviousSegment() || currentRange->interval.ExtendsIntoNextSegment()) { auto clusterRanges = currentRange->GetAllSubrangesInCluster(); for (auto& rangeIt : clusterRanges) @@ -1128,7 +1127,7 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon while (subrangeItr) { - raInstructionEdge currentRangeStart = subrangeItr->interval2.start; // used to be currentIndex before refactor + raInstructionEdge currentRangeStart = subrangeItr->interval.start; // used to be currentIndex before refactor PPCRecRA_debugValidateSubrange(subrangeItr); livenessTimeline.ExpireRanges((currentRangeStart > lastInstructionEdge) ? lastInstructionEdge : currentRangeStart); // expire up to currentIndex (inclusive), but exclude infinite ranges @@ -1204,7 +1203,7 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon selectedStrategy = &newStrategy; }; - if (!subrangeItr->interval2.ExtendsIntoNextSegment()) + if (!subrangeItr->interval.ExtendsIntoNextSegment()) { // range ends in current segment, use local strategies // evaluate strategy: Cut hole into local subrange @@ -1232,9 +1231,9 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon else { // none of the evulated strategies can be applied, this should only happen if the segment extends into the next segment(s) for which we have no good strategy - cemu_assert_debug(subrangeItr->interval2.ExtendsPreviousSegment()); + cemu_assert_debug(subrangeItr->interval.ExtendsPreviousSegment()); // alternative strategy if we have no other choice: explode current range - PPCRecRA_explodeRange(ppcImlGenContext, subrangeItr); + IMLRA_ExplodeRangeCluster(ppcImlGenContext, subrangeItr); } return false; } @@ -1336,7 +1335,7 @@ void IMLRA_ReshapeForRegisterAllocation(ppcImlGenContext_t* ppcImlGenContext) for (size_t s = 0; s < ppcImlGenContext->segmentList2.size(); s++) { IMLSegment* imlSegment = ppcImlGenContext->segmentList2[s]; - PPCRecRA_identifyLoop(ppcImlGenContext, imlSegment); + IMLRA_IdentifyLoop(ppcImlGenContext, imlSegment); } } @@ -1411,7 +1410,7 @@ raLivenessRange* PPCRecRA_convertToMappedRanges(IMLRegisterAllocatorContext& ctx inclusiveEnd--; // subtract one, because usageEnd is exclusive, but the end value of the interval passed to createSubrange is inclusive raInterval interval; interval.SetInterval(abstractRange->usageStart, true, inclusiveEnd, true); - raLivenessRange* subrange = PPCRecRA_createSubrange2(ctx.deprGenContext, imlSegment, vGPR, name, interval.start, interval.end); + raLivenessRange* subrange = IMLRA_CreateRange(ctx.deprGenContext, imlSegment, vGPR, name, interval.start, interval.end); // traverse forward if (abstractRange->usageEnd == RA_INTER_RANGE_END) { @@ -1422,7 +1421,7 @@ raLivenessRange* PPCRecRA_convertToMappedRanges(IMLRegisterAllocatorContext& ctx { subrange->subrangeBranchTaken = PPCRecRA_convertToMappedRanges(ctx, imlSegment->nextSegmentBranchTaken, vGPR, name); subrange->subrangeBranchTaken->previousRanges.push_back(subrange); - cemu_assert_debug(subrange->subrangeBranchTaken->interval2.ExtendsPreviousSegment()); + cemu_assert_debug(subrange->subrangeBranchTaken->interval.ExtendsPreviousSegment()); } } if (imlSegment->nextSegmentBranchNotTaken) @@ -1432,7 +1431,7 @@ raLivenessRange* PPCRecRA_convertToMappedRanges(IMLRegisterAllocatorContext& ctx { subrange->subrangeBranchNotTaken = PPCRecRA_convertToMappedRanges(ctx, imlSegment->nextSegmentBranchNotTaken, vGPR, name); subrange->subrangeBranchNotTaken->previousRanges.push_back(subrange); - cemu_assert_debug(subrange->subrangeBranchNotTaken->interval2.ExtendsPreviousSegment()); + cemu_assert_debug(subrange->subrangeBranchNotTaken->interval.ExtendsPreviousSegment()); } } } @@ -1771,7 +1770,7 @@ void IMLRA_AnalyzeSubrangeDataDependency(raLivenessRange* subrange) subrange->_noLoad = isOverwritten; subrange->hasStore = isWritten; - if (subrange->interval2.ExtendsPreviousSegment()) + if (subrange->interval.ExtendsPreviousSegment()) subrange->_noLoad = true; } @@ -1796,7 +1795,7 @@ void _findSubrangeWriteEndings(raLivenessRange* subrange, uint32 iterationIndex, if (subrange->hasStoreDelayed) return; // no need to traverse this subrange IMLSegment* imlSegment = subrange->imlSegment; - if (!subrange->interval2.ExtendsIntoNextSegment()) + if (!subrange->interval.ExtendsIntoNextSegment()) { // ending segment if (info->subrangeCount >= SUBRANGE_LIST_SIZE) @@ -1839,7 +1838,7 @@ void _findSubrangeWriteEndings(raLivenessRange* subrange, uint32 iterationIndex, static void IMLRA_AnalyzeRangeDataFlow(raLivenessRange* subrange) { - if (!subrange->interval2.ExtendsIntoNextSegment()) + if (!subrange->interval.ExtendsIntoNextSegment()) return; // analyze data flow across segments (if this segment has writes) if (subrange->hasStore) @@ -1847,7 +1846,7 @@ static void IMLRA_AnalyzeRangeDataFlow(raLivenessRange* subrange) subrangeEndingInfo_t writeEndingInfo; writeEndingInfo.subrangeCount = 0; writeEndingInfo.hasUndefinedEndings = false; - _findSubrangeWriteEndings(subrange, PPCRecRA_getNextIterationIndex(), 0, &writeEndingInfo); + _findSubrangeWriteEndings(subrange, IMLRA_GetNextIterationIndex(), 0, &writeEndingInfo); if (writeEndingInfo.hasUndefinedEndings == false) { // get cost of delaying store into endings @@ -1924,7 +1923,7 @@ void IMLRA_RewriteRegisters(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSeg { currentEdge.Set(i, false); // set to instruction index on output edge // activate ranges which begin before or during this instruction - while (currentRange && currentRange->interval2.start <= currentEdge) + while (currentRange && currentRange->interval.start <= currentEdge) { cemu_assert_debug(virtId2PhysReg.find(currentRange->GetVirtualRegister()) == virtId2PhysReg.end() || virtId2PhysReg[currentRange->GetVirtualRegister()] == currentRange->GetPhysicalRegister()); // check for register conflict @@ -1938,7 +1937,7 @@ void IMLRA_RewriteRegisters(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSeg auto it = activeRanges.begin(); while (it != activeRanges.end()) { - if ((*it)->interval2.end <= currentEdge) + if ((*it)->interval.end <= currentEdge) { virtId2PhysReg.erase((*it)->GetVirtualRegister()); it = activeRanges.erase(it); @@ -1981,7 +1980,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM { if (!currentRange->_noLoad) { - cemu_assert_debug(currentRange->interval2.ExtendsIntoNextSegment()); + cemu_assert_debug(currentRange->interval.ExtendsIntoNextSegment()); rebuiltInstructions.emplace_back().make_r_name(_MakeNativeReg(ctx.regIdToBaseFormat[currentRange->GetVirtualRegister()], currentRange->GetPhysicalRegister()), currentRange->GetName()); } currentRange = currentRange->link_allSegmentRanges.next; @@ -2001,9 +2000,9 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM while (currentRange) { - if (!currentRange->interval2.IsNextSegmentOnly() && currentRange->interval2.end > edge) + if (!currentRange->interval.IsNextSegmentOnly() && currentRange->interval.end > edge) { - currentRange->interval2.SetEnd(edge); + currentRange->interval.SetEnd(edge); } currentRange = currentRange->link_allSegmentRanges.next; } @@ -2025,9 +2024,8 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM boost::container::small_vector activeRanges; // first we add all the ranges that extend from the previous segment, some of these will end immediately at the first instruction so we might need to store them early raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; - // make all ranges active that start on RA_INTER_RANGE_START - while (currentRange && currentRange->interval2.start.ConnectsToPreviousSegment()) + while (currentRange && currentRange->interval.start.ConnectsToPreviousSegment()) { activeRanges.push_back(currentRange); currentRange = currentRange->link_allSegmentRanges.next; @@ -2038,7 +2036,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM firstOutputEdge.Set(0, false); while (it != activeRanges.end()) { - if ((*it)->interval2.end < firstOutputEdge) + if ((*it)->interval.end < firstOutputEdge) { raLivenessRange* storedRange = *it; if (storedRange->hasStore) @@ -2055,7 +2053,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM raInstructionEdge curEdge; // input edge curEdge.SetRaw(i * 2 + 1); // +1 to include ranges that start at the output of the instruction - while (currentRange && currentRange->interval2.start <= curEdge) + while (currentRange && currentRange->interval.start <= curEdge) { if (!currentRange->_noLoad) { @@ -2072,11 +2070,9 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM auto it = activeRanges.begin(); while (it != activeRanges.end()) { - if ((*it)->interval2.end <= curEdge) + if ((*it)->interval.end <= curEdge) { // range expires - // we cant erase it from virtId2PhysReg right away because a store might happen before the last use (the +1 thing above) - // todo - check hasStore raLivenessRange* storedRange = *it; if (storedRange->hasStore) @@ -2084,7 +2080,6 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM cemu_assert_debug(i != numInstructionsWithoutSuffix); // not allowed to emit after suffix rebuiltInstructions.emplace_back().make_name_r(storedRange->GetName(), _MakeNativeReg(ctx.regIdToBaseFormat[storedRange->GetVirtualRegister()], storedRange->GetPhysicalRegister())); } - it = activeRanges.erase(it); continue; } @@ -2109,7 +2104,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM } while (currentRange) { - cemu_assert_debug(currentRange->interval2.IsNextSegmentOnly()); + cemu_assert_debug(currentRange->interval.IsNextSegmentOnly()); cemu_assert_debug(!currentRange->_noLoad); rebuiltInstructions.emplace_back().make_r_name(_MakeNativeReg(ctx.regIdToBaseFormat[currentRange->GetVirtualRegister()], currentRange->GetPhysicalRegister()), currentRange->GetName()); currentRange = currentRange->link_allSegmentRanges.next; diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocator.h b/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocator.h index b5a7610b2..0a54e4cbd 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocator.h +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocator.h @@ -60,10 +60,10 @@ class IMLPhysRegisterSet } // returns index of first available register. Do not call when HasAnyAvailable() == false - uint32 GetFirstAvailableReg() + IMLPhysReg GetFirstAvailableReg() { cemu_assert_debug(m_regBitmask != 0); - uint32 regIndex = 0; + sint32 regIndex = 0; auto tmp = m_regBitmask; while ((tmp & 0xFF) == 0) { @@ -80,7 +80,7 @@ class IMLPhysRegisterSet // returns index of next available register (search includes any register index >= startIndex) // returns -1 if there is no more register - sint32 GetNextAvailableReg(sint32 startIndex) const + IMLPhysReg GetNextAvailableReg(sint32 startIndex) const { if (startIndex >= 64) return -1; @@ -111,7 +111,6 @@ class IMLPhysRegisterSet uint64 m_regBitmask{ 0 }; }; - struct IMLRegisterAllocatorParameters { inline IMLPhysRegisterSet& GetPhysRegPool(IMLRegFormat regFormat) diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.cpp b/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.cpp index 2c930651b..1ac884cd8 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.cpp @@ -3,7 +3,7 @@ #include "IMLRegisterAllocatorRanges.h" #include "util/helpers/MemoryPool.h" -uint32 PPCRecRA_getNextIterationIndex(); +uint32 IMLRA_GetNextIterationIndex(); IMLRegID raLivenessRange::GetVirtualRegister() const { @@ -20,12 +20,12 @@ IMLName raLivenessRange::GetName() const return name; } -void raLivenessRange::SetPhysicalRegister(sint32 physicalRegister) +void raLivenessRange::SetPhysicalRegister(IMLPhysReg physicalRegister) { this->physicalRegister = physicalRegister; } -void raLivenessRange::SetPhysicalRegisterForCluster(sint32 physicalRegister) +void raLivenessRange::SetPhysicalRegisterForCluster(IMLPhysReg physicalRegister) { auto clusterRanges = GetAllSubrangesInCluster(); for(auto& range : clusterRanges) @@ -34,7 +34,7 @@ void raLivenessRange::SetPhysicalRegisterForCluster(sint32 physicalRegister) boost::container::small_vector raLivenessRange::GetAllSubrangesInCluster() { - uint32 iterationIndex = PPCRecRA_getNextIterationIndex(); + uint32 iterationIndex = IMLRA_GetNextIterationIndex(); boost::container::small_vector subranges; subranges.push_back(this); this->lastIterationIndex = iterationIndex; @@ -87,7 +87,7 @@ void raLivenessRange::GetAllowedRegistersExRecursive(raLivenessRange* range, uin bool raLivenessRange::GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters) { - uint32 iterationIndex = PPCRecRA_getNextIterationIndex(); + uint32 iterationIndex = IMLRA_GetNextIterationIndex(); allowedRegisters.SetAllAvailable(); GetAllowedRegistersExRecursive(this, iterationIndex, allowedRegisters); return !allowedRegisters.HasAllAvailable(); @@ -96,7 +96,7 @@ bool raLivenessRange::GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters IMLPhysRegisterSet raLivenessRange::GetAllowedRegisters(IMLPhysRegisterSet regPool) { IMLPhysRegisterSet fixedRegRequirements = regPool; - if(interval2.ExtendsPreviousSegment() || interval2.ExtendsIntoNextSegment()) + if(interval.ExtendsPreviousSegment() || interval.ExtendsIntoNextSegment()) { auto clusterRanges = GetAllSubrangesInCluster(); for(auto& subrange : clusterRanges) @@ -203,7 +203,7 @@ void PPCRecRARange_removeLink_allSegmentRanges(raLivenessRange** root, raLivenes MemoryPoolPermanentObjects memPool_livenessSubrange(4096); // startPosition and endPosition are inclusive -raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition) +raLivenessRange* IMLRA_CreateRange(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition) { raLivenessRange* range = memPool_livenessSubrange.acquireObj(); range->previousRanges.clear(); @@ -212,8 +212,8 @@ raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext, range->imlSegment = imlSegment; cemu_assert_debug(startPosition <= endPosition); - range->interval2.start = startPosition; - range->interval2.end = endPosition; + range->interval.start = startPosition; + range->interval.end = endPosition; // register mapping range->virtualRegister = virtualRegister; @@ -233,42 +233,42 @@ raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext, return range; } -void _unlinkSubrange(raLivenessRange* subrange) +void _unlinkSubrange(raLivenessRange* range) { - IMLSegment* imlSegment = subrange->imlSegment; - PPCRecRARange_removeLink_perVirtualGPR(imlSegment->raInfo.linkedList_perVirtualRegister, subrange); - PPCRecRARange_removeLink_allSegmentRanges(&imlSegment->raInfo.linkedList_allSubranges, subrange); + IMLSegment* imlSegment = range->imlSegment; + PPCRecRARange_removeLink_perVirtualGPR(imlSegment->raInfo.linkedList_perVirtualRegister, range); + PPCRecRARange_removeLink_allSegmentRanges(&imlSegment->raInfo.linkedList_allSubranges, range); // unlink reverse references - if(subrange->subrangeBranchTaken) - subrange->subrangeBranchTaken->previousRanges.erase(std::find(subrange->subrangeBranchTaken->previousRanges.begin(), subrange->subrangeBranchTaken->previousRanges.end(), subrange)); - if(subrange->subrangeBranchNotTaken) - subrange->subrangeBranchNotTaken->previousRanges.erase(std::find(subrange->subrangeBranchNotTaken->previousRanges.begin(), subrange->subrangeBranchNotTaken->previousRanges.end(), subrange)); - subrange->subrangeBranchTaken = (raLivenessRange*)(uintptr_t)-1; - subrange->subrangeBranchNotTaken = (raLivenessRange*)(uintptr_t)-1; + if(range->subrangeBranchTaken) + range->subrangeBranchTaken->previousRanges.erase(std::find(range->subrangeBranchTaken->previousRanges.begin(), range->subrangeBranchTaken->previousRanges.end(), range)); + if(range->subrangeBranchNotTaken) + range->subrangeBranchNotTaken->previousRanges.erase(std::find(range->subrangeBranchNotTaken->previousRanges.begin(), range->subrangeBranchNotTaken->previousRanges.end(), range)); + range->subrangeBranchTaken = (raLivenessRange*)(uintptr_t)-1; + range->subrangeBranchNotTaken = (raLivenessRange*)(uintptr_t)-1; // remove forward references - for(auto& prev : subrange->previousRanges) + for(auto& prev : range->previousRanges) { - if(prev->subrangeBranchTaken == subrange) + if(prev->subrangeBranchTaken == range) prev->subrangeBranchTaken = nullptr; - if(prev->subrangeBranchNotTaken == subrange) + if(prev->subrangeBranchNotTaken == range) prev->subrangeBranchNotTaken = nullptr; } - subrange->previousRanges.clear(); + range->previousRanges.clear(); } -void PPCRecRA_deleteSubrange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange) +void IMLRA_DeleteRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* range) { - _unlinkSubrange(subrange); - subrange->list_accessLocations.clear(); - subrange->list_fixedRegRequirements.clear(); - memPool_livenessSubrange.releaseObj(subrange); + _unlinkSubrange(range); + range->list_accessLocations.clear(); + range->list_fixedRegRequirements.clear(); + memPool_livenessSubrange.releaseObj(range); } -void PPCRecRA_deleteSubrangeCluster(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange) +void IMLRA_DeleteRangeCluster(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* range) { - auto clusterRanges = subrange->GetAllSubrangesInCluster(); + auto clusterRanges = range->GetAllSubrangesInCluster(); for (auto& subrange : clusterRanges) - PPCRecRA_deleteSubrange(ppcImlGenContext, subrange); + IMLRA_DeleteRange(ppcImlGenContext, subrange); } void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext) @@ -277,13 +277,13 @@ void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext) { raLivenessRange* cur; while(cur = seg->raInfo.linkedList_allSubranges) - PPCRecRA_deleteSubrange(ppcImlGenContext, cur); + IMLRA_DeleteRange(ppcImlGenContext, cur); seg->raInfo.linkedList_allSubranges = nullptr; seg->raInfo.linkedList_perVirtualRegister.clear(); } } -void PPCRecRA_mergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange, raLivenessRange* absorbedSubrange) +void IMLRA_MergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange, raLivenessRange* absorbedSubrange) { #ifdef CEMU_DEBUG_ASSERT PPCRecRA_debugValidateSubrange(subrange); @@ -322,17 +322,17 @@ void PPCRecRA_mergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRan subrange->list_fixedRegRequirements.push_back(fixedReg); absorbedSubrange->list_fixedRegRequirements.clear(); - subrange->interval2.end = absorbedSubrange->interval2.end; + subrange->interval.end = absorbedSubrange->interval.end; PPCRecRA_debugValidateSubrange(subrange); - PPCRecRA_deleteSubrange(ppcImlGenContext, absorbedSubrange); + IMLRA_DeleteRange(ppcImlGenContext, absorbedSubrange); } -// remove all inter-segment connections from the range cluster and split it into local ranges (also removes empty ranges) -void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange) +// remove all inter-segment connections from the range cluster and split it into local ranges. Ranges are trimmed and if they have no access location they will be removed +void IMLRA_ExplodeRangeCluster(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange) { - cemu_assert_debug(originRange->interval2.ExtendsPreviousSegment() || originRange->interval2.ExtendsIntoNextSegment()); // only call this on ranges that span multiple segments + cemu_assert_debug(originRange->interval.ExtendsPreviousSegment() || originRange->interval.ExtendsIntoNextSegment()); // only call this on ranges that span multiple segments auto clusterRanges = originRange->GetAllSubrangesInCluster(); for (auto& subrange : clusterRanges) { @@ -340,7 +340,7 @@ void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange continue; raInterval interval; interval.SetInterval(subrange->list_accessLocations.front().pos, subrange->list_accessLocations.back().pos); - raLivenessRange* newSubrange = PPCRecRA_createSubrange2(ppcImlGenContext, subrange->imlSegment, subrange->GetVirtualRegister(), subrange->GetName(), interval.start, interval.end); + raLivenessRange* newSubrange = IMLRA_CreateRange(ppcImlGenContext, subrange->imlSegment, subrange->GetVirtualRegister(), subrange->GetName(), interval.start, interval.end); // copy locations and fixed reg indices newSubrange->list_accessLocations = subrange->list_accessLocations; newSubrange->list_fixedRegRequirements = subrange->list_fixedRegRequirements; @@ -351,17 +351,17 @@ void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange // validate if(!newSubrange->list_accessLocations.empty()) { - cemu_assert_debug(newSubrange->list_accessLocations.front().pos >= newSubrange->interval2.start); - cemu_assert_debug(newSubrange->list_accessLocations.back().pos <= newSubrange->interval2.end); + cemu_assert_debug(newSubrange->list_accessLocations.front().pos >= newSubrange->interval.start); + cemu_assert_debug(newSubrange->list_accessLocations.back().pos <= newSubrange->interval.end); } if(!newSubrange->list_fixedRegRequirements.empty()) { - cemu_assert_debug(newSubrange->list_fixedRegRequirements.front().pos >= newSubrange->interval2.start); // fixed register requirements outside of the actual access range probably means there is a mistake in GetInstructionFixedRegisters() - cemu_assert_debug(newSubrange->list_fixedRegRequirements.back().pos <= newSubrange->interval2.end); + cemu_assert_debug(newSubrange->list_fixedRegRequirements.front().pos >= newSubrange->interval.start); // fixed register requirements outside of the actual access range probably means there is a mistake in GetInstructionFixedRegisters() + cemu_assert_debug(newSubrange->list_fixedRegRequirements.back().pos <= newSubrange->interval.end); } } - // remove subranges - PPCRecRA_deleteSubrangeCluster(ppcImlGenContext, originRange); + // delete the original range cluster + IMLRA_DeleteRangeCluster(ppcImlGenContext, originRange); } #ifdef CEMU_DEBUG_ASSERT @@ -408,19 +408,19 @@ void IMLRA_TrimRangeToUse(raLivenessRange* range) if(range->list_accessLocations.empty()) { // special case where we trim ranges extending from other segments to a single instruction edge - cemu_assert_debug(!range->interval2.start.IsInstructionIndex() || !range->interval2.end.IsInstructionIndex()); - if(range->interval2.start.IsInstructionIndex()) - range->interval2.start = range->interval2.end; - if(range->interval2.end.IsInstructionIndex()) - range->interval2.end = range->interval2.start; + cemu_assert_debug(!range->interval.start.IsInstructionIndex() || !range->interval.end.IsInstructionIndex()); + if(range->interval.start.IsInstructionIndex()) + range->interval.start = range->interval.end; + if(range->interval.end.IsInstructionIndex()) + range->interval.end = range->interval.start; return; } // trim start and end - raInterval prevInterval = range->interval2; - if(range->interval2.start.IsInstructionIndex()) - range->interval2.start = range->list_accessLocations.front().pos; - if(range->interval2.end.IsInstructionIndex()) - range->interval2.end = range->list_accessLocations.back().pos; + raInterval prevInterval = range->interval; + if(range->interval.start.IsInstructionIndex()) + range->interval.start = range->list_accessLocations.front().pos; + if(range->interval.end.IsInstructionIndex()) + range->interval.end = range->list_accessLocations.back().pos; // extra checks #ifdef CEMU_DEBUG_ASSERT cemu_assert_debug(range->interval2.start <= range->interval2.end); @@ -438,22 +438,20 @@ void IMLRA_TrimRangeToUse(raLivenessRange* range) // tail -> a new subrange that ranges from splitIndex (inclusive) to the end of the original subrange // if head has a physical register assigned it will not carry over to tail // The return value is the tail range -// If trimToHole is true, the end of the head subrange and the start of the tail subrange will be shrunk to fit the read/write locations within them -// the range after the split point does not inherit the physical register -// if trimToHole is true and any of the halfes is empty, it will be deleted -raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange*& subrange, raInstructionEdge splitPosition, bool trimToHole) +// If trimToUsage is true, the end of the head subrange and the start of the tail subrange will be shrunk to fit the read/write locations within. If there are no locations then the range will be deleted +raLivenessRange* IMLRA_SplitRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange*& subrange, raInstructionEdge splitPosition, bool trimToUsage) { cemu_assert_debug(splitPosition.IsInstructionIndex()); - cemu_assert_debug(!subrange->interval2.IsNextSegmentOnly() && !subrange->interval2.IsPreviousSegmentOnly()); - cemu_assert_debug(subrange->interval2.ContainsEdge(splitPosition)); + cemu_assert_debug(!subrange->interval.IsNextSegmentOnly() && !subrange->interval.IsPreviousSegmentOnly()); + cemu_assert_debug(subrange->interval.ContainsEdge(splitPosition)); // determine new intervals raInterval headInterval, tailInterval; - headInterval.SetInterval(subrange->interval2.start, splitPosition-1); - tailInterval.SetInterval(splitPosition, subrange->interval2.end); + headInterval.SetInterval(subrange->interval.start, splitPosition-1); + tailInterval.SetInterval(splitPosition, subrange->interval.end); cemu_assert_debug(headInterval.start <= headInterval.end); cemu_assert_debug(tailInterval.start <= tailInterval.end); // create tail - raLivenessRange* tailSubrange = PPCRecRA_createSubrange2(ppcImlGenContext, subrange->imlSegment, subrange->GetVirtualRegister(), subrange->GetName(), tailInterval.start, tailInterval.end); + raLivenessRange* tailSubrange = IMLRA_CreateRange(ppcImlGenContext, subrange->imlSegment, subrange->GetVirtualRegister(), subrange->GetName(), tailInterval.start, tailInterval.end); tailSubrange->SetPhysicalRegister(subrange->GetPhysicalRegister()); // carry over branch targets and update reverse references tailSubrange->subrangeBranchTaken = subrange->subrangeBranchTaken; @@ -505,23 +503,23 @@ raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenConte } } // adjust intervals - subrange->interval2 = headInterval; - tailSubrange->interval2 = tailInterval; + subrange->interval = headInterval; + tailSubrange->interval = tailInterval; // trim to hole - if(trimToHole) + if(trimToUsage) { - if(subrange->list_accessLocations.empty() && (subrange->interval2.start.IsInstructionIndex() && subrange->interval2.end.IsInstructionIndex())) + if(subrange->list_accessLocations.empty() && (subrange->interval.start.IsInstructionIndex() && subrange->interval.end.IsInstructionIndex())) { - PPCRecRA_deleteSubrange(ppcImlGenContext, subrange); + IMLRA_DeleteRange(ppcImlGenContext, subrange); subrange = nullptr; } else { IMLRA_TrimRangeToUse(subrange); } - if(tailSubrange->list_accessLocations.empty() && (tailSubrange->interval2.start.IsInstructionIndex() && tailSubrange->interval2.end.IsInstructionIndex())) + if(tailSubrange->list_accessLocations.empty() && (tailSubrange->interval.start.IsInstructionIndex() && tailSubrange->interval.end.IsInstructionIndex())) { - PPCRecRA_deleteSubrange(ppcImlGenContext, tailSubrange); + IMLRA_DeleteRange(ppcImlGenContext, tailSubrange); tailSubrange = nullptr; } else @@ -530,11 +528,11 @@ raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenConte } } // validation - cemu_assert_debug(!subrange || subrange->interval2.start <= subrange->interval2.end); - cemu_assert_debug(!tailSubrange || tailSubrange->interval2.start <= tailSubrange->interval2.end); - cemu_assert_debug(!tailSubrange || tailSubrange->interval2.start >= splitPosition); - if (!trimToHole) - cemu_assert_debug(!tailSubrange || tailSubrange->interval2.start == splitPosition); + cemu_assert_debug(!subrange || subrange->interval.start <= subrange->interval.end); + cemu_assert_debug(!tailSubrange || tailSubrange->interval.start <= tailSubrange->interval.end); + cemu_assert_debug(!tailSubrange || tailSubrange->interval.start >= splitPosition); + if (!trimToUsage) + cemu_assert_debug(!tailSubrange || tailSubrange->interval.start == splitPosition); if(subrange) PPCRecRA_debugValidateSubrange(subrange); @@ -560,8 +558,8 @@ sint32 IMLRA_CalculateAdditionalCostOfRangeExplode(raLivenessRange* subrange) if (subrange->list_accessLocations.empty()) continue; // this range would be deleted and thus has no cost sint32 segmentLoadStoreCost = IMLRA_GetSegmentReadWriteCost(subrange->imlSegment); - bool hasAdditionalLoad = subrange->interval2.ExtendsPreviousSegment(); - bool hasAdditionalStore = subrange->interval2.ExtendsIntoNextSegment(); + bool hasAdditionalLoad = subrange->interval.ExtendsPreviousSegment(); + bool hasAdditionalStore = subrange->interval.ExtendsIntoNextSegment(); if(hasAdditionalLoad && subrange->list_accessLocations.front().IsWrite()) // if written before read then a load isn't necessary { cemu_assert_debug(!subrange->list_accessLocations.front().IsRead()); diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.h b/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.h index bc78a1155..b0685cc56 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.h +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLRegisterAllocatorRanges.h @@ -302,7 +302,7 @@ struct raFixedRegRequirement struct raLivenessRange { IMLSegment* imlSegment; - raInterval interval2; + raInterval interval; // dirty state tracking bool _noLoad; @@ -327,7 +327,7 @@ struct raLivenessRange IMLRegID virtualRegister; IMLName name; // register allocator result - sint32 physicalRegister; + IMLPhysReg physicalRegister; boost::container::small_vector GetAllSubrangesInCluster(); bool GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters); // if the cluster has fixed register requirements in any instruction this returns the combined register mask. Otherwise returns false in which case allowedRegisters is left undefined @@ -337,23 +337,23 @@ struct raLivenessRange sint32 GetPhysicalRegister() const; bool HasPhysicalRegister() const { return physicalRegister >= 0; } IMLName GetName() const; - void SetPhysicalRegister(sint32 physicalRegister); - void SetPhysicalRegisterForCluster(sint32 physicalRegister); + void SetPhysicalRegister(IMLPhysReg physicalRegister); + void SetPhysicalRegisterForCluster(IMLPhysReg physicalRegister); void UnsetPhysicalRegister() { physicalRegister = -1; } private: void GetAllowedRegistersExRecursive(raLivenessRange* range, uint32 iterationIndex, IMLPhysRegisterSet& allowedRegs); }; -raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition); -void PPCRecRA_deleteSubrange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange); +raLivenessRange* IMLRA_CreateRange(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition); +void IMLRA_DeleteRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange); void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext); -void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange); +void IMLRA_ExplodeRangeCluster(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange); -void PPCRecRA_mergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange, raLivenessRange* absorbedSubrange); +void IMLRA_MergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange, raLivenessRange* absorbedSubrange); -raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange*& subrange, raInstructionEdge splitPosition, bool trimToHole = false); +raLivenessRange* IMLRA_SplitRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange*& subrange, raInstructionEdge splitPosition, bool trimToUsage = false); void PPCRecRA_debugValidateSubrange(raLivenessRange* subrange); diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp b/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp index 733c6e5a5..762647170 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp @@ -19,6 +19,7 @@ #include "util/highresolutiontimer/HighResolutionTimer.h" #define PPCREC_FORCE_SYNCHRONOUS_COMPILATION 0 // if 1, then function recompilation will block and execute on the thread that called PPCRecompiler_visitAddressNoBlock +#define PPCREC_LOG_RECOMPILATION_RESULTS 0 struct PPCInvalidationRange { @@ -185,8 +186,10 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP ppcRecFunc->ppcAddress = range.startAddress; ppcRecFunc->ppcSize = range.length; +#if PPCREC_LOG_RECOMPILATION_RESULTS BenchmarkTimer bt; bt.Start(); +#endif // generate intermediate code ppcImlGenContext_t ppcImlGenContext = { 0 }; @@ -217,18 +220,6 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP return nullptr; } - // if (ppcRecFunc->ppcAddress == 0x2BDA9F4) - // { - // IMLDebug_Dump(&ppcImlGenContext); - // __debugbreak(); - // } - - // Functions for testing (botw): - // 3B4049C (large with switch case) - // 30BF118 (has a bndz copy loop + some float instructions at the end) - - - // emit x64 code bool x64GenerationSuccess = PPCRecompiler_generateX64Code(ppcRecFunc, &ppcImlGenContext); if (x64GenerationSuccess == false) @@ -258,18 +249,16 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP entryPointsOut.emplace_back(ppcEnterOffset, x64Offset); } +#if PPCREC_LOG_RECOMPILATION_RESULTS bt.Stop(); - - //cemuLog_log(LogType::Force, "[Recompiler] Successfully compiled {:08x} - {:08x} Segments: {} Entrypoints: {}", ppcRecFunc->ppcAddress, ppcRecFunc->ppcAddress + ppcRecFunc->ppcSize, ppcImlGenContext.segmentList2.size(), entryPointsOut.size()); - uint32 codeHash = 0; for (uint32 i = 0; i < ppcRecFunc->x86Size; i++) { codeHash = _rotr(codeHash, 3); codeHash += ((uint8*)ppcRecFunc->x86Code)[i]; } - cemuLog_log(LogType::Force, "[Recompiler] PPC 0x{:08x} -> x64: 0x{:x} Took {:.4}ms | Size {:04x} CodeHash {:08x}", (uint32)ppcRecFunc->ppcAddress, (uint64)(uintptr_t)ppcRecFunc->x86Code, bt.GetElapsedMilliseconds(), ppcRecFunc->x86Size, codeHash); +#endif return ppcRecFunc; } diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp index cf25128b6..9b74e45b8 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp @@ -3008,7 +3008,6 @@ void PPCRecompiler_SetSegmentsUncertainFlow(ppcImlGenContext_t& ppcImlGenContext break; case PPCREC_IML_MACRO_DEBUGBREAK: case PPCREC_IML_MACRO_COUNT_CYCLES: - case PPCREC_IML_MACRO_MFTB: break; default: cemu_assert_unimplemented();