diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index f50a2211e..9352a7067 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -3344,27 +3344,25 @@ OrderedNode* OpDispatchBuilder::PMADDUBSWOpImpl(OpcodeArgs, const X86Tables::Dec return _VSQXTN(Size * 2, 4, ResAdd); } + // V{U,S}XTL{,2}/ and VUnZip{,2} can be optimized in this solution to save about one instruction. + // We can up-front zero extend and sign extend the elements in-place. + // This means extracting even and odd elements up-front so the unzips aren't required. + // Requires implementing IR ops for BIC (vector, immediate) although. + // Src1 is unsigned auto Src1_16b_L = _VUXTL(Size, 1, Src1); // [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] - auto Src1_16b_H = _VUXTL2(Size, 1, Src1); // Offset to +64bits [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + auto Src2_16b_L = _VSXTL(Size, 1, Src2); // [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + auto ResMul_L = _VSMul(Size, 2, Src1_16b_L, Src2_16b_L); // Src2 is signed - auto Src2_16b_L = _VSXTL(Size, 1, Src2); // [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + auto Src1_16b_H = _VUXTL2(Size, 1, Src1); // Offset to +64bits [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] auto Src2_16b_H = _VSXTL2(Size, 1, Src2); // Offset to +64bits [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + auto ResMul_L_H = _VSMul(Size, 2, Src1_16b_H, Src2_16b_H); - auto ResMul_L = _VSMull(Size, 2, Src1_16b_L, Src2_16b_L); - auto ResMul_L_H = _VSMull2(Size, 2, Src1_16b_L, Src2_16b_L); + auto TmpZip1 = _VUnZip(Size, 2, ResMul_L, ResMul_L_H); + auto TmpZip2 = _VUnZip2(Size, 2, ResMul_L, ResMul_L_H); - auto ResMul_H = _VSMull(Size, 2, Src1_16b_H, Src2_16b_H); - auto ResMul_H_H = _VSMull2(Size, 2, Src1_16b_H, Src2_16b_H); - - // Now add pairwise across the vector - auto ResAdd_L = _VAddP(Size, 4, ResMul_L, ResMul_L_H); - auto ResAdd_H = _VAddP(Size, 4, ResMul_H, ResMul_H_H); - - // Add saturate back down to 16bit - OrderedNode *Res = _VSQXTN(Size, 4, ResAdd_L); - return _VSQXTN2(Size, 4, Res, ResAdd_H); + return _VSQAdd(Size, 2, TmpZip1, TmpZip2); } void OpDispatchBuilder::PMADDUBSW(OpcodeArgs) { diff --git a/unittests/InstructionCountCI/H0F38.json b/unittests/InstructionCountCI/H0F38.json index db3ec0d40..2485da229 100644 --- a/unittests/InstructionCountCI/H0F38.json +++ b/unittests/InstructionCountCI/H0F38.json @@ -127,26 +127,25 @@ ] }, "pmaddubsw xmm0, xmm1": { - "ExpectedInstructionCount": 14, - "Optimal": "Unknown", + "ExpectedInstructionCount": 9, + "Optimal": "No", "Comment": [ + "{u,s}xtl{,2} and uzp{1,2} can be more optimal", + "Up-front zero extend and sign extend the elements in place", + "This allows extracting even and odd elements up-front so we don't need the unzips at the end", + "Requires implementing IR ops for BIC (vector, immediate)", "0x66 0x0f 0x38 0x04" ], "ExpectedArm64ASM": [ "uxtl v4.8h, v16.8b", + "sxtl v5.8h, v17.8b", + "mul v4.8h, v4.8h, v5.8h", "uxtl2 v5.8h, v16.16b", - "sxtl v6.8h, v17.8b", - "sxtl2 v7.8h, v17.16b", - "smull v8.4s, v4.4h, v6.4h", - "smull2 v4.4s, v4.8h, v6.8h", - "smull v6.4s, v5.4h, v7.4h", - "smull2 v5.4s, v5.8h, v7.8h", - "addp v4.4s, v8.4s, v4.4s", - "addp v5.4s, v6.4s, v5.4s", - "sqxtn v4.4h, v4.4s", - "mov v0.16b, v4.16b", - "sqxtn2 v0.8h, v5.4s", - "mov v16.16b, v0.16b" + "sxtl2 v6.8h, v17.16b", + "mul v5.8h, v5.8h, v6.8h", + "uzp1 v6.8h, v4.8h, v5.8h", + "uzp2 v4.8h, v4.8h, v5.8h", + "sqadd v16.8h, v6.8h, v4.8h" ] }, "phsubw mm0, mm1": { @@ -1280,4 +1279,4 @@ ] } } -} \ No newline at end of file +} diff --git a/unittests/InstructionCountCI/VEX_map2.json b/unittests/InstructionCountCI/VEX_map2.json index 51eb39436..179625ae1 100644 --- a/unittests/InstructionCountCI/VEX_map2.json +++ b/unittests/InstructionCountCI/VEX_map2.json @@ -191,7 +191,7 @@ ] }, "vpmaddubsw xmm0, xmm1, xmm2": { - "ExpectedInstructionCount": 18, + "ExpectedInstructionCount": 13, "Optimal": "No", "Comment": [ "Map 2 0b01 0x04 128-bit" @@ -200,25 +200,20 @@ "mov z4.d, p7/m, z17.d", "mov z5.d, p7/m, z18.d", "uxtl v6.8h, v4.8b", - "uxtl2 v4.8h, v4.16b", "sxtl v7.8h, v5.8b", + "mul v6.8h, v6.8h, v7.8h", + "uxtl2 v4.8h, v4.16b", "sxtl2 v5.8h, v5.16b", - "smull v8.4s, v6.4h, v7.4h", - "smull2 v6.4s, v6.8h, v7.8h", - "smull v7.4s, v4.4h, v5.4h", - "smull2 v4.4s, v4.8h, v5.8h", - "addp v5.4s, v8.4s, v6.4s", - "addp v4.4s, v7.4s, v4.4s", - "sqxtn v5.4h, v5.4s", - "mov v0.16b, v5.16b", - "sqxtn2 v0.8h, v4.4s", - "mov v4.16b, v0.16b", + "mul v4.8h, v4.8h, v5.8h", + "uzp1 v5.8h, v6.8h, v4.8h", + "uzp2 v4.8h, v6.8h, v4.8h", + "sqadd v4.8h, v5.8h, v4.8h", "mov v4.16b, v4.16b", "mov z16.d, p7/m, z4.d" ] }, "vpmaddubsw ymm0, ymm1, ymm2": { - "ExpectedInstructionCount": 35, + "ExpectedInstructionCount": 12, "Optimal": "No", "Comment": [ "Map 2 0b01 0x04 256-bit" @@ -227,37 +222,14 @@ "mov z4.d, p7/m, z17.d", "mov z5.d, p7/m, z18.d", "uunpklo z6.h, z4.b", - "uunpkhi z4.h, z4.b", "sunpklo z7.h, z5.b", + "mul z6.h, z6.h, z7.h", + "uunpkhi z4.h, z4.b", "sunpkhi z5.h, z5.b", - "smullb z0.s, z6.h, z7.h", - "smullt z1.s, z6.h, z7.h", - "zip1 z8.s, z0.s, z1.s", - "smullb z0.s, z6.h, z7.h", - "smullt z1.s, z6.h, z7.h", - "zip2 z6.s, z0.s, z1.s", - "smullb z0.s, z4.h, z5.h", - "smullt z1.s, z4.h, z5.h", - "zip1 z7.s, z0.s, z1.s", - "smullb z0.s, z4.h, z5.h", - "smullt z1.s, z4.h, z5.h", - "zip2 z4.s, z0.s, z1.s", - "movprfx z0, z8", - "addp z0.s, p7/m, z0.s, z6.s", - "uzp1 z5.s, z0.s, z0.s", - "uzp2 z1.s, z0.s, z0.s", - "splice z5.d, p6, z5.d, z1.d", - "movprfx z0, z7", - "addp z0.s, p7/m, z0.s, z4.s", - "uzp1 z4.s, z0.s, z0.s", - "uzp2 z1.s, z0.s, z0.s", - "splice z4.d, p6, z4.d, z1.d", - "sqxtnb z5.h, z5.s", - "uzp1 z5.h, z5.h, z5.h", - "sqxtnb z1.h, z4.s", - "uzp1 z1.h, z1.h, z1.h", - "movprfx z4, z5", - "splice z4.h, p6, z4.h, z1.h", + "mul z4.h, z4.h, z5.h", + "uzp1 z5.h, z6.h, z4.h", + "uzp2 z4.h, z6.h, z4.h", + "sqadd z4.h, z5.h, z4.h", "mov z16.d, p7/m, z4.d" ] },