From 9fc31f658521c28e3c439545ca250de7553418b0 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Sat, 7 Sep 2024 10:18:13 -0400 Subject: [PATCH] RedundantFlagCalculationElimination: use LUT thanks, Tony! Signed-off-by: Alyssa Rosenzweig --- .../RedundantFlagCalculationElimination.cpp | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/FEXCore/Source/Interface/IR/Passes/RedundantFlagCalculationElimination.cpp b/FEXCore/Source/Interface/IR/Passes/RedundantFlagCalculationElimination.cpp index e3eba6a0bc..15d856a446 100644 --- a/FEXCore/Source/Interface/IR/Passes/RedundantFlagCalculationElimination.cpp +++ b/FEXCore/Source/Interface/IR/Passes/RedundantFlagCalculationElimination.cpp @@ -7,6 +7,7 @@ desc: This is not used right now, possibly broken */ #include "FEXCore/Core/X86Enums.h" +#include "FEXCore/Utils/CompilerDefs.h" #include "FEXCore/Utils/MathUtils.h" #include "FEXCore/fextl/deque.h" #include "Interface/IR/IR.h" @@ -47,13 +48,17 @@ struct FlagInfoUnpacked { // eliminated. IROps Replacement; IROps ReplacementNoWrite; + + // Needs speical handling + bool Special; }; struct FlagInfo { uint64_t Raw; static constexpr struct FlagInfo Pack(struct FlagInfoUnpacked F) { - uint64_t R = F.Read | (F.Write << 8) | (F.CanEliminate << 16) | (((uint64_t)F.Replacement) << 32) | ((uint64_t)F.ReplacementNoWrite << 48); + uint64_t R = F.Read | (F.Write << 8) | (F.CanEliminate << 16) | (((uint64_t)F.Replacement) << 32) | + ((uint64_t)F.ReplacementNoWrite << 48) | (F.Special ? (1ull << 63) : 0); return {.Raw = R}; } @@ -73,6 +78,10 @@ struct FlagInfo { return Bits(16, 1); } + bool Special() { + return Bits(63, 1); + } + IROps Replacement() { return (IROps)Bits(32, 16); } @@ -186,8 +195,8 @@ unsigned DeadFlagCalculationEliminination::FlagsForCondClassType(CondClassType C } } -FlagInfo DeadFlagCalculationEliminination::Classify(IROp_Header* IROp) { - switch (IROp->Op) { +constexpr FlagInfo ClassifyConst(IROps Op) { + switch (Op) { case OP_ANDWITHFLAGS: return FlagInfo::Pack({ .Write = FLAG_NZCV, @@ -309,6 +318,35 @@ FlagInfo DeadFlagCalculationEliminination::Classify(IROp_Header* IROp) { case OP_STOREPF: return FlagInfo::Pack({.Write = FLAG_P, .CanEliminate = true}); case OP_STOREAF: return FlagInfo::Pack({.Write = FLAG_A, .CanEliminate = true}); + case OP_NZCVSELECT: + case OP_NZCVSELECTINCREMENT: + case OP_NEG: + case OP_CONDJUMP: + case OP_CONDSUBNZCV: + case OP_CONDADDNZCV: + case OP_RMIFNZCV: + case OP_INVALIDATEFLAGS: return FlagInfo::Pack({.Special = true}); + default: return FlagInfo::Pack({}); + } +} + +constexpr auto FlagInfos = std::invoke([] { + std::array ret = {}; + + for (unsigned i = 0; i < OP_LAST; ++i) { + ret[i] = ClassifyConst((IROps)i); + } + + return ret; +}); + +FlagInfo DeadFlagCalculationEliminination::Classify(IROp_Header* IROp) { + FlagInfo Info = FlagInfos[IROp->Op]; + if (!Info.Special()) { + return Info; + } + + switch (IROp->Op) { case OP_NZCVSELECT: case OP_NZCVSELECTINCREMENT: { auto Op = IROp->CW(); @@ -323,7 +361,7 @@ FlagInfo DeadFlagCalculationEliminination::Classify(IROp_Header* IROp) { case OP_CONDJUMP: { auto Op = IROp->CW(); if (!Op->FromNZCV) { - break; + return FlagInfo::Pack({}); } return FlagInfo::Pack({.Read = FlagsForCondClassType(Op->Cond)}); @@ -391,10 +429,10 @@ FlagInfo DeadFlagCalculationEliminination::Classify(IROp_Header* IROp) { }); } - default: break; + default: LOGMAN_THROW_AA_FMT(false, "invalid special op"); FEX_UNREACHABLE; } - return FlagInfo::Pack({}); + FEX_UNREACHABLE; } // General purpose dead code elimination. Returns whether flag handling should