From 24cb2610a2e6aae48a34ebb349c91efbccf7f138 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 16 Jul 2023 21:37:54 -0700 Subject: [PATCH] OpcodeDispatcher: Another FCMov minor optimization If we are loading exactly the flags we need from the RFLAGS (ensuring we don't load the reserved flag in bit 1) then we don't need to do a mask on the result. Additionally there is some bad code-motion around selects that was causing SBFE operations to occur on constants. Ensure that we const-prop any SBFE operations to clean this up. This PR along with #2783 causes FMOV blow-up to go from 41 instruction to 31 instructions. --- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 2 +- .../Interface/Core/OpcodeDispatcher/X87.cpp | 7 ++----- .../Source/Interface/IR/Passes/ConstProp.cpp | 19 +++++++++++++++++++ .../FEXCore/include/FEXCore/Core/X86Enums.h | 1 + 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 8c0bcccf5..0b1ed3117 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -63,7 +63,7 @@ OrderedNode *OpDispatchBuilder::GetPackedRFLAG(uint32_t FlagsMask) { // Calculate flags early. CalculateDeferredFlags(); - OrderedNode *Original = _Constant(2); + OrderedNode *Original = _Constant((1U << X86State::RFLAG_RESERVED_LOC) & FlagsMask ? 2 : 0); for (size_t i = 0; i < FlagOffsets.size(); ++i) { const auto FlagOffset = FlagOffsets[i]; if (!((1U << FlagOffset) & FlagsMask)) { diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index e97626916..3af970f6c 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -1357,20 +1357,17 @@ void OpDispatchBuilder::X87FCMOV(OpcodeArgs) { break; } - auto MaskConst = _Constant(FLAGMask); - auto RFLAG = GetPackedRFLAG(FLAGMask); - auto AndOp = _And(RFLAG, MaskConst); switch (Type) { case COMPARE_ZERO: { SrcCond = _Select(FEXCore::IR::COND_EQ, - AndOp, ZeroConst, OneConst, ZeroConst); + RFLAG, ZeroConst, OneConst, ZeroConst); break; } case COMPARE_NOTZERO: { SrcCond = _Select(FEXCore::IR::COND_EQ, - AndOp, ZeroConst, ZeroConst, OneConst); + RFLAG, ZeroConst, ZeroConst, OneConst); break; } } diff --git a/External/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp b/External/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp index 6a22a79a1..ed3ded59d 100644 --- a/External/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp +++ b/External/FEXCore/Source/Interface/IR/Passes/ConstProp.cpp @@ -813,6 +813,25 @@ bool ConstProp::ConstantPropagation(IREmitter *IREmit, const IRListView& Current break; } + case OP_SBFE: { + auto Op = IROp->C(); + uint64_t Constant; + if (IREmit->IsValueConstant(Op->Src, &Constant)) { + // SBFE of a constant can be converted to a constant. + uint64_t SourceMask = (1ULL << Op->Width) - 1; + if (Op->Width == 64) + SourceMask = ~0ULL; + SourceMask <<= Op->lsb; + + int64_t NewConstant = (Constant & SourceMask) >> Op->lsb; + NewConstant <<= 64 - Op->Width; + NewConstant >>= 64 - Op->Width; + IREmit->ReplaceWithConstant(CodeNode, NewConstant); + + Changed = true; + } + break; + } case OP_MUL: { auto Op = IROp->C(); uint64_t Constant1{}; diff --git a/External/FEXCore/include/FEXCore/Core/X86Enums.h b/External/FEXCore/include/FEXCore/Core/X86Enums.h index bfbe4821c..a28c942cd 100644 --- a/External/FEXCore/include/FEXCore/Core/X86Enums.h +++ b/External/FEXCore/include/FEXCore/Core/X86Enums.h @@ -56,6 +56,7 @@ enum X86Reg : uint32_t { * @{ */ enum X86RegLocation : uint32_t { RFLAG_CF_LOC = 0, + RFLAG_RESERVED_LOC = 1, // Reserved Bit, Read-as-1 RFLAG_PF_LOC = 2, RFLAG_AF_LOC = 4, RFLAG_ZF_LOC = 6,