From 3dd597a591908d84fb8b04f231dc972073954305 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Wed, 24 Jan 2024 15:14:14 -0400 Subject: [PATCH] OpcodeDispatcher: optimize lzcnt Signed-off-by: Alyssa Rosenzweig --- .../Source/Interface/Core/OpcodeDispatcher.cpp | 2 +- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index ad6af79f2..77f08fbb6 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5387,7 +5387,7 @@ void OpDispatchBuilder::LZCNT(OpcodeArgs) { auto Res = _CountLeadingZeroes(OpSizeFromSrc(Op), Src); StoreResult(GPRClass, Op, Res, -1); - GenerateFlags_LZCNT(Op, Src); + GenerateFlags_LZCNT(Op, Res); } void OpDispatchBuilder::MOVBEOp(OpcodeArgs) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 3593f3444..30c8c7942 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -1091,18 +1091,16 @@ void OpDispatchBuilder::CalculateFlags_TZCNT(OrderedNode *Src) { SetRFLAG(Src, 0, true); } -void OpDispatchBuilder::CalculateFlags_LZCNT(uint8_t SrcSize, OrderedNode *Src) { +void OpDispatchBuilder::CalculateFlags_LZCNT(uint8_t SrcSize, OrderedNode *Result) { // OF, SF, AF, PF all undefined - ZeroNZCV(); + // Test ZF of result, SF is undefined so this is ok. + SetNZ_ZeroCV(SrcSize, Result); - auto Zero = _Constant(0); - auto ZFResult = _Select(FEXCore::IR::COND_EQ, - Src, Zero, - _Constant(1), Zero); - - // Set flags - SetRFLAG(ZFResult); - SetRFLAG(Src, SrcSize * 8 - 1, true); + // Now set CF if the Result = SrcSize * 8. Since SrcSize is a power-of-two and + // Result is <= SrcSize * 8, we equivalently check if the log2(SrcSize * 8) + // bit is set. No masking is needed because no higher bits could be set. + unsigned CarryBit = FEXCore::ilog2(SrcSize * 8u); + SetRFLAG(Result, CarryBit); } void OpDispatchBuilder::CalculateFlags_RDRAND(OrderedNode *Src) {