From 07c146e7e2c244b6a217fa9f07139f7e116649b6 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Fri, 21 Dec 2018 11:03:03 +0000 Subject: [PATCH 1/2] crXXX: Remove unnecessary CRBA == CRBD constraint for crclr and crset --- Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp index 2ff1c37986..f9eeb83e13 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -553,14 +553,14 @@ void Jit64::crXXX(UGeckoInstruction inst) DEBUG_ASSERT_MSG(DYNA_REC, inst.OPCD == 19, "Invalid crXXX"); // Special case: crclr - if (inst.CRBA == inst.CRBB && inst.CRBA == inst.CRBD && inst.SUBOP10 == 193) + if (inst.CRBA == inst.CRBB && inst.SUBOP10 == 193) { ClearCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3)); return; } // Special case: crset - if (inst.CRBA == inst.CRBB && inst.CRBA == inst.CRBD && inst.SUBOP10 == 289) + if (inst.CRBA == inst.CRBB && inst.SUBOP10 == 289) { SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3)); return; From 174d2b023090535906b4059cf36eb386ad8b3de3 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Fri, 21 Dec 2018 11:19:03 +0000 Subject: [PATCH 2/2] crXXX: Avoid loading twice when CRBA == CRBB --- .../PowerPC/Jit64/Jit_SystemRegisters.cpp | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp index f9eeb83e13..f14cd38994 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -552,23 +552,40 @@ void Jit64::crXXX(UGeckoInstruction inst) JITDISABLE(bJITSystemRegistersOff); DEBUG_ASSERT_MSG(DYNA_REC, inst.OPCD == 19, "Invalid crXXX"); - // Special case: crclr - if (inst.CRBA == inst.CRBB && inst.SUBOP10 == 193) - { - ClearCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3)); - return; - } + // TODO(merry): Futher optimizations can be performed here. For example, + // instead of extracting each CR field bit then setting it, the operation + // could be performed on the internal format directly instead and the + // relevant bit result can be masked out. - // Special case: crset - if (inst.CRBA == inst.CRBB && inst.SUBOP10 == 289) + if (inst.CRBA == inst.CRBB) { - SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3)); - return; - } + switch (inst.SUBOP10) + { + // crclr + case 129: // crandc: A && ~B => 0 + case 193: // crxor: A ^ B => 0 + ClearCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3)); + return; - // TODO(delroth): Potential optimizations could be applied here. For - // instance, if the two CR bits being loaded are the same, two loads are - // not required. + // crset + case 289: // creqv: ~(A ^ B) => 1 + case 417: // crorc: A || ~B => 1 + SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3)); + return; + + case 257: // crand: A && B => A + case 449: // cror: A || B => A + GetCRFieldBit(inst.CRBA >> 2, 3 - (inst.CRBA & 3), RSCRATCH, false); + SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), RSCRATCH); + return; + + case 33: // crnor: ~(A || B) => ~A + case 225: // crnand: ~(A && B) => ~A + GetCRFieldBit(inst.CRBA >> 2, 3 - (inst.CRBA & 3), RSCRATCH, true); + SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), RSCRATCH); + return; + } + } // creqv or crnand or crnor bool negateA = inst.SUBOP10 == 289 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33;