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" ] } }