diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index a9c76752e..27f64dad1 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -4026,15 +4026,131 @@ void OpDispatchBuilder::AVXVectorRound<8, true>(OpcodeArgs); template void OpDispatchBuilder::VectorBlend(OpcodeArgs) { + const auto DstSize = GetDstSize(Op); + LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here"); uint8_t Select = Op->Src[1].Data.Literal.Value; OrderedNode *Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags, -1); OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); - for (size_t i = 0; i < (16 / ElementSize); ++i) { - if (Select & (1 << i)) { - // This could be optimized if it becomes costly - Dest = _VInsElement(16, ElementSize, i, i, Dest, Src); + + if constexpr (ElementSize == 4) { + Select &= 0b1111; + switch (Select) { + case 0b0000: + // No-op + return; + case 0b0001: + // Dest[31:0] = Src[31:0] + Dest = _VInsElement(DstSize, ElementSize, 0, 0, Dest, Src); + break; + case 0b0010: + // Dest[63:32] = Src[63:32] + Dest = _VInsElement(DstSize, ElementSize, 1, 1, Dest, Src); + break; + case 0b0011: + // Dest[31:0] = Src[31:0] + // Dest[63:32] = Src[63:32] + Dest = _VInsElement(DstSize, 8, 0, 0, Dest, Src); + break; + case 0b0100: + // Dest[95:64] = Src[95:64] + Dest = _VInsElement(DstSize, ElementSize, 2, 2, Dest, Src); + break; + case 0b0101: + // Dest[31:0] = Src[31:0] + // Dest[95:64] = Src[95:64] + Dest = _VInsElement(DstSize, ElementSize, 0, 0, Dest, Src); + Dest = _VInsElement(DstSize, ElementSize, 2, 2, Dest, Src); + break; + case 0b0110: + // Dest[63:32] = Src[63:32] + // Dest[95:64] = Src[95:64] + Dest = _VInsElement(DstSize, ElementSize, 1, 1, Dest, Src); + Dest = _VInsElement(DstSize, ElementSize, 2, 2, Dest, Src); + break; + case 0b0111: + // Dest[31:0] = Src[31:0] + // Dest[63:32] = Src[63:32] + // Dest[95:64] = Src[95:64] + Dest = _VInsElement(DstSize, 8, 0, 0, Dest, Src); + Dest = _VInsElement(DstSize, ElementSize, 2, 2, Dest, Src); + break; + case 0b1000: + // Dest[127:96] = Src[127:96] + Dest = _VInsElement(DstSize, ElementSize, 3, 3, Dest, Src); + break; + case 0b1001: + // Dest[31:0] = Src[31:0] + // Dest[127:96] = Src[127:96] + Dest = _VInsElement(DstSize, ElementSize, 0, 0, Dest, Src); + Dest = _VInsElement(DstSize, ElementSize, 3, 3, Dest, Src); + break; + case 0b1010: + // Dest[63:32] = Src[63:32] + // Dest[127:96] = Src[127:96] + Dest = _VInsElement(DstSize, ElementSize, 1, 1, Dest, Src); + Dest = _VInsElement(DstSize, ElementSize, 3, 3, Dest, Src); + break; + case 0b1011: + // Dest[31:0] = Src[31:0] + // Dest[63:32] = Src[63:32] + // Dest[95:64] = Src[95:64] + Dest = _VInsElement(DstSize, 8, 0, 0, Dest, Src); + Dest = _VInsElement(DstSize, ElementSize, 3, 3, Dest, Src); + break; + case 0b1100: + // Dest[95:64] = Src[95:64] + // Dest[127:96] = Src[127:96] + Dest = _VInsElement(DstSize, 8, 1, 1, Dest, Src); + break; + case 0b1101: + // Dest[31:0] = Src[31:0] + // Dest[95:64] = Src[95:64] + // Dest[127:96] = Src[127:96] + Dest = _VInsElement(DstSize, ElementSize, 0, 0, Dest, Src); + Dest = _VInsElement(DstSize, 8, 1, 1, Dest, Src); + break; + case 0b1110: + // Dest[63:32] = Src[63:32] + // Dest[95:64] = Src[95:64] + // Dest[127:96] = Src[127:96] + Dest = _VInsElement(DstSize, ElementSize, 1, 1, Dest, Src); + Dest = _VInsElement(DstSize, 8, 1, 1, Dest, Src); + break; + case 0b1111: + // Copy + Dest = Src; + break; + default: break; + } + } + else if constexpr (ElementSize == 8) { + Select &= 0b11; + switch (Select) { + case 0b00: + // No-op + return; + case 0b01: + // Dest[63:0] = Src[63:0] + Dest = _VInsElement(DstSize, ElementSize, 0, 0, Dest, Src); + break; + case 0b10: + // Dest[127:64] = Src[127:64] + Dest = _VInsElement(DstSize, ElementSize, 1, 1, Dest, Src); + break; + case 0b11: + // Copy + Dest = Src; + break; + } + } + else { + for (size_t i = 0; i < (16 / ElementSize); ++i) { + if (Select & (1 << i)) { + // This could be optimized if it becomes costly + Dest = _VInsElement(16, ElementSize, i, i, Dest, Src); + } } } StoreResult(FPRClass, Op, Dest, -1); diff --git a/unittests/InstructionCountCI/H0F3A.json b/unittests/InstructionCountCI/H0F3A.json index 0031f6349..8dd9b1961 100644 --- a/unittests/InstructionCountCI/H0F3A.json +++ b/unittests/InstructionCountCI/H0F3A.json @@ -280,15 +280,12 @@ ] }, "blendps xmm0, xmm1, 0000b": { - "ExpectedInstructionCount": 2, - "Optimal": "No", + "ExpectedInstructionCount": 0, + "Optimal": "Yes", "Comment": [ "0x66 0x0f 0x3a 0x0c" ], - "ExpectedArm64ASM": [ - "mov v2.16b, v16.16b", - "mov v16.16b, v2.16b" - ] + "ExpectedArm64ASM": [] }, "blendps xmm0, xmm1, 0001b": { "ExpectedInstructionCount": 1, @@ -311,18 +308,13 @@ ] }, "blendps xmm0, xmm1, 0011b": { - "ExpectedInstructionCount": 6, - "Optimal": "No", + "ExpectedInstructionCount": 1, + "Optimal": "Yes", "Comment": [ "0x66 0x0f 0x3a 0x0c" ], "ExpectedArm64ASM": [ - "mov v0.16b, v16.16b", - "mov v0.s[0], v17.s[0]", - "mov v2.16b, v0.16b", - "mov v0.16b, v2.16b", - "mov v0.s[1], v17.s[1]", - "mov v16.16b, v0.16b" + "mov v16.d[0], v17.d[0]" ] }, "blendps xmm0, xmm1, 0100b": { @@ -366,16 +358,15 @@ ] }, "blendps xmm0, xmm1, 0111b": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 6, "Optimal": "No", "Comment": [ "0x66 0x0f 0x3a 0x0c" ], "ExpectedArm64ASM": [ "mov v0.16b, v16.16b", - "mov v0.s[0], v17.s[0]", + "mov v0.d[0], v17.d[0]", "mov v2.16b, v0.16b", - "mov v2.s[1], v17.s[1]", "mov v0.16b, v2.16b", "mov v0.s[2], v17.s[2]", "mov v16.16b, v0.16b" @@ -422,22 +413,6 @@ ] }, "blendps xmm0, xmm1, 1011b": { - "ExpectedInstructionCount": 7, - "Optimal": "No", - "Comment": [ - "0x66 0x0f 0x3a 0x0c" - ], - "ExpectedArm64ASM": [ - "mov v0.16b, v16.16b", - "mov v0.s[0], v17.s[0]", - "mov v2.16b, v0.16b", - "mov v2.s[1], v17.s[1]", - "mov v0.16b, v2.16b", - "mov v0.s[3], v17.s[3]", - "mov v16.16b, v0.16b" - ] - }, - "blendps xmm0, xmm1, 1100b": { "ExpectedInstructionCount": 6, "Optimal": "No", "Comment": [ @@ -445,15 +420,25 @@ ], "ExpectedArm64ASM": [ "mov v0.16b, v16.16b", - "mov v0.s[2], v17.s[2]", + "mov v0.d[0], v17.d[0]", "mov v2.16b, v0.16b", "mov v0.16b, v2.16b", "mov v0.s[3], v17.s[3]", "mov v16.16b, v0.16b" ] }, + "blendps xmm0, xmm1, 1100b": { + "ExpectedInstructionCount": 1, + "Optimal": "Yes", + "Comment": [ + "0x66 0x0f 0x3a 0x0c" + ], + "ExpectedArm64ASM": [ + "mov v16.d[1], v17.d[1]" + ] + }, "blendps xmm0, xmm1, 1101b": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 6, "Optimal": "No", "Comment": [ "0x66 0x0f 0x3a 0x0c" @@ -462,14 +447,13 @@ "mov v0.16b, v16.16b", "mov v0.s[0], v17.s[0]", "mov v2.16b, v0.16b", - "mov v2.s[2], v17.s[2]", "mov v0.16b, v2.16b", - "mov v0.s[3], v17.s[3]", + "mov v0.d[1], v17.d[1]", "mov v16.16b, v0.16b" ] }, "blendps xmm0, xmm1, 1110b": { - "ExpectedInstructionCount": 7, + "ExpectedInstructionCount": 6, "Optimal": "No", "Comment": [ "0x66 0x0f 0x3a 0x0c" @@ -478,39 +462,28 @@ "mov v0.16b, v16.16b", "mov v0.s[1], v17.s[1]", "mov v2.16b, v0.16b", - "mov v2.s[2], v17.s[2]", "mov v0.16b, v2.16b", - "mov v0.s[3], v17.s[3]", + "mov v0.d[1], v17.d[1]", "mov v16.16b, v0.16b" ] }, "blendps xmm0, xmm1, 1111b": { - "ExpectedInstructionCount": 8, - "Optimal": "No", + "ExpectedInstructionCount": 1, + "Optimal": "Yes", "Comment": [ "0x66 0x0f 0x3a 0x0c" ], "ExpectedArm64ASM": [ - "mov v0.16b, v16.16b", - "mov v0.s[0], v17.s[0]", - "mov v2.16b, v0.16b", - "mov v2.s[1], v17.s[1]", - "mov v2.s[2], v17.s[2]", - "mov v0.16b, v2.16b", - "mov v0.s[3], v17.s[3]", - "mov v16.16b, v0.16b" + "mov v16.16b, v17.16b" ] }, "blendpd xmm0, xmm1, 00b": { - "ExpectedInstructionCount": 2, - "Optimal": "No", + "ExpectedInstructionCount": 0, + "Optimal": "Yes", "Comment": [ "0x66 0x0f 0x3a 0x0d" ], - "ExpectedArm64ASM": [ - "mov v2.16b, v16.16b", - "mov v16.16b, v2.16b" - ] + "ExpectedArm64ASM": [] }, "blendpd xmm0, xmm1, 01b": { "ExpectedInstructionCount": 1, @@ -533,18 +506,13 @@ ] }, "blendpd xmm0, xmm1, 11b": { - "ExpectedInstructionCount": 6, - "Optimal": "No", + "ExpectedInstructionCount": 1, + "Optimal": "Yes", "Comment": [ "0x66 0x0f 0x3a 0x0d" ], "ExpectedArm64ASM": [ - "mov v0.16b, v16.16b", - "mov v0.d[0], v17.d[0]", - "mov v2.16b, v0.16b", - "mov v0.16b, v2.16b", - "mov v0.d[1], v17.d[1]", - "mov v16.16b, v0.16b" + "mov v16.16b, v17.16b" ] }, "pblendw xmm0, xmm1, 00000000b": {