From ea8b7633ebc85aa5ef2df3ca4fe252a46753f79f Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Sun, 24 Sep 2023 16:46:56 -0400 Subject: [PATCH] OpcodeDispatcher: Optimize OF calc of immediates If we know the sign of one of the sources, we can do better when calculating OF. Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 3f17e37ba..daa8a9306 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -202,11 +202,29 @@ OrderedNode *OpDispatchBuilder::GetPackedRFLAG(uint32_t FlagsMask) { void OpDispatchBuilder::CalculateOF_Add(uint8_t SrcSize, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) { auto OpSize = SrcSize == 8 ? OpSize::i64Bit : OpSize::i32Bit; - auto XorOp1 = _Xor(OpSize, Src1, Src2); - auto XorOp2 = _Xor(OpSize, Res, Src1); - OrderedNode *AndOp1 = _Andn(OpSize, XorOp2, XorOp1); - AndOp1 = _Bfe(OpSize, 1, SrcSize * 8 - 1, AndOp1); - SetRFLAG(AndOp1); + uint64_t SignBit = (SrcSize * 8) - 1; + OrderedNode *Anded = nullptr; + + // OF is set iff the sources have the same sign but the destination sign + // differs. If we know a source sign, we can simplify the expression: if + // source 2 is known to be positive, we set OF if source 1 is positive and + // source 2 is negative. Similarly if source 2 is known negative. + uint64_t Const; + if (IsValueConstant(WrapNode(Src2), &Const)) { + bool Negative = (Const & (1ull << SignBit)) != 0; + + if (Negative) + Anded = _Andn(OpSize, Src1, Res); + else + Anded = _Andn(OpSize, Res, Src1); + } else { + auto XorOp1 = _Xor(OpSize, Src1, Src2); + auto XorOp2 = _Xor(OpSize, Res, Src1); + Anded = _Andn(OpSize, XorOp2, XorOp1); + } + + auto OF = _Bfe(OpSize, 1, SrcSize * 8 - 1, Anded); + SetRFLAG(OF); } OrderedNode *OpDispatchBuilder::LoadPFRaw() {