From d5c3036bc20a6bc4ec6db3d3ac563a2e6344e20f Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 12 Sep 2023 19:23:59 -0700 Subject: [PATCH 1/4] JITx86: Fixes VREV64 with 32-bit element size. This has been incorrect since it has been implemented. Noticed when implementing optimizations. --- FEXCore/Source/Interface/Core/JIT/x86_64/VectorOps.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/FEXCore/Source/Interface/Core/JIT/x86_64/VectorOps.cpp b/FEXCore/Source/Interface/Core/JIT/x86_64/VectorOps.cpp index 676be025b..0e86c111a 100644 --- a/FEXCore/Source/Interface/Core/JIT/x86_64/VectorOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/x86_64/VectorOps.cpp @@ -4914,10 +4914,10 @@ DEF_OP(VRev64) { } else if (OpSize == Core::CPUState::XMM_SSE_REG_SIZE) { vpshufd(Dst, Vector, - (0b11 << 0) | - (0b10 << 2) | - (0b01 << 4) | - (0b00 << 6)); + (0b01 << 0) | + (0b00 << 2) | + (0b11 << 4) | + (0b10 << 6)); } else { vpshufd(Dst, Vector, From 3f1979286f111886da356e864b9f0fe990b4d67a Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 12 Sep 2023 19:24:39 -0700 Subject: [PATCH 2/4] OpcodeDispatcher: Optimize a bunch of shufps variants Hits a whole bunch of common cases, most of which then emit optimal code generation. Two cases that use VInsElement hit the RA quirk where the SRA destination is dead but RA doesn't see it, so it ends up doing a couple moves. If RA gets fixed then those two moves will go away. There are definitely still cases that we could emit more optimal code. Additionally we could implement a TBL2 IR operation to do a LUT approach for ones we don't cover. Problem with implementing a TBL2 ir operation is that we have no way to ensure registers are sequential so we would need to always do moves ```asm ldr v2, mov v0, v16 mov v1, v18 tbl v16.16b, { v0.16b, v1.16b }, v2.16b ``` Which to be fair isn't terrible, and if we're lucky that the guest uses sequential registers we can naturally get the more optimal code path. Ideally our RA could push some operations in to sequential registers but that's not possible currently. I'll do a follow-up PR that implements TBL2. --- .../Core/OpcodeDispatcher/Vector.cpp | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 7e971f989..058a4194e 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -1262,6 +1262,135 @@ OrderedNode* OpDispatchBuilder::SHUFOpImpl(OpcodeArgs, size_t ElementSize, Shuffle >>= ShiftAmount; } } else { + if (ElementSize == 4) { + // We can shuffle optimally in a lot of cases. + // TODO: We can optimize more of these cases. + switch (Shuffle) { + case 0b01'00'01'00: + // Combining of low 64-bits. + // Dest[63:0] = Src1[63:0] + // Dest[127:64] = Src2[63:0] + return _VZip(DstSize, 8, Src1Node, Src2Node); + case 0b11'10'11'10: + // Combining of high 64-bits. + // Dest[63:0] = Src1[127:64] + // Dest[127:64] = Src2[127:64] + return _VZip2(DstSize, 8, Src1Node, Src2Node); + case 0b11'10'01'00: + // Mixing Low and high elements + // Dest[63:0] = Src1[63:0] + // Dest[127:64] = Src2[127:64] + return _VInsElement(DstSize, 8, 1, 1, Src1Node, Src2Node); + case 0b01'00'11'10: + // Mixing Low and high elements, inverse of above + // Dest[63:0] = Src1[127:64] + // Dest[127:64] = Src2[63:0] + return _VExtr(DstSize, 1, Src2Node, Src1Node, 8); + case 0b10'00'10'00: + // Mixing even elements. + // Dest[31:0] = Src1[31:0] + // Dest[63:32] = Src1[95:64] + // Dest[95:64] = Src2[31:0] + // Dest[127:96] = Src2[95:64] + return _VUnZip(DstSize, ElementSize, Src1Node, Src2Node); + case 0b11'01'11'01: + // Mixing odd elements. + // Dest[31:0] = Src1[63:32] + // Dest[63:32] = Src1[127:96] + // Dest[95:64] = Src2[63:32] + // Dest[127:96] = Src2[127:96] + return _VUnZip2(DstSize, ElementSize, Src1Node, Src2Node); + case 0b11'10'00'00: + case 0b11'10'01'01: + case 0b11'10'10'10: + case 0b11'10'11'11: { + // Bottom elements duplicated, Top 64-bits inserted + auto DupSrc1 = _VDupElement(DstSize, ElementSize, Src1Node, Shuffle & 0b11); + return _VZip2(DstSize, 8, DupSrc1, Src2Node); + } + case 0b01'00'00'00: + case 0b01'00'01'01: + case 0b01'00'10'10: + case 0b01'00'11'11: { + // Bottom elements duplicated, Bottom 64-bits inserted + auto DupSrc1 = _VDupElement(DstSize, ElementSize, Src1Node, Shuffle & 0b11); + return _VZip(DstSize, 8, DupSrc1, Src2Node); + } + case 0b00'00'01'00: + case 0b01'01'01'00: + case 0b10'10'01'00: + case 0b11'11'01'00: { + // Top elements duplicated, Bottom 64-bits inserted + auto DupSrc2 = _VDupElement(DstSize, ElementSize, Src2Node, (Shuffle >> 4) & 0b11); + return _VZip(DstSize, 8, Src1Node, DupSrc2); + } + case 0b00'00'11'10: + case 0b01'01'11'10: + case 0b10'10'11'10: + case 0b11'11'11'10: { + // Top elements duplicated, Top 64-bits inserted + auto DupSrc2 = _VDupElement(DstSize, ElementSize, Src2Node, (Shuffle >> 4) & 0b11); + return _VZip2(DstSize, 8, Src1Node, DupSrc2); + } + case 0b01'00'01'11: { + // TODO: This doesn't generate optimal code. + // RA doesn't understand that Src1Node is dead after VInsElement due to SRA class differences. + // With RA fixes this would be 2 instructions. + // Odd elements inverted, Low 64-bits inserted + Src1Node = _VInsElement(DstSize, 4, 0, 3, Src1Node, Src1Node); + return _VZip(DstSize, 8, Src1Node, Src2Node); + } + case 0b11'10'01'11: { + // TODO: This doesn't generate optimal code. + // RA doesn't understand that Src1Node is dead after VInsElement due to SRA class differences. + // With RA fixes this would be 2 instructions. + // Odd elements inverted, Top 64-bits inserted + Src1Node = _VInsElement(DstSize, 4, 0, 3, Src1Node, Src1Node); + return _VInsElement(DstSize, 8, 1, 1, Src1Node, Src2Node); + } + case 0b01'00'00'01: { + // Lower 32-bit elements inverted, low 64-bits inserted + Src1Node = _VRev64(DstSize, 4, Src1Node); + return _VZip(DstSize, 8, Src1Node, Src2Node); + } + case 0b11'10'00'01: { + // TODO: This doesn't generate optimal code. + // RA doesn't understand that Src1Node is dead after VInsElement due to SRA class differences. + // With RA fixes this would be 2 instructions. + // Lower 32-bit elements inverted, Top 64-bits inserted + Src1Node = _VRev64(DstSize, 4, Src1Node); + return _VInsElement(DstSize, 8, 1, 1, Src1Node, Src2Node); + } + case 0b00'00'00'00: + case 0b00'00'01'01: + case 0b00'00'10'10: + case 0b00'00'11'11: + case 0b01'01'00'00: + case 0b01'01'01'01: + case 0b01'01'10'10: + case 0b01'01'11'11: + case 0b10'10'00'00: + case 0b10'10'01'01: + case 0b10'10'10'10: + case 0b10'10'11'11: + case 0b11'11'00'00: + case 0b11'11'01'01: + case 0b11'11'10'10: + case 0b11'11'11'11: + { + // Duplicate element in upper and lower across each 64-bit segment. + auto DupSrc1 = _VDupElement(DstSize, ElementSize, Src1Node, Shuffle & 0b11); + auto DupSrc2 = _VDupElement(DstSize, ElementSize, Src2Node, (Shuffle >> 4) & 0b11); + return _VZip(DstSize, 8, DupSrc1, DupSrc2); + } + default: + // Intentional doing nothing. + // Uncomment if you want to see remaining fallthrough in the output logs. + //LogMan::Msg::DFmt("shufps: 0x{:x}", Shuffle); + break; + } + } + for (uint8_t Element = 0; Element < NumElements; ++Element) { const auto SrcIndex = Shuffle & SelectionMask; Dest = _VInsElement(DstSize, ElementSize, Element, SrcIndex, Dest, Srcs[Element]); From e37cef82838d70a9b9db7a82d2819d91d3530e47 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 12 Sep 2023 19:32:14 -0700 Subject: [PATCH 3/4] unittests: Implement shufps optimization test Tests all current forms of shufps optimizations. --- .../ASM/Secondary/shufps_optimization.asm | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 unittests/ASM/Secondary/shufps_optimization.asm diff --git a/unittests/ASM/Secondary/shufps_optimization.asm b/unittests/ASM/Secondary/shufps_optimization.asm new file mode 100644 index 000000000..9bd622772 --- /dev/null +++ b/unittests/ASM/Secondary/shufps_optimization.asm @@ -0,0 +1,70 @@ +%ifdef CONFIG +{ + "RegData": { + "XMM0": ["0x4054c664c2f837b5", "0x4044836d86ec17ec"], + "XMM1": ["0x402a1e1c58255b03", "0x4035fe425aee6320"], + "XMM2": ["0x401568e0c9d9d346", "0x40154b7d41743e96"], + "XMM3": ["0x40154b7d41743e96", "0x403d075a31a4bdba"], + "XMM4": ["0xbd66277c31a4bdba", "0x4ea4a8c17ebaf102"], + "XMM5": ["0x4056d74040334ec1", "0x40497b13404439b5"], + "XMM6": ["0x404439b5404439b5", "0x4037f9ca18bd6627"], + "XMM7": ["0x4037f9ca4037f9ca", "0x403839b866e43aa8"], + "XMM8": ["0x403839b8403839b8", "0x4058bc1f212d7732"], + "XMM9": ["0x4058bc1f212d7732", "0xa10e0221a10e0221"], + "XMM10": ["0x4058defb00bcbe62", "0x9eecbfb19eecbfb1"], + "XMM11": ["0x40503e3c4052997f", "0x40395a6bf8769ec3"], + "XMM12": ["0x40419d2240395a6b", "0x40177e28240b7803"], + "XMM13": ["0x240b780340177e28", "0x404a03c74fb549f9"], + "XMM14": ["0x9f16b11c40408402", "0x404d31595feda661"], + "XMM15": ["0x5feda6615feda661", "0x7aa25d8d7aa25d8d"] + } +} +%endif + +movaps xmm0, [rel .data + 16 * 0] +movaps xmm1, [rel .data + 16 * 1] + +movaps xmm2, [rel .data + 16 * 2] +movaps xmm3, [rel .data + 16 * 3] + +movaps xmm4, [rel .data + 16 * 4] +movaps xmm5, [rel .data + 16 * 5] + +movaps xmm6, [rel .data + 16 * 6] +movaps xmm7, [rel .data + 16 * 7] + +movaps xmm8, [rel .data + 16 * 8] +movaps xmm9, [rel .data + 16 * 9] + +movaps xmm10, [rel .data + 16 * 10] +movaps xmm11, [rel .data + 16 * 11] + +movaps xmm12, [rel .data + 16 * 12] +movaps xmm13, [rel .data + 16 * 13] + +movaps xmm14, [rel .data + 16 * 14] +movaps xmm15, [rel .data + 16 * 15] + +shufps xmm0, xmm1, 01000100b +shufps xmm1, xmm2, 11101110b +shufps xmm2, xmm3, 11100100b +shufps xmm3, xmm4, 01001110b +shufps xmm4, xmm5, 10001000b +shufps xmm5, xmm6, 11011101b +shufps xmm6, xmm7, 11100101b +shufps xmm7, xmm8, 11101111b +shufps xmm8, xmm9, 01001111b +shufps xmm9, xmm10, 00000100b +shufps xmm10, xmm11, 00001110b +shufps xmm11, xmm12, 11100111b +shufps xmm12, xmm13, 01000111b +shufps xmm13, xmm14, 11100001b +shufps xmm14, xmm15, 01000001b +shufps xmm15, [rel .data + 16 * 16], 0 + +hlt + +align 16 +; 512bytes of random data +.data: +dq 83.0999,69.50512,41.02678,13.05881,5.35242,21.9932,9.67383,5.32372,29.02872,66.50151,19.30764,91.3633,40.45086,50.96153,32.64489,23.97574,90.64316,24.22547,98.9394,91.21715,90.80143,99.48407,64.97245,74.39838,35.22761,25.35321,5.8732,90.19956,33.03133,52.02952,58.38554,10.17531,47.84703,84.04831,90.02965,65.81329,96.27991,6.64479,25.58971,95.00694,88.1929,37.16964,49.52602,10.27223,77.70605,20.21439,9.8056,41.29389,15.4071,57.54286,9.61117,55.54302,52.90745,4.88086,72.52882,3.0201,56.55091,71.22749,61.84736,88.74295,47.72641,24.17404,33.70564,96.71303 From ea8d63350a8ad5df8321c26d2521cfb38904b2ce Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 12 Sep 2023 19:32:38 -0700 Subject: [PATCH 4/4] InstCountCI: Updates for optimized shufps --- unittests/InstructionCountCI/Secondary.json | 548 ++++++++++++++++++-- unittests/InstructionCountCI/VEX_map1.json | 13 +- 2 files changed, 512 insertions(+), 49 deletions(-) diff --git a/unittests/InstructionCountCI/Secondary.json b/unittests/InstructionCountCI/Secondary.json index abd7c5990..79e9c3040 100644 --- a/unittests/InstructionCountCI/Secondary.json +++ b/unittests/InstructionCountCI/Secondary.json @@ -3611,35 +3611,523 @@ "uxth x4, w20" ] }, - "shufps xmm0, xmm1, 0": { - "ExpectedInstructionCount": 8, + "shufps xmm0, xmm1, 01000100b": { + "ExpectedInstructionCount": 1, + "Optimal": "Yes", + "Comment": [ + "Dst[63:0] = Src1[63:0]", + "Dest[127:64] = Src2[63:0]", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "zip1 v16.2d, v16.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11101110b": { + "ExpectedInstructionCount": 1, + "Optimal": "Yes", + "Comment": [ + "Dst[63:0] = Src1[127:64]", + "Dest[127:64] = Src2[127:64]", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "zip2 v16.2d, v16.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11100100b": { + "ExpectedInstructionCount": 1, + "Optimal": "Yes", + "Comment": [ + "Dst[63:0] = Src1[63:0]", + "Dest[127:64] = Src2[127:64]", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "mov v16.d[1], v17.d[1]" + ] + }, + "shufps xmm0, xmm1, 01001110b": { + "ExpectedInstructionCount": 1, + "Optimal": "Yes", + "Comment": [ + "Dst[63:0] = Src1[63:0]", + "Dest[127:64] = Src2[127:64]", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "ext v16.16b, v16.16b, v17.16b, #8" + ] + }, + "shufps xmm0, xmm1, 00000000b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "dup v3.4s, v17.s[0]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 00000101b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "dup v3.4s, v17.s[0]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 00001010b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "dup v3.4s, v17.s[0]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 00001111b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "dup v3.4s, v17.s[0]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 01010000b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "dup v3.4s, v17.s[1]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 01010101b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "dup v3.4s, v17.s[1]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 01011010b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "dup v3.4s, v17.s[1]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 01011111b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "dup v3.4s, v17.s[1]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 10100000b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "dup v3.4s, v17.s[2]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 10100101b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "dup v3.4s, v17.s[2]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 10101010b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "dup v3.4s, v17.s[2]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 10101111b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "dup v3.4s, v17.s[2]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 11110000b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "dup v3.4s, v17.s[3]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 11110101b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "dup v3.4s, v17.s[3]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 11111010b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "dup v3.4s, v17.s[3]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, + "shufps xmm0, xmm1, 11100000b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "zip2 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11100101b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "zip2 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11101010b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "zip2 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11101111b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "zip2 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 01000000b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[0]", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 01000101b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[1]", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 01001010b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[2]", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 01001111b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Bottom elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 00000100b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Bottom 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[0]", + "zip1 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 01010100b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Bottom 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[1]", + "zip1 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 10100100b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Bottom 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[2]", + "zip1 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 11110100b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Bottom 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[3]", + "zip1 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 00001110b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[0]", + "zip2 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 01011110b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[1]", + "zip2 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 10101110b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[2]", + "zip2 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 11111110b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Top elements duplicated, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v17.s[3]", + "zip2 v16.2d, v16.2d, v2.2d" + ] + }, + "shufps xmm0, xmm1, 01000111b": { + "ExpectedInstructionCount": 4, "Optimal": "No", - "Comment": "0x0f 0xc6", + "Comment": [ + "odd elements inverted, Low 64-bits inserted", + "SRA quirks with RA fail to understand that v16 is dead", + "Could InsElement directly in to v16 but it does two moves instead", + "0x0f 0xc6" + ], "ExpectedArm64ASM": [ "mov v0.16b, v16.16b", - "mov v0.s[0], v16.s[0]", + "mov v0.s[0], v16.s[3]", + "mov v2.16b, v0.16b", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11100111b": { + "ExpectedInstructionCount": 6, + "Optimal": "No", + "Comment": [ + "odd elements inverted, Top 64-bits inserted", + "SRA quirks with RA fail to understand that v16 is dead", + "Could InsElement directly in to v16 but it does two moves instead", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "mov v0.16b, v16.16b", + "mov v0.s[0], v16.s[3]", "mov v2.16b, v0.16b", - "mov v2.s[1], v16.s[0]", - "mov v2.s[2], v17.s[0]", "mov v0.16b, v2.16b", - "mov v0.s[3], v17.s[0]", + "mov v0.d[1], v17.d[1]", "mov v16.16b, v0.16b" ] }, + "shufps xmm0, xmm1, 11100001b": { + "ExpectedInstructionCount": 4, + "Optimal": "Yes", + "Comment": [ + "Lower 32-bit elements inverted, Top 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "rev64 v2.4s, v16.4s", + "mov v0.16b, v2.16b", + "mov v0.d[1], v17.d[1]", + "mov v16.16b, v0.16b" + ] + }, + "shufps xmm0, xmm1, 01000001b": { + "ExpectedInstructionCount": 2, + "Optimal": "Yes", + "Comment": [ + "Lower 32-bit elements inverted, Low 64-bits inserted", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "rev64 v2.4s, v16.4s", + "zip1 v16.2d, v2.2d, v17.2d" + ] + }, + "shufps xmm0, xmm1, 11111111b": { + "ExpectedInstructionCount": 3, + "Optimal": "Yes", + "Comment": [ + "Duplicate selected element between each 64-bit segment", + "0x0f 0xc6" + ], + "ExpectedArm64ASM": [ + "dup v2.4s, v16.s[3]", + "dup v3.4s, v17.s[3]", + "zip1 v16.2d, v2.2d, v3.2d" + ] + }, "shufps xmm0, [rax], 0": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 4, "Optimal": "No", "Comment": "0x0f 0xc6", "ExpectedArm64ASM": [ "ldr q2, [x4]", - "mov v0.16b, v16.16b", - "mov v0.s[0], v16.s[0]", - "mov v3.16b, v0.16b", - "mov v3.s[1], v16.s[0]", - "mov v3.s[2], v2.s[0]", - "mov v0.16b, v3.16b", - "mov v0.s[3], v2.s[0]", - "mov v16.16b, v0.16b" + "dup v3.4s, v16.s[0]", + "dup v2.4s, v2.s[0]", + "zip1 v16.2d, v3.2d, v2.2d" ] }, "shufps xmm0, xmm1, 1": { @@ -3673,35 +4161,15 @@ "mov v16.16b, v0.16b" ] }, - "shufps xmm0, xmm1, 0xFF": { - "ExpectedInstructionCount": 8, - "Optimal": "No", - "Comment": "0x0f 0xc6", - "ExpectedArm64ASM": [ - "mov v0.16b, v16.16b", - "mov v0.s[0], v16.s[3]", - "mov v2.16b, v0.16b", - "mov v2.s[1], v16.s[3]", - "mov v2.s[2], v17.s[3]", - "mov v0.16b, v2.16b", - "mov v0.s[3], v17.s[3]", - "mov v16.16b, v0.16b" - ] - }, "shufps xmm0, [rax], 0xFF": { - "ExpectedInstructionCount": 9, + "ExpectedInstructionCount": 4, "Optimal": "No", "Comment": "0x0f 0xc6", "ExpectedArm64ASM": [ "ldr q2, [x4]", - "mov v0.16b, v16.16b", - "mov v0.s[0], v16.s[3]", - "mov v3.16b, v0.16b", - "mov v3.s[1], v16.s[3]", - "mov v3.s[2], v2.s[3]", - "mov v0.16b, v3.16b", - "mov v0.s[3], v2.s[3]", - "mov v16.16b, v0.16b" + "dup v3.4s, v16.s[3]", + "dup v2.4s, v2.s[3]", + "zip1 v16.2d, v3.2d, v2.2d" ] }, "bswap eax": { diff --git a/unittests/InstructionCountCI/VEX_map1.json b/unittests/InstructionCountCI/VEX_map1.json index fc71252e9..421701861 100644 --- a/unittests/InstructionCountCI/VEX_map1.json +++ b/unittests/InstructionCountCI/VEX_map1.json @@ -3145,7 +3145,7 @@ ] }, "vshufps xmm0, xmm1, xmm2, 00b": { - "ExpectedInstructionCount": 12, + "ExpectedInstructionCount": 7, "Optimal": "No", "Comment": [ "Map 1 0b00 0xC6 128-bit" @@ -3153,14 +3153,9 @@ "ExpectedArm64ASM": [ "mov z2.d, p7/m, z17.d", "mov z3.d, p7/m, z18.d", - "mov v0.16b, v2.16b", - "mov v0.s[0], v2.s[0]", - "mov v4.16b, v0.16b", - "mov v0.16b, v4.16b", - "mov v0.s[1], v2.s[0]", - "mov v2.16b, v0.16b", - "mov v2.s[2], v3.s[0]", - "mov v2.s[3], v3.s[0]", + "dup v2.4s, v2.s[0]", + "dup v3.4s, v3.s[0]", + "zip1 v2.2d, v2.2d, v3.2d", "mov v2.16b, v2.16b", "mov z16.d, p7/m, z2.d" ]