[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.
This commit is contained in:
LC committed 2026-06-21 02:27:53 -04:00
1 parent 27acbba52e
commit b40f9db735
3 files changed
+38 -61

No files matched your search

@@ -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) {
@@ -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"
]
}
}
@@ -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"
]
}
}