From 711b56c9f628738fc27d6b0d4db5ff883814b64c Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Fri, 25 Oct 2024 08:51:22 +0200 Subject: [PATCH] PPCRec: Reintroduce optimization for BDNZ loops --- .../Recompiler/PPCRecompilerImlGen.cpp | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp index 928bbc90..cf25128b 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp @@ -2930,6 +2930,30 @@ void PPCIMLGen_AssertIfNotLastSegmentInstruction(ppcImlGenContext_t& ppcImlGenCo cemu_assert_debug(ppcImlGenContext.currentBasicBlock->lastAddress == ppcImlGenContext.ppcAddressOfCurrentInstruction); } +bool PPCRecompiler_IsBasicBlockATightFiniteLoop(IMLSegment* imlSegment, PPCBasicBlockInfo& basicBlockInfo) +{ + // if we detect a finite loop we can skip generating the cycle check + // currently we only check for BDNZ loops since thats reasonably safe to rely on + // however there are other forms of loops that can be classified as finite, + // but detecting those involves analyzing PPC code and we dont have the infrastructure for that (e.g. IML has CheckRegisterUsage but we dont have an equivalent for PPC code) + + // base criteria, must jump to beginning of same segment + if (imlSegment->nextSegmentBranchTaken != imlSegment) + return false; + + uint32 opcode = *(uint32be*)(memory_base + basicBlockInfo.lastAddress); + if (Espresso::GetPrimaryOpcode(opcode) != Espresso::PrimaryOpcode::BC) + return false; + uint32 BO, BI, BD; + PPC_OPC_TEMPL_B(opcode, BO, BI, BD); + Espresso::BOField boField(BO); + if(!boField.conditionIgnore() || boField.branchAlways()) + return false; + if(boField.decrementerIgnore()) + return false; + return true; +} + void PPCRecompiler_HandleCycleCheckCount(ppcImlGenContext_t& ppcImlGenContext, PPCBasicBlockInfo& basicBlockInfo) { IMLSegment* imlSegment = basicBlockInfo.GetFirstSegmentInChain(); @@ -2938,8 +2962,7 @@ void PPCRecompiler_HandleCycleCheckCount(ppcImlGenContext_t& ppcImlGenContext, P if (basicBlockInfo.branchTarget > basicBlockInfo.startAddress) return; - // exclude non-infinite tight loops - if (IMLAnalyzer_IsTightFiniteLoop(imlSegment)) + if (PPCRecompiler_IsBasicBlockATightFiniteLoop(imlSegment, basicBlockInfo)) return; // make the segment enterable so execution can return after passing a check