AVX: Lessen codegen for VMOVMSKPD

Performs the same thing as what we've done for VMOVMSKPS. Though,
the effect isn't as drastic, given we're only operating on a max
of four elements as opposed to 8.
This commit is contained in:
LC committed 2026-06-28 14:06:32 -04:00
1 parent 41fc57f46c
commit 2ec2c39cf1
2 files changed
+31 -48

No files matched your search

@@ -732,11 +732,9 @@ void OpDispatchBuilder::MOVQMMXOp(OpcodeArgs) {
void OpDispatchBuilder::MOVMSKOp(OpcodeArgs, IR::OpSize ElementSize) {
const auto Size = OpSizeFromSrc(Op);
const auto NumElements = IR::NumElements(Size, ElementSize);
Ref Src = LoadSourceFPR(Op, Op->Src[0], Op->Flags);
const auto F32Handler = [this](Ref Input, IR::OpSize VecSize) {
const auto F32Handler = [this](Ref Input, OpSize VecSize) {
// Shift all the sign bits to the bottom of their respective elements.
Input = _VUShrI(VecSize, OpSize::i32Bit, Input, 31);
// Load the specific 128-bit movmskps shift elements operator.
@@ -749,45 +747,36 @@ void OpDispatchBuilder::MOVMSKOp(OpcodeArgs, IR::OpSize ElementSize) {
return _VExtractToGPR(VecSize, OpSize::i32Bit, Input, 0);
};
if (Size == OpSize::i128Bit && ElementSize == OpSize::i64Bit) {
const auto F64Handler = [this](Ref Input, OpSize VecSize) {
// UnZip2 the 64-bit elements as 32-bit to get the sign bits closer.
// Sign bits are now in bit positions 31 and 63 after this.
Src = _VUnZip2(Size, OpSize::i32Bit, Src, Src);
Input = _VUnZip2(VecSize, OpSize::i32Bit, Input, Input);
// Extract the low 64-bits to GPR in one move.
Ref GPR = _VExtractToGPR(Size, OpSize::i64Bit, Src, 0);
Ref GPR = _VExtractToGPR(VecSize, OpSize::i64Bit, Input, 0);
// BFI the sign bit in 31 in to 62.
// Inserting the full lower 32-bits offset 31 so the sign bit ends up at offset 63.
GPR = _Bfi(OpSize::i64Bit, 32, 31, GPR, GPR);
// Shift right to only get the two sign bits we care about.
GPR = _Lshr(OpSize::i64Bit, GPR, Constant(62));
StoreResultGPR_WithOpSize(Op, Op->Dest, GPR, GetGPROpSize());
} else if (Size == OpSize::i128Bit && ElementSize == OpSize::i32Bit) {
Ref GPR = F32Handler(Src, Size);
StoreResultGPR_WithOpSize(Op, Op->Dest, GPR, GetGPROpSize());
} else if (Size == OpSize::i256Bit && ElementSize == OpSize::i32Bit) {
Ref UpperLane = _VDupElement(Size, OpSize::i128Bit, Src, 1);
return _Lshr(OpSize::i64Bit, GPR, Constant(62));
};
Ref Lower = F32Handler(Src, OpSize::i128Bit);
Ref Upper = F32Handler(UpperLane, OpSize::i128Bit);
Ref Result = _Orlshl(OpSize::i64Bit, Lower, Upper, 4);
StoreResultGPR_WithOpSize(Op, Op->Dest, Result, GetGPROpSize());
if (Size == OpSize::i128Bit) {
Ref GPR = ElementSize == OpSize::i32Bit ? F32Handler(Src, Size) : F64Handler(Src, Size);
StoreResultGPR_WithOpSize(Op, Op->Dest, GPR, GetGPROpSize());
} else {
Ref CurrentVal = Constant(0);
Ref UpperLane = _VDupElement(Size, OpSize::i128Bit, Src, 1);
Ref Result {};
for (unsigned i = 0; i < NumElements; ++i) {
// Extract the top bit of the element
Ref Tmp = _VExtractToGPR(Size, ElementSize, Src, i);
Tmp = _Bfe(ElementSize, 1, IR::OpSizeAsBits(ElementSize) - 1, Tmp);
// Shift it to the correct location and or it with the current value
if (i != 0) {
CurrentVal = _Orlshl(OpSize::i64Bit, CurrentVal, Tmp, i);
} else {
CurrentVal = Tmp;
}
if (ElementSize == OpSize::i32Bit) {
Ref Lower = F32Handler(Src, OpSize::i128Bit);
Ref Upper = F32Handler(UpperLane, OpSize::i128Bit);
Result = _Orlshl(OpSize::i64Bit, Lower, Upper, 4);
} else {
Ref Lower = F64Handler(Src, OpSize::i128Bit);
Ref Upper = F64Handler(UpperLane, OpSize::i128Bit);
Result = _Orlshl(OpSize::i64Bit, Lower, Upper, 2);
}
StoreResultGPR(Op, CurrentVal);
StoreResultGPR_WithOpSize(Op, Op->Dest, Result, GetGPROpSize());
}
}
+11 -17
View File
@@ -516,27 +516,21 @@
]
},
"vmovmskpd rax, ymm0": {
"ExpectedInstructionCount": 16,
"ExpectedInstructionCount": 10,
"Comment": [
"Map 1 0b01 0x50 256-bit"
],
"ExpectedArm64ASM": [
"mov x20, v16.d[0]",
"lsr x20, x20, #63",
"mov x21, v16.d[1]",
"lsr x21, x21, #63",
"orr x20, x20, x21, lsl #1",
"not p0.b, p7/z, p6.b",
"compact z0.d, p0, z16.d",
"mov x21, v16.d[0]",
"lsr x21, x21, #63",
"orr x20, x20, x21, lsl #2",
"not p0.b, p7/z, p6.b",
"compact z0.d, p0, z16.d",
"mov x21, v16.d[1]",
"lsr x21, x21, #63",
"orr x20, x20, x21, lsl #3",
"mov w4, w20"
"mov z2.q, z16.q[1]",
"uzp2 v3.4s, v16.4s, v16.4s",
"mov x20, v3.d[0]",
"bfi x20, x20, #31, #32",
"lsr x20, x20, #62",
"uzp2 v2.4s, v2.4s, v2.4s",
"mov x21, v2.d[0]",
"bfi x21, x21, #31, #32",
"lsr x21, x21, #62",
"orr x4, x20, x21, lsl #2"
]
},
"vsqrtps xmm0, xmm1": {