mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-17 20:00:36 +02:00
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:
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in new issue
Block a user