From 6cc4f593e54fbce4f9b8920ae4053549050e86a1 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 29 Jun 2021 15:18:55 +0200 Subject: [PATCH] PPCAnalyst: Add in-register/discard analysis for CR This brings the analysis done for condition registers more in line with the analysis done for GPRs and FPRs. This gets rid of the old wantsCR member, which wasn't actually used anyway. In case someone wants it again in the future, they can compute the bitwise inverse of crDiscardable. --- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 41 +++++++++++++------------ Source/Core/Core/PowerPC/PPCAnalyst.h | 6 +++- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 01feaffd45..2dd988d6c2 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -506,7 +506,7 @@ void PPCAnalyzer::ReorderInstructionsCore(u32 instructions, CodeOp* code, bool r // Reorder integer compares, rlwinm., and carry-affecting ops // (if we add more merged branch instructions, add them here!) if ((type == ReorderType::CROR && isCror(a)) || (type == ReorderType::Carry && isCarryOp(a)) || - (type == ReorderType::CMP && (isCmp(a) || a.outputCR[0]))) + (type == ReorderType::CMP && (isCmp(a) || a.crOut[0]))) { // once we're next to a carry instruction, don't move away! if (type == ReorderType::Carry && i != start) @@ -570,40 +570,40 @@ void PPCAnalyzer::SetInstructionStats(CodeBlock* block, CodeOp* code, block->m_fpa->any = true; } - code->wantsCR = BitSet8(0); + code->crIn = BitSet8(0); if (opinfo->flags & FL_READ_ALL_CR) { - code->wantsCR = BitSet8(0xFF); + code->crIn = BitSet8(0xFF); } else if (opinfo->flags & FL_READ_CRn) { - code->wantsCR[code->inst.CRFS] = true; + code->crIn[code->inst.CRFS] = true; } else if (opinfo->flags & FL_READ_CR_BI) { - code->wantsCR[code->inst.BI] = true; + code->crIn[code->inst.BI] = true; } else if (opinfo->type == OpType::CR) { - code->wantsCR[code->inst.CRBA >> 2] = true; - code->wantsCR[code->inst.CRBB >> 2] = true; + code->crIn[code->inst.CRBA >> 2] = true; + code->crIn[code->inst.CRBB >> 2] = true; // CR instructions only write to one bit of the destination CR, // so treat the other three bits of the destination as inputs - code->wantsCR[code->inst.CRBD >> 2] = true; + code->crIn[code->inst.CRBD >> 2] = true; } - code->outputCR = BitSet8(0); + code->crOut = BitSet8(0); if (opinfo->flags & FL_SET_ALL_CR) - code->outputCR = BitSet8(0xFF); + code->crOut = BitSet8(0xFF); else if (opinfo->flags & FL_SET_CRn) - code->outputCR[code->inst.CRFD] = true; + code->crOut[code->inst.CRFD] = true; else if ((opinfo->flags & FL_SET_CR0) || ((opinfo->flags & FL_RC_BIT) && code->inst.Rc)) - code->outputCR[0] = true; + code->crOut[0] = true; else if ((opinfo->flags & FL_SET_CR1) || ((opinfo->flags & FL_RC_BIT_F) && code->inst.Rc)) - code->outputCR[1] = true; + code->crOut[1] = true; else if (opinfo->type == OpType::CR) - code->outputCR[code->inst.CRBD >> 2] = true; + code->crOut[code->inst.CRBD >> 2] = true; code->wantsFPRF = (opinfo->flags & FL_READ_FPRF) != 0; code->outputFPRF = (opinfo->flags & FL_SET_FPRF) != 0; @@ -972,9 +972,9 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, // Scan for flag dependencies; assume the next block (or any branch that can leave the block) // wants flags, to be safe. - BitSet8 wantsCR = BitSet8(0xFF); bool wantsFPRF = true; bool wantsCA = true; + BitSet8 crInUse, crDiscardable; BitSet32 gprBlockInputs, gprInUse, fprInUse, gprDiscardable, fprDiscardable, fprInXmm; for (int i = block->m_num_instructions - 1; i >= 0; i--) { @@ -991,27 +991,26 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, const bool hle = !!HLE::TryReplaceFunction(op.address); const bool may_exit_block = hle || op.canEndBlock || op.canCauseException; - const BitSet8 opWantsCR = op.wantsCR; const bool opWantsFPRF = op.wantsFPRF; const bool opWantsCA = op.wantsCA; - op.wantsCR = wantsCR | BitSet8(may_exit_block ? 0xFF : 0); op.wantsFPRF = wantsFPRF || may_exit_block; op.wantsCA = wantsCA || may_exit_block; - wantsCR |= opWantsCR | BitSet8(may_exit_block ? 0xFF : 0); wantsFPRF |= opWantsFPRF || may_exit_block; wantsCA |= opWantsCA || may_exit_block; - wantsCR &= ~op.outputCR | opWantsCR; wantsFPRF &= !op.outputFPRF || opWantsFPRF; wantsCA &= !op.outputCA || opWantsCA; op.gprInUse = gprInUse; op.fprInUse = fprInUse; + op.crInUse = crInUse; op.gprDiscardable = gprDiscardable; op.fprDiscardable = fprDiscardable; + op.crDiscardable = crDiscardable; op.fprInXmm = fprInXmm; gprBlockInputs &= ~op.regsOut; gprBlockInputs |= op.regsIn; gprInUse |= op.regsIn | op.regsOut; fprInUse |= op.fregsIn | op.GetFregsOut(); + crInUse |= op.crIn | op.crOut; if (strncmp(op.opinfo->opname, "stfd", 4)) fprInXmm |= op.fregsIn; @@ -1023,11 +1022,13 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, fprInXmm = BitSet32{}; gprDiscardable = BitSet32{}; fprDiscardable = BitSet32{}; + crDiscardable = BitSet8{}; } else if (op.canEndBlock || op.canCauseException) { gprDiscardable = BitSet32{}; fprDiscardable = BitSet32{}; + crDiscardable = BitSet8{}; } else { @@ -1035,6 +1036,8 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, gprDiscardable &= ~op.regsIn; fprDiscardable |= op.GetFregsOut(); fprDiscardable &= ~op.fregsIn; + crDiscardable |= op.crOut; + crDiscardable &= ~op.crIn; } } diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.h b/Source/Core/Core/PowerPC/PPCAnalyst.h index 1c24120cc9..1bd25ae476 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.h +++ b/Source/Core/Core/PowerPC/PPCAnalyst.h @@ -32,10 +32,12 @@ struct CodeOp // 16B const GekkoOPInfo* opinfo = nullptr; u32 address = 0; u32 branchTo = 0; // if UINT32_MAX, not a branch - BitSet32 regsOut; BitSet32 regsIn; + BitSet32 regsOut; BitSet32 fregsIn; s8 fregOut = 0; + BitSet8 crIn; + BitSet8 crOut; bool isBranchTarget = false; bool branchUsesCtr = false; bool branchIsIdleLoop = false; @@ -50,6 +52,8 @@ struct CodeOp // 16B bool canCauseException = false; bool skipLRStack = false; bool skip = false; // followed BL-s for example + BitSet8 crInUse; + BitSet8 crDiscardable; // which registers are still needed after this instruction in this block BitSet32 fprInUse; BitSet32 gprInUse;