From a3115d46995f5d94ce571a6611023b21ded01c96 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 14 Sep 2023 16:21:42 -0700 Subject: [PATCH 1/2] OpcodeDispatcher: Optimize CRC32 The only version of this instruction that was generating optimal code was the one with 64-bit destination and source. Optimizes the rest of the operating sizes so that they are all optimal at one instruction translations --- FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index ec455a5e1..dc2678cea 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5722,17 +5722,24 @@ void OpDispatchBuilder::RDTSCPOp(OpcodeArgs) { } void OpDispatchBuilder::CRC32(OpcodeArgs) { + const uint8_t GPRSize = CTX->GetGPRSize(); + // Destination GPR size is always 4 or 8 bytes depending on widening uint8_t DstSize = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING ? 8 : 4; - OrderedNode *Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, DstSize, Op->Flags, -1); + OrderedNode *Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, GPRSize, Op->Flags, -1); // Incoming memory is 8, 16, 32, or 64 - OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, 1); + OrderedNode *Src{}; + if (Op->Src[0].IsGPR()) { + Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], GPRSize, Op->Flags, -1); + } + else { + Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, 1); + } auto Result = _CRC32(Dest, Src, GetSrcSize(Op)); StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Result, DstSize, -1); } - template void OpDispatchBuilder::RDRANDOp(OpcodeArgs) { auto Res = _RDRAND(Reseed); From 31ad26202ee103d54251b25535b4f574aa05b589 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 14 Sep 2023 16:23:33 -0700 Subject: [PATCH 2/2] InstCountCI: Update for Optimized CRC32 --- unittests/InstructionCountCI/H0F38.json | 31 ++++++++++--------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/unittests/InstructionCountCI/H0F38.json b/unittests/InstructionCountCI/H0F38.json index 30769c8f1..7489bc594 100644 --- a/unittests/InstructionCountCI/H0F38.json +++ b/unittests/InstructionCountCI/H0F38.json @@ -1047,50 +1047,43 @@ ] }, "crc32 eax, bl": { - "ExpectedInstructionCount": 3, - "Optimal": "No", + "ExpectedInstructionCount": 1, + "Optimal": "Yes", "Comment": [ "0xf2 0x0f 0x38 0xf0" ], "ExpectedArm64ASM": [ - "lsr w20, w4, #0", - "uxtb w21, w7", - "crc32cb w4, w20, w21" + "crc32cb w4, w4, w7" ] }, "crc32 eax, bx": { - "ExpectedInstructionCount": 3, - "Optimal": "No", + "ExpectedInstructionCount": 1, + "Optimal": "Yes", "Comment": [ "0xf2 0x0f 0x38 0xf1" ], "ExpectedArm64ASM": [ - "lsr w20, w4, #0", - "uxth w21, w7", - "crc32ch w4, w20, w21" + "crc32ch w4, w4, w7" ] }, "crc32 eax, ebx": { - "ExpectedInstructionCount": 3, - "Optimal": "No", + "ExpectedInstructionCount": 1, + "Optimal": "Yes", "Comment": [ "0xf2 0x0f 0x38 0xf1" ], "ExpectedArm64ASM": [ - "lsr w20, w4, #0", - "lsr w21, w7, #0", - "crc32cw w4, w20, w21" + "crc32cw w4, w4, w7" ] }, "crc32 rax, bl": { - "ExpectedInstructionCount": 2, - "Optimal": "No", + "ExpectedInstructionCount": 1, + "Optimal": "Yes", "Comment": [ "0xf2 0x0f 0x38 0xf0" ], "ExpectedArm64ASM": [ - "uxtb w20, w7", - "crc32cb w4, w4, w20" + "crc32cb w4, w4, w7" ] }, "crc32 rax, rbx": {