From b40f9db735953d24786e4e838aaacccf96d63d22 Mon Sep 17 00:00:00 2001 From: LC Date: Sun, 21 Jun 2026 01:11:59 -0400 Subject: [PATCH] [SVE256] Remove heavy handed moves from scalar compares (See #3799) I had a feeling #5569 was a little overkill, but was just getting everything up to a functional baseline at the time. Now, with the tests added in #5584 to test all SSE paths, I was able to see which comparisons in particular were the ones that would have deviating behavior (NLT and NLE) This lets us safely restore the behavior without the excessive moves on hardware that makes use of FEAT_AFP. --- .../Core/OpcodeDispatcher/Vector.cpp | 15 ++++++- .../AFP/SVE256/Secondary_REP.json | 42 ++++++------------- .../AFP/SVE256/Secondary_REPNE.json | 42 ++++++------------- 3 files changed, 38 insertions(+), 61 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 5dd4fb914..e4f11b4b9 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -606,7 +606,20 @@ void OpDispatchBuilder::InsertScalarFCMPOp(OpcodeArgs, IR::OpSize ElementSize) { Ref Src2 = LoadSourceFPR_WithOpSize(Op, Op->Src[0], SrcSize, Op->Flags, {.AllowUpperGarbage = true}); Ref Result = InsertScalarFCMPOpImpl(DstSize, OpSizeFromDst(Op), ElementSize, Src1, Src2, CompType & 0b111, false); - StoreResult_WithAVXInsert(VectorOpType::SSE, RegClass::FPR, Op, Result); + + // ARM doesn't have any instructions that handle the semantics of NLT and NLE directly. + // In fact, these are the two SSE compatison types where we cannot use VFCMPScalarInsert + // to handle them. They need to be handled separately due to negation. So, to avoid + // making all other comparison types suffer, we can just special case these two for insertion. + // + // All other comparison types do insertion as part of their behavior, so these can go down + // the non-insertion path. + const auto VCompType = VectorCompareType {CompType}; + if (VCompType == VectorCompareType::NLT_US || VCompType == VectorCompareType::NLE_US) { + StoreResult_WithAVXInsert(VectorOpType::SSE, RegClass::FPR, Op, Result); + } else { + StoreResultFPR(Op, Result); + } } void OpDispatchBuilder::AVXInsertScalarFCMPOp(OpcodeArgs, IR::OpSize ElementSize) { diff --git a/unittests/InstructionCountCI/AFP/SVE256/Secondary_REP.json b/unittests/InstructionCountCI/AFP/SVE256/Secondary_REP.json index 9136b65f8..32d85dca3 100644 --- a/unittests/InstructionCountCI/AFP/SVE256/Secondary_REP.json +++ b/unittests/InstructionCountCI/AFP/SVE256/Secondary_REP.json @@ -142,71 +142,56 @@ ] }, "cmpss xmm0, xmm1, 0": { - "ExpectedInstructionCount": 4, + "ExpectedInstructionCount": 1, "Comment": [ "0xf3 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", - "fcmeq s2, s17, s16", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "fcmeq s16, s17, s16" ] }, "cmpss xmm0, xmm1, 1": { - "ExpectedInstructionCount": 4, + "ExpectedInstructionCount": 1, "Comment": [ "0xf3 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", - "fcmgt s2, s17, s16", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "fcmgt s16, s17, s16" ] }, "cmpss xmm0, xmm1, 2": { - "ExpectedInstructionCount": 4, + "ExpectedInstructionCount": 1, "Comment": [ "0xf3 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", - "fcmge s2, s17, s16", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "fcmge s16, s17, s16" ] }, "cmpss xmm0, xmm1, 3": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 6, "Comment": [ "0xf3 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", "fcmge s0, s16, s17", "fcmgt s1, s17, s16", "orr v0.8b, v0.8b, v1.8b", "mvn v0.8b, v0.8b", "ptrue p0.s, vl1", - "mov z2.s, p0/m, z0.s", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "mov z16.s, p0/m, z0.s" ] }, "cmpss xmm0, xmm1, 4": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 4, "Comment": [ "0xf3 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", "fcmeq s0, s17, s16", "mvn v0.8b, v0.8b", "ptrue p0.s, vl1", - "mov z2.s, p0/m, z0.s", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "mov z16.s, p0/m, z0.s" ] }, "cmpss xmm0, xmm1, 5": { @@ -240,19 +225,16 @@ ] }, "cmpss xmm0, xmm1, 7": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 5, "Comment": [ "0xf3 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", "fcmge s0, s16, s17", "fcmgt s1, s17, s16", "orr v0.8b, v0.8b, v1.8b", "ptrue p0.s, vl1", - "mov z2.s, p0/m, z0.s", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "mov z16.s, p0/m, z0.s" ] } } diff --git a/unittests/InstructionCountCI/AFP/SVE256/Secondary_REPNE.json b/unittests/InstructionCountCI/AFP/SVE256/Secondary_REPNE.json index b08e90a3b..d80ed255e 100644 --- a/unittests/InstructionCountCI/AFP/SVE256/Secondary_REPNE.json +++ b/unittests/InstructionCountCI/AFP/SVE256/Secondary_REPNE.json @@ -130,71 +130,56 @@ ] }, "cmpsd xmm0, xmm1, 0": { - "ExpectedInstructionCount": 4, + "ExpectedInstructionCount": 1, "Comment": [ "0xf2 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", - "fcmeq d2, d17, d16", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "fcmeq d16, d17, d16" ] }, "cmpsd xmm0, xmm1, 1": { - "ExpectedInstructionCount": 4, + "ExpectedInstructionCount": 1, "Comment": [ "0xf2 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", - "fcmgt d2, d17, d16", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "fcmgt d16, d17, d16" ] }, "cmpsd xmm0, xmm1, 2": { - "ExpectedInstructionCount": 4, + "ExpectedInstructionCount": 1, "Comment": [ "0xf2 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", - "fcmge d2, d17, d16", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "fcmge d16, d17, d16" ] }, "cmpsd xmm0, xmm1, 3": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 6, "Comment": [ "0xf2 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", "fcmge d0, d16, d17", "fcmgt d1, d17, d16", "orr v0.8b, v0.8b, v1.8b", "mvn v0.8b, v0.8b", "ptrue p0.d, vl1", - "mov z2.d, p0/m, z0.d", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "mov z16.d, p0/m, z0.d" ] }, "cmpsd xmm0, xmm1, 4": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 4, "Comment": [ "0xf2 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", "fcmeq d0, d17, d16", "mvn v0.8b, v0.8b", "ptrue p0.d, vl1", - "mov z2.d, p0/m, z0.d", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "mov z16.d, p0/m, z0.d" ] }, "cmpsd xmm0, xmm1, 5": { @@ -228,19 +213,16 @@ ] }, "cmpsd xmm0, xmm1, 7": { - "ExpectedInstructionCount": 8, + "ExpectedInstructionCount": 5, "Comment": [ "0xf2 0x0f 0xc2" ], "ExpectedArm64ASM": [ - "mov z2.d, z16.d", "fcmge d0, d16, d17", "fcmgt d1, d17, d16", "orr v0.8b, v0.8b, v1.8b", "ptrue p0.d, vl1", - "mov z2.d, p0/m, z0.d", - "mov z1.q, q2", - "mov z16.b, p6/m, z1.b" + "mov z16.d, p0/m, z0.d" ] } }