From 33a2fbb89659e41a3ca6aec714a67e61ba0fd7c3 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 13 Sep 2023 13:50:59 -0700 Subject: [PATCH] OpcodeDispatcher: Optimize pextr{b,w} Cleans up the code which had special cased some 32-bit optimization which is unnecessary now that both 8-bit and 16-bit are also optimized. When FEX does a VExtractToGPR, the result is zero extended to the full GPR register size. This means we don't need to do a zero extend when storing to a guest GPR. Makes pextr{b,w} optimal now. Needs #3088 merged first. --- .../Core/OpcodeDispatcher/Vector.cpp | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 9d90c46b7..090da92b7 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -1609,34 +1609,36 @@ void OpDispatchBuilder::VINSERTPSOp(OpcodeArgs) { template void OpDispatchBuilder::PExtrOp(OpcodeArgs) { - const auto Size = GetSrcSize(Op); const auto DstSize = GetDstSize(Op); - const auto Is32Bit = ElementSize == 4; OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here"); uint64_t Index = Op->Src[1].Data.Literal.Value; - const uint8_t NumElements = Is32Bit ? Size / DstSize - : Size / ElementSize; - Index &= NumElements - 1; + // Fixup of 32-bit element size. + // When the element size is 32-bit then it can be overriden as 64-bit because the encoding of PEXTRD/PEXTRQ + // is the same except that REX.W or VEX.W is set to 1. Incredibly frustrating. + // Use the destination size as the element size in this case. + size_t OverridenElementSize = ElementSize; + if constexpr (ElementSize == 4) { + OverridenElementSize = DstSize; + } - OrderedNode *Result = Is32Bit ? _VExtractToGPR(16, DstSize, Src, Index) - : _VExtractToGPR(16, ElementSize, Src, Index); + // AVX version only operates on 128-bit. + const uint8_t NumElements = std::min(GetSrcSize(Op), 16) / OverridenElementSize; + Index &= NumElements - 1; if (Op->Dest.IsGPR()) { const uint8_t GPRSize = CTX->GetGPRSize(); - - // If we are storing to a GPR then we zero extend it - if constexpr (ElementSize < 4) { - Result = _Bfe(IR::SizeToOpSize(GPRSize), ElementSize * 8, 0, Result); - } + // Extract already zero extends the result. + OrderedNode *Result = _VExtractToGPR(16, OverridenElementSize, Src, Index); StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Result, GPRSize, -1); - } else { - // If we are storing to memory then we store the size of the element extracted - const auto StoreSize = Is32Bit ? DstSize : ElementSize; - StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Result, StoreSize, -1); + return; } + + // If we are storing to memory then we store the size of the element extracted + OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, -1, false); + _VStoreVectorElement(16, OverridenElementSize, Src, Index, Dest); } template